X-Git-Url: http://git.meshlink.io/?a=blobdiff_plain;f=avahi-core%2Ftimeeventq.c;h=17334ee063ba55af276bb6e19aeb12fbb4305b5f;hb=acdec2c38860b6bc36328d20f5da6584787a368a;hp=efce7b7d1e2769be055dd1554fc9d425859b7467;hpb=c58379bde376cb2298fca14f83a86626f1b76f2f;p=catta diff --git a/avahi-core/timeeventq.c b/avahi-core/timeeventq.c index efce7b7..17334ee 100644 --- a/avahi-core/timeeventq.c +++ b/avahi-core/timeeventq.c @@ -23,163 +23,205 @@ #include #endif -#include "timeeventq.h" -#include "util.h" - -static gint compare(gconstpointer _a, gconstpointer _b) { - const AvahiTimeEvent *a = _a, *b = _b; +#include +#include - return avahi_timeval_compare(&a->expiry, &b->expiry); -} +#include +#include -static gboolean prepare_func(GSource *source, gint *timeout) { - AvahiTimeEventQueue *q = (AvahiTimeEventQueue*) source; - AvahiTimeEvent *e; - GTimeVal now; - - g_assert(source); - g_assert(timeout); +#include "timeeventq.h" +#include "log.h" + +struct AvahiTimeEvent { + AvahiTimeEventQueue *queue; + AvahiPrioQueueNode *node; + struct timeval expiry; + struct timeval last_run; + AvahiTimeEventCallback callback; + void* userdata; +}; + +struct AvahiTimeEventQueue { + const AvahiPoll *poll_api; + AvahiPrioQueue *prioq; + AvahiTimeout *timeout; +}; + +static int compare(const void* _a, const void* _b) { + const AvahiTimeEvent *a = _a, *b = _b; + int ret; - if (!q->prioq->root) { - *timeout = -1; - return FALSE; - } - - e = q->prioq->root->data; - g_assert(e); + if ((ret = avahi_timeval_compare(&a->expiry, &b->expiry)) != 0) + return ret; - g_source_get_current_time(source, &now); + /* If both exevents are scheduled for the same time, put the entry + * that has been run earlier the last time first. */ + return avahi_timeval_compare(&a->last_run, &b->last_run); +} - if (avahi_timeval_compare(&now, &e->expiry) >= 0) { - *timeout = -1; - return TRUE; - } +static AvahiTimeEvent* time_event_queue_root(AvahiTimeEventQueue *q) { + assert(q); - *timeout = (gint) (avahi_timeval_diff(&e->expiry, &now)/1000); - - return FALSE; + return q->prioq->root ? q->prioq->root->data : NULL; } -static gboolean check_func(GSource *source) { - AvahiTimeEventQueue *q = (AvahiTimeEventQueue*) source; +static void update_timeout(AvahiTimeEventQueue *q) { AvahiTimeEvent *e; - GTimeVal now; + assert(q); - g_assert(source); + if ((e = time_event_queue_root(q))) + q->poll_api->timeout_update(q->timeout, &e->expiry); + else + q->poll_api->timeout_update(q->timeout, NULL); +} - if (!q->prioq->root) - return FALSE; +static void expiration_event(AVAHI_GCC_UNUSED AvahiTimeout *timeout, void *userdata) { + AvahiTimeEventQueue *q = userdata; + AvahiTimeEvent *e; - e = q->prioq->root->data; - g_assert(e); + if ((e = time_event_queue_root(q))) { + struct timeval now; - g_source_get_current_time(source, &now); + gettimeofday(&now, NULL); - return avahi_timeval_compare(&now, &e->expiry) >= 0; -} + /* Check if expired */ + if (avahi_timeval_compare(&now, &e->expiry) >= 0) { -static gboolean dispatch_func(GSource *source, GSourceFunc callback, gpointer user_data) { - AvahiTimeEventQueue *q = (AvahiTimeEventQueue*) source; - GTimeVal now; + /* Make sure to move the entry away from the front */ + e->last_run = now; + avahi_prio_queue_shuffle(q->prioq, e->node); - g_assert(source); + /* Run it */ + assert(e->callback); + e->callback(e, e->userdata); - g_source_get_current_time(source, &now); + update_timeout(q); + return; + } + } - while (q->prioq->root) { - AvahiTimeEvent *e = q->prioq->root->data; + avahi_log_debug(__FILE__": Strange, expiration_event() called, but nothing really happened."); + update_timeout(q); +} - if (avahi_timeval_compare(&now, &e->expiry) < 0) - break; +static void fix_expiry_time(AvahiTimeEvent *e) { + struct timeval now; + assert(e); - g_assert(e->callback); - e->callback(e, e->userdata); - } + return; /*** DO WE REALLY NEED THIS? ***/ - return TRUE; + gettimeofday(&now, NULL); + + if (avahi_timeval_compare(&now, &e->expiry) > 0) + e->expiry = now; } -AvahiTimeEventQueue* avahi_time_event_queue_new(GMainContext *context, gint priority) { +AvahiTimeEventQueue* avahi_time_event_queue_new(const AvahiPoll *poll_api) { AvahiTimeEventQueue *q; - static GSourceFuncs source_funcs = { - prepare_func, - check_func, - dispatch_func, - NULL, - NULL, - NULL - }; + if (!(q = avahi_new(AvahiTimeEventQueue, 1))) { + avahi_log_error(__FILE__": Out of memory"); + goto oom; + } - q = (AvahiTimeEventQueue*) g_source_new(&source_funcs, sizeof(AvahiTimeEventQueue)); - q->prioq = avahi_prio_queue_new(compare); + q->poll_api = poll_api; - g_source_set_priority((GSource*) q, priority); - - g_source_attach(&q->source, context); + if (!(q->prioq = avahi_prio_queue_new(compare))) + goto oom; + + if (!(q->timeout = poll_api->timeout_new(poll_api, NULL, expiration_event, q))) + goto oom; return q; + +oom: + + if (q) { + avahi_free(q); + + if (q->prioq) + avahi_prio_queue_free(q->prioq); + } + + return NULL; } void avahi_time_event_queue_free(AvahiTimeEventQueue *q) { - g_assert(q); + AvahiTimeEvent *e; + + assert(q); - while (q->prioq->root) - avahi_time_event_queue_remove(q, q->prioq->root->data); + while ((e = time_event_queue_root(q))) + avahi_time_event_free(e); avahi_prio_queue_free(q->prioq); - g_source_destroy(&q->source); - g_source_unref(&q->source); + q->poll_api->timeout_free(q->timeout); + + avahi_free(q); } -AvahiTimeEvent* avahi_time_event_queue_add(AvahiTimeEventQueue *q, const GTimeVal *timeval, void (*callback)(AvahiTimeEvent *e, void *userdata), void *userdata) { +AvahiTimeEvent* avahi_time_event_new( + AvahiTimeEventQueue *q, + const struct timeval *timeval, + AvahiTimeEventCallback callback, + void* userdata) { + AvahiTimeEvent *e; - g_assert(q); - g_assert(timeval); - g_assert(callback); - g_assert(userdata); + assert(q); + assert(callback); + assert(userdata); - e = g_new(AvahiTimeEvent, 1); + if (!(e = avahi_new(AvahiTimeEvent, 1))) { + avahi_log_error(__FILE__": Out of memory"); + return NULL; /* OOM */ + } + e->queue = q; - e->expiry = *timeval; e->callback = callback; e->userdata = userdata; - e->node = avahi_prio_queue_put(q->prioq, e); + if (timeval) + e->expiry = *timeval; + else { + e->expiry.tv_sec = 0; + e->expiry.tv_usec = 0; + } - return e; -} + fix_expiry_time(e); + + e->last_run.tv_sec = 0; + e->last_run.tv_usec = 0; -void avahi_time_event_queue_remove(AvahiTimeEventQueue *q, AvahiTimeEvent *e) { - g_assert(q); - g_assert(e); - g_assert(e->queue == q); + if (!(e->node = avahi_prio_queue_put(q->prioq, e))) { + avahi_free(e); + return NULL; + } - avahi_prio_queue_remove(q->prioq, e->node); - g_free(e); + update_timeout(q); + return e; } -void avahi_time_event_queue_update(AvahiTimeEventQueue *q, AvahiTimeEvent *e, const GTimeVal *timeval) { - g_assert(q); - g_assert(e); - g_assert(e->queue == q); +void avahi_time_event_free(AvahiTimeEvent *e) { + AvahiTimeEventQueue *q; + assert(e); - e->expiry = *timeval; + q = e->queue; - avahi_prio_queue_shuffle(q->prioq, e->node); -} - -AvahiTimeEvent* avahi_time_event_queue_root(AvahiTimeEventQueue *q) { - g_assert(q); + avahi_prio_queue_remove(q->prioq, e->node); + avahi_free(e); - return q->prioq->root ? q->prioq->root->data : NULL; + update_timeout(q); } -AvahiTimeEvent* avahi_time_event_next(AvahiTimeEvent *e) { - g_assert(e); +void avahi_time_event_update(AvahiTimeEvent *e, const struct timeval *timeval) { + assert(e); + assert(timeval); - return e->node->next->data; + e->expiry = *timeval; + fix_expiry_time(e); + avahi_prio_queue_shuffle(e->queue->prioq, e->node); + + update_timeout(e->queue); } -