1/*
2 * Copyright (c) 2000-2013 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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
11 * file.
12 *
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.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24/*
25 * Timer.c
26 * - hides the details of how to get a timer callback
27 * - wraps the CFRunLoopTimer functionality
28 */
29
30/*
31 * Modification History
32 *
33 * October 26, 2001	Dieter Siegmund (dieter@apple.com)
34 * - created (based on bootp/IPConfiguration.tproj/timer.c)
35 */
36
37#include <stdlib.h>
38#include <unistd.h>
39#include <string.h>
40#include <stdio.h>
41#include <sys/types.h>
42#include <math.h>
43#include <CoreFoundation/CFRunLoop.h>
44#include "Timer.h"
45#include "myCFUtil.h"
46#include "mylog.h"
47
48
49struct Timer_s {
50    Timer_func_t *	func;
51    void *		arg1;
52    void *		arg2;
53    void *		arg3;
54    void *		rls;
55    bool		enabled;
56};
57
58
59#define USECS_PER_SEC		(1000 * 1000)
60
61/**
62 ** Timer timer functions
63 **/
64
65static void
66Timer_process(CFRunLoopTimerRef rls, void * info)
67{
68    TimerRef	timer = (TimerRef)info;
69
70    if (timer->func && timer->enabled) {
71	timer->enabled = 0;
72	(*timer->func)(timer->arg1, timer->arg2, timer->arg3);
73    }
74    return;
75}
76
77TimerRef
78Timer_create()
79{
80    TimerRef timer;
81
82    timer = malloc(sizeof(*timer));
83    if (timer == NULL)
84	return (NULL);
85    bzero(timer, sizeof(*timer));
86    return (timer);
87}
88
89void
90Timer_free(TimerRef * timer_p)
91{
92    TimerRef timer = *timer_p;
93
94    if (timer == NULL)
95	return;
96
97    Timer_cancel(timer);
98    free(timer);
99    *timer_p = NULL;
100    return;
101}
102
103int
104Timer_set_relative(TimerRef timer,
105		   struct timeval rel_time, Timer_func_t * func,
106		   void * arg1, void * arg2, void * arg3)
107{
108    CFRunLoopTimerContext 	context =  { 0, NULL, NULL, NULL, NULL };
109    CFAbsoluteTime 		wakeup_time;
110
111    if (timer == NULL) {
112	return (0);
113    }
114    Timer_cancel(timer);
115    timer->enabled = 0;
116    if (func == NULL) {
117	return (0);
118    }
119    timer->func = func;
120    timer->arg1 = arg1;
121    timer->arg2 = arg2;
122    timer->arg3 = arg3;
123    timer->enabled = 1;
124    if (rel_time.tv_sec <= 0 && rel_time.tv_usec < 1000) {
125	rel_time.tv_sec = 0;
126	rel_time.tv_usec = 1000; /* force millisecond resolution */
127    }
128    wakeup_time = CFAbsoluteTimeGetCurrent() + rel_time.tv_sec
129	  + ((double)rel_time.tv_usec / USECS_PER_SEC);
130    context.info = timer;
131    timer->rls
132	= CFRunLoopTimerCreate(NULL, wakeup_time,
133			       0.0, 0, 0,
134			       Timer_process,
135			       &context);
136    CFRunLoopAddTimer(CFRunLoopGetCurrent(), timer->rls,
137		      kCFRunLoopDefaultMode);
138    return (1);
139}
140
141void
142Timer_cancel(TimerRef timer)
143{
144    if (timer == NULL) {
145	return;
146    }
147    timer->enabled = 0;
148    timer->func = NULL;
149    if (timer->rls) {
150	CFRunLoopTimerInvalidate(timer->rls);
151	my_CFRelease(&timer->rls);
152    }
153    return;
154}
155
156/**
157 ** timer functions
158 **/
159long
160Timer_current_secs()
161{
162    return ((long)CFAbsoluteTimeGetCurrent());
163}
164
165struct timeval
166Timer_current_time()
167{
168    double 		t = CFAbsoluteTimeGetCurrent();
169    struct timeval 	tv;
170
171    tv.tv_sec = (int32_t)t;
172    tv.tv_usec = (t - tv.tv_sec) * USECS_PER_SEC;
173
174    return (tv);
175}
176