#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <sys/types.h>
#include <math.h>
#include <syslog.h>
#include <CoreFoundation/CFRunLoop.h>
#include "Timer.h"
#include "myCFUtil.h"
#include "mylog.h"
struct Timer_s {
Timer_func_t * func;
void * arg1;
void * arg2;
void * arg3;
void * rls;
bool enabled;
};
#define USECS_PER_SEC (1000 * 1000)
static void
Timer_process(CFRunLoopTimerRef rls, void * info)
{
Timer * timer = (Timer *)info;
if (timer->func && timer->enabled) {
timer->enabled = 0;
(*timer->func)(timer->arg1, timer->arg2, timer->arg3);
}
return;
}
Timer *
Timer_create()
{
Timer * timer;
timer = malloc(sizeof(*timer));
if (timer == NULL)
return (NULL);
bzero(timer, sizeof(*timer));
return (timer);
}
void
Timer_free(Timer * * timer_p)
{
Timer * timer = *timer_p;
if (timer == NULL)
return;
Timer_cancel(timer);
free(timer);
*timer_p = NULL;
return;
}
int
Timer_set_relative(Timer * timer,
struct timeval rel_time, Timer_func_t * func,
void * arg1, void * arg2, void * arg3)
{
CFRunLoopTimerContext context = { 0, NULL, NULL, NULL, NULL };
CFAbsoluteTime wakeup_time;
if (timer == NULL) {
return (0);
}
Timer_cancel(timer);
timer->enabled = 0;
if (func == NULL) {
return (0);
}
timer->func = func;
timer->arg1 = arg1;
timer->arg2 = arg2;
timer->arg3 = arg3;
timer->enabled = 1;
if (rel_time.tv_sec <= 0 && rel_time.tv_usec < 1000) {
rel_time.tv_sec = 0;
rel_time.tv_usec = 1000;
}
wakeup_time = CFAbsoluteTimeGetCurrent() + rel_time.tv_sec
+ ((double)rel_time.tv_usec / USECS_PER_SEC);
context.info = timer;
timer->rls
= CFRunLoopTimerCreate(NULL, wakeup_time,
0.0, 0, 0,
Timer_process,
&context);
my_log(LOG_DEBUG, "timer: wakeup time is (%d.%d) %g",
rel_time.tv_sec, rel_time.tv_usec, wakeup_time);
my_log(LOG_DEBUG, "timer: adding timer source");
CFRunLoopAddTimer(CFRunLoopGetCurrent(), timer->rls,
kCFRunLoopDefaultMode);
return (1);
}
void
Timer_cancel(Timer * timer)
{
if (timer == NULL) {
return;
}
timer->enabled = 0;
timer->func = NULL;
if (timer->rls) {
my_log(LOG_DEBUG, "timer: freeing timer source");
CFRunLoopTimerInvalidate(timer->rls);
my_CFRelease(&timer->rls);
}
return;
}
long
Timer_current_secs()
{
return ((long)CFAbsoluteTimeGetCurrent());
}
struct timeval
Timer_current_time()
{
double t = CFAbsoluteTimeGetCurrent();
struct timeval tv;
tv.tv_sec = (int32_t)t;
tv.tv_usec = (t - tv.tv_sec) * USECS_PER_SEC;
return (tv);
}