mirror of https://github.com/sipwise/rtpengine.git
Change-Id: I445f3e2556ce647bf7e245e9612f4babcf04e388changes/11/27611/9
parent
cfe6f87c8d
commit
d96dbdea17
@ -0,0 +1,87 @@
|
||||
#include "timerthread.h"
|
||||
#include "aux.h"
|
||||
|
||||
|
||||
static int tt_obj_cmp(const void *a, const void *b) {
|
||||
const struct timerthread_obj *A = a, *B = b;
|
||||
return timeval_cmp_ptr(&A->next_check, &B->next_check);
|
||||
}
|
||||
|
||||
void timerthread_init(struct timerthread *tt, void (*func)(void *)) {
|
||||
tt->tree = g_tree_new(tt_obj_cmp);
|
||||
mutex_init(&tt->lock);
|
||||
cond_init(&tt->cond);
|
||||
tt->func = func;
|
||||
}
|
||||
|
||||
void timerthread_run(void *p) {
|
||||
struct timerthread *tt = p;
|
||||
|
||||
mutex_lock(&tt->lock);
|
||||
|
||||
while (!rtpe_shutdown) {
|
||||
gettimeofday(&rtpe_now, NULL);
|
||||
|
||||
/* lock our list and get the first element */
|
||||
struct timerthread_obj *tt_obj = g_tree_find_first(tt->tree, NULL, NULL);
|
||||
/* scheduled to run? if not, we just go to sleep, otherwise we remove it from the tree,
|
||||
* steal the reference and run it */
|
||||
if (!tt_obj)
|
||||
goto sleep;
|
||||
if (timeval_cmp(&rtpe_now, &tt_obj->next_check) < 0)
|
||||
goto sleep;
|
||||
|
||||
// steal reference
|
||||
g_tree_remove(tt->tree, tt_obj);
|
||||
ZERO(tt_obj->next_check);
|
||||
tt_obj->last_run = rtpe_now;
|
||||
mutex_unlock(&tt->lock);
|
||||
|
||||
// run and release
|
||||
tt->func(tt_obj);
|
||||
obj_put(tt_obj);
|
||||
|
||||
mutex_lock(&tt->lock);
|
||||
continue;
|
||||
|
||||
sleep:;
|
||||
/* figure out how long we should sleep */
|
||||
long long sleeptime = tt_obj ? timeval_diff(&tt_obj->next_check, &rtpe_now) : 100000;
|
||||
sleeptime = MIN(100000, sleeptime); /* 100 ms at the most */
|
||||
struct timeval tv = rtpe_now;
|
||||
timeval_add_usec(&tv, sleeptime);
|
||||
cond_timedwait(&tt->cond, &tt->lock, &tv);
|
||||
}
|
||||
|
||||
mutex_unlock(&tt->lock);
|
||||
}
|
||||
|
||||
void timerthread_obj_schedule_abs_nl(struct timerthread_obj *tt_obj, const struct timeval *tv) {
|
||||
if (!tt_obj)
|
||||
return;
|
||||
|
||||
struct timerthread *tt = tt_obj->tt;
|
||||
if (tt_obj->next_check.tv_sec && timeval_cmp(&tt_obj->next_check, tv) <= 0)
|
||||
return; /* already scheduled sooner */
|
||||
if (!g_tree_remove(tt->tree, tt_obj))
|
||||
obj_hold(tt_obj); /* if it wasn't removed, we make a new reference */
|
||||
tt_obj->next_check = *tv;
|
||||
g_tree_insert(tt->tree, tt_obj, tt_obj);
|
||||
cond_broadcast(&tt->cond);
|
||||
}
|
||||
|
||||
void timerthread_obj_deschedule(struct timerthread_obj *tt_obj) {
|
||||
if (!tt_obj)
|
||||
return;
|
||||
|
||||
struct timerthread *tt = tt_obj->tt;
|
||||
mutex_lock(&tt->lock);
|
||||
if (!tt_obj->next_check.tv_sec)
|
||||
goto nope; /* already descheduled */
|
||||
int ret = g_tree_remove(tt->tree, tt_obj);
|
||||
ZERO(tt_obj->next_check);
|
||||
if (ret)
|
||||
obj_put(tt_obj);
|
||||
nope:
|
||||
mutex_unlock(&tt->lock);
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
#ifndef _TIMERTHREAD_H_
|
||||
#define _TIMERTHREAD_H_
|
||||
|
||||
#include "obj.h"
|
||||
#include <glib.h>
|
||||
#include <sys/time.h>
|
||||
#include "auxlib.h"
|
||||
|
||||
|
||||
struct timerthread {
|
||||
GTree *tree;
|
||||
mutex_t lock;
|
||||
cond_t cond;
|
||||
void (*func)(void *);
|
||||
};
|
||||
|
||||
struct timerthread_obj {
|
||||
struct obj obj;
|
||||
|
||||
struct timerthread *tt;
|
||||
struct timeval next_check; /* protected by ->lock */
|
||||
struct timeval last_run; /* ditto */
|
||||
};
|
||||
|
||||
|
||||
void timerthread_init(struct timerthread *, void (*)(void *));
|
||||
void timerthread_run(void *);
|
||||
|
||||
void timerthread_obj_schedule_abs_nl(struct timerthread_obj *, const struct timeval *);
|
||||
void timerthread_obj_deschedule(struct timerthread_obj *);
|
||||
|
||||
|
||||
#endif
|
||||
Loading…
Reference in new issue