2  * Copyright (c) 2017 Apple Inc. All Rights Reserved. 
   4  * @APPLE_LICENSE_HEADER_START@ 
   6  * This file contains Original Code and/or Modifications of Original Code 
   7  * as defined in and that are subject to the Apple Public Source License 
   8  * Version 2.0 (the 'License'). You may not use this file except in 
   9  * compliance with the License. Please obtain a copy of the License at 
  10  * http://www.opensource.apple.com/apsl/ and read it before using this 
  13  * The Original Code and all software distributed under the License are 
  14  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  15  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  16  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 
  17  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  18  * Please see the License for the specific language governing rights and 
  19  * limitations under the License. 
  21  * @APPLE_LICENSE_HEADER_END@ 
  26 #include <dispatch/dispatch.h> 
  28 #include "sec_action.h" 
  30 struct sec_action_context_s 
{ 
  31         dispatch_queue_t queue
; 
  32         dispatch_source_t source
; 
  33         dispatch_block_t handler
; 
  37 static void _sec_action_event(void *ctx
); 
  38 static void _sec_action_finalize(void *ctx
); 
  43 sec_action_create_with_queue(dispatch_queue_t queue
, const char *label
, uint64_t interval
) 
  45         dispatch_source_t source
; 
  46         struct sec_action_context_s 
*context
; 
  48                 dispatch_retain(queue
); 
  50                 queue 
= dispatch_queue_create(label
, DISPATCH_QUEUE_SERIAL
); 
  52         source 
= dispatch_source_create(DISPATCH_SOURCE_TYPE_DATA_ADD
, 0, 0, queue
); 
  54         context 
= malloc(sizeof(*context
)); 
  55         context
->queue 
= queue
; 
  56         context
->source 
= source
; 
  57         context
->handler 
= NULL
; 
  58         context
->interval 
= interval
; 
  59         dispatch_set_context(source
, context
); 
  61         dispatch_source_set_event_handler_f(source
, _sec_action_event
); 
  62         dispatch_set_finalizer_f(source
, _sec_action_finalize
); 
  68 sec_action_create(const char *label
, uint64_t interval
) 
  70         return sec_action_create_with_queue(NULL
, label
, interval
); 
  74 sec_action_set_handler(sec_action_t source
, dispatch_block_t handler
) 
  76         struct sec_action_context_s 
*context
; 
  78         context 
= dispatch_get_context(source
); 
  79         context
->handler 
= Block_copy(handler
); 
  81         dispatch_activate(source
); 
  85 sec_action_perform(sec_action_t source
) 
  87         dispatch_source_merge_data(source
, 1); 
  93 _sec_action_event(void *ctx
) 
  95         struct sec_action_context_s 
*context 
= (struct sec_action_context_s 
*)ctx
; 
  97         if (context
->handler 
!= NULL
) { 
 101         // Suspend the source; resume after specified interval. 
 102         dispatch_suspend(context
->source
); 
 103         dispatch_after_f(dispatch_time(DISPATCH_TIME_NOW
, (int64_t)(context
->interval 
* NSEC_PER_SEC
)), context
->queue
, context
->source
, (dispatch_function_t
)dispatch_resume
); 
 107 _sec_action_finalize(void *ctx
) 
 109         struct sec_action_context_s 
*context 
= (struct sec_action_context_s 
*)ctx
; 
 111         dispatch_release(context
->queue
); 
 112         if (context
->handler 
!= NULL
) { 
 113                 Block_release(context
->handler
);