X-Git-Url: http://git.meshlink.io/?a=blobdiff_plain;f=avahi-glib%2Fglib-watch.c;h=9d804409df23911c1aea33c44f5eb75785a7e1ef;hb=b73aab83cbdaaac40c4bb80b82049dc4452b5f1c;hp=4af23907f301c2bebc8cef2ff0653ca179e095de;hpb=4f0a5e7572a4257894b4bfede42c26d65152609e;p=catta diff --git a/avahi-glib/glib-watch.c b/avahi-glib/glib-watch.c index 4af2390..9d80440 100644 --- a/avahi-glib/glib-watch.c +++ b/avahi-glib/glib-watch.c @@ -25,32 +25,46 @@ #include #include +#include #include "glib-watch.h" struct AvahiWatch { AvahiGLibPoll *glib_poll; int dead; + GPollFD pollfd; int pollfd_added; + AvahiWatchCallback callback; void *userdata; AVAHI_LLIST_FIELDS(AvahiWatch, watches); }; +struct AvahiTimeout { + AvahiGLibPoll *glib_poll; + gboolean dead; + + gboolean enabled; + struct timeval expiry; + + AvahiTimeoutCallback callback; + void *userdata; + + AVAHI_LLIST_FIELDS(AvahiTimeout, timeouts); +}; + struct AvahiGLibPoll { GSource source; AvahiPoll api; GMainContext *context; - struct timeval wakeup; - AvahiWakeupCallback wakeup_callback; - void *wakeup_userdata; - - int req_cleanup; + gboolean timeout_req_cleanup; + gboolean watch_req_cleanup; - AVAHI_LLIST_HEAD(AvahiWatch, watches); + AVAHI_LLIST_HEAD(AvahiWatch, watches); + AVAHI_LLIST_HEAD(AvahiTimeout, timeouts); }; static void destroy_watch(AvahiWatch *w) { @@ -64,7 +78,7 @@ static void destroy_watch(AvahiWatch *w) { avahi_free(w); } -static void cleanup(AvahiGLibPoll *g, int all) { +static void cleanup_watches(AvahiGLibPoll *g, int all) { AvahiWatch *w, *next; assert(g); @@ -75,10 +89,10 @@ static void cleanup(AvahiGLibPoll *g, int all) { destroy_watch(w); } - g->req_cleanup = 0; + g->watch_req_cleanup = 0; } -static AvahiWatch* watch_new(AvahiPoll *api, int fd, AvahiWatchEvent event, AvahiWatchCallback callback, void *userdata) { +static AvahiWatch* watch_new(const AvahiPoll *api, int fd, AvahiWatchEvent event, AvahiWatchCallback callback, void *userdata) { AvahiWatch *w; AvahiGLibPoll *g; @@ -99,13 +113,13 @@ static AvahiWatch* watch_new(AvahiPoll *api, int fd, AvahiWatchEvent event, Avah (event & AVAHI_WATCH_OUT ? G_IO_OUT : 0) | (event & AVAHI_WATCH_ERR ? G_IO_ERR : 0) | (event & AVAHI_WATCH_HUP ? G_IO_HUP : 0); - ; + w->pollfd.revents = 0; w->callback = callback; w->userdata = userdata; - w->dead = 0; + w->dead = FALSE; g_source_add_poll(&g->source, &w->pollfd); - w->pollfd_added = 1; + w->pollfd_added = TRUE; AVAHI_LLIST_PREPEND(AvahiWatch, watches, g->watches, w); @@ -119,68 +133,129 @@ static void watch_update(AvahiWatch *w, AvahiWatchEvent events) { w->pollfd.events = events; } +static AvahiWatchEvent watch_get_events(AvahiWatch *w) { + assert(w); + assert(!w->dead); + + return w->pollfd.revents; +} + static void watch_free(AvahiWatch *w) { assert(w); assert(!w->dead); if (w->pollfd_added) { g_source_remove_poll(&w->glib_poll->source, &w->pollfd); - w->pollfd_added = 0; + w->pollfd_added = TRUE; } - w->dead = 1; - w->glib_poll->req_cleanup = 1; + w->dead = TRUE; + w->glib_poll->timeout_req_cleanup = TRUE; } -static void set_wakeup(AvahiPoll *api, const struct timeval *tv, AvahiWakeupCallback callback, void *userdata) { +static AvahiTimeout* timeout_new(const AvahiPoll *api, const struct timeval *tv, AvahiTimeoutCallback callback, void *userdata) { + AvahiTimeout *t; AvahiGLibPoll *g; - + assert(api); + assert(callback); + g = api->userdata; + assert(g); - if (callback) { - if (tv) - g->wakeup = *tv; - else { - g->wakeup.tv_sec = 0; - g->wakeup.tv_usec = 0; - } - - g->wakeup_callback = callback; - g->wakeup_userdata = userdata; - } else - g->wakeup_callback = NULL; + if (!(t = avahi_new(AvahiTimeout, 1))) + return NULL; + + t->glib_poll = g; + t->dead = FALSE; + + if ((t->enabled = !!tv)) + t->expiry = *tv; + + t->callback = callback; + t->userdata = userdata; + + AVAHI_LLIST_PREPEND(AvahiTimeout, timeouts, g->timeouts, t); + + return t; } -static void start_wakeup_callback(AvahiGLibPoll *g) { - AvahiWakeupCallback callback; - void *userdata; +static void timeout_update(AvahiTimeout *t, const struct timeval *tv) { + assert(t); + assert(!t->dead); + + if ((t->enabled = !!tv)) + t->expiry = *tv; +} + +static void timeout_free(AvahiTimeout *t) { + assert(t); + assert(!t->dead); + + t->dead = TRUE; + t->glib_poll->timeout_req_cleanup = TRUE; +} + +static void destroy_timeout(AvahiTimeout *t) { + assert(t); + AVAHI_LLIST_REMOVE(AvahiTimeout, timeouts, t->glib_poll->timeouts, t); + avahi_free(t); +} + +static void cleanup_timeouts(AvahiGLibPoll *g, int all) { + AvahiTimeout *t, *next; assert(g); - /* Reset the wakeup functions, but allow changing of the two - values from the callback function */ + for (t = g->timeouts; t; t = next) { + next = t->timeouts_next; - callback = g->wakeup_callback; - userdata = g->wakeup_userdata; - g->wakeup_callback = NULL; - g->wakeup_userdata = NULL; + if (all || t->dead) + destroy_timeout(t); + } - assert(callback); - - callback(&g->api, userdata); + g->timeout_req_cleanup = FALSE; +} + +static AvahiTimeout* find_next_timeout(AvahiGLibPoll *g) { + AvahiTimeout *t, *n = NULL; + assert(g); + + for (t = g->timeouts; t; t = t->timeouts_next) { + + if (t->dead || !t->enabled) + continue; + + if (!n || avahi_timeval_compare(&t->expiry, &n->expiry) < 0) + n = t; + } + + return n; +} + +static void start_timeout_callback(AvahiTimeout *t) { + assert(t); + assert(!t->dead); + assert(t->enabled); + + t->enabled = 0; + t->callback(t, t->userdata); } static gboolean prepare_func(GSource *source, gint *timeout) { AvahiGLibPoll *g = (AvahiGLibPoll*) source; + AvahiTimeout *next_timeout; g_assert(g); g_assert(timeout); - if (g->req_cleanup) - cleanup(g, 0); + if (g->watch_req_cleanup) + cleanup_watches(g, 0); + + if (g->timeout_req_cleanup) + cleanup_timeouts(g, 0); - if (g->wakeup_callback) { + if ((next_timeout = find_next_timeout(g))) { GTimeVal now; struct timeval tvnow; AvahiUsec usec; @@ -189,7 +264,7 @@ static gboolean prepare_func(GSource *source, gint *timeout) { tvnow.tv_sec = now.tv_sec; tvnow.tv_usec = now.tv_usec; - usec = avahi_timeval_diff(&g->wakeup, &tvnow); + usec = avahi_timeval_diff(&next_timeout->expiry, &tvnow); if (usec <= 0) return TRUE; @@ -203,17 +278,18 @@ static gboolean prepare_func(GSource *source, gint *timeout) { static gboolean check_func(GSource *source) { AvahiGLibPoll *g = (AvahiGLibPoll*) source; AvahiWatch *w; + AvahiTimeout *next_timeout; g_assert(g); - if (g->wakeup_callback) { + if ((next_timeout = find_next_timeout(g))) { GTimeVal now; struct timeval tvnow; g_source_get_current_time(source, &now); tvnow.tv_sec = now.tv_sec; tvnow.tv_usec = now.tv_usec; - if (avahi_timeval_compare(&g->wakeup, &tvnow) < 0) + if (avahi_timeval_compare(&next_timeout->expiry, &tvnow) < 0) return TRUE; } @@ -224,21 +300,22 @@ static gboolean check_func(GSource *source) { return FALSE; } -static gboolean dispatch_func(GSource *source, GSourceFunc callback, gpointer userdata) { +static gboolean dispatch_func(GSource *source, AVAHI_GCC_UNUSED GSourceFunc callback, AVAHI_GCC_UNUSED gpointer userdata) { AvahiGLibPoll* g = (AvahiGLibPoll*) source; AvahiWatch *w; + AvahiTimeout *next_timeout; g_assert(g); - if (g->wakeup_callback) { + if ((next_timeout = find_next_timeout(g))) { GTimeVal now; struct timeval tvnow; g_source_get_current_time(source, &now); tvnow.tv_sec = now.tv_sec; tvnow.tv_usec = now.tv_usec; - if (avahi_timeval_compare(&g->wakeup, &tvnow) < 0) { - start_wakeup_callback(g); + if (avahi_timeval_compare(&next_timeout->expiry, &tvnow) < 0) { + start_timeout_callback(next_timeout); return TRUE; } } @@ -254,7 +331,7 @@ static gboolean dispatch_func(GSource *source, GSourceFunc callback, gpointer us return TRUE; } -AvahiGLibPoll *avahi_glib_poll_new(GMainContext *context) { +AvahiGLibPoll *avahi_glib_poll_new(GMainContext *context, gint priority) { AvahiGLibPoll *g; static GSourceFuncs source_funcs = { @@ -270,17 +347,24 @@ AvahiGLibPoll *avahi_glib_poll_new(GMainContext *context) { g_main_context_ref(g->context = context ? context : g_main_context_default()); g->api.userdata = g; + g->api.watch_new = watch_new; g->api.watch_free = watch_free; g->api.watch_update = watch_update; - g->api.set_wakeup = set_wakeup; + g->api.watch_get_events = watch_get_events; + + g->api.timeout_new = timeout_new; + g->api.timeout_free = timeout_free; + g->api.timeout_update = timeout_update; - g->wakeup_callback = NULL; - g->req_cleanup = 0; + g->watch_req_cleanup = FALSE; + g->timeout_req_cleanup = FALSE; AVAHI_LLIST_HEAD_INIT(AvahiWatch, g->watches); + AVAHI_LLIST_HEAD_INIT(AvahiTimeout, g->timeouts); g_source_attach(&g->source, g->context); + g_source_set_priority(&g->source, priority); return g; } @@ -289,17 +373,15 @@ void avahi_glib_poll_free(AvahiGLibPoll *g) { GSource *s = &g->source; assert(g); -/* g_message("BEFORE"); */ - cleanup(g, 1); + cleanup_watches(g, 1); + cleanup_timeouts(g, 1); -/* g_message("MIDDLE"); */ g_main_context_unref(g->context); g_source_destroy(s); g_source_unref(s); -/* g_message("AFTER"); */ } -AvahiPoll* avahi_glib_poll_get(AvahiGLibPoll *g) { +const AvahiPoll* avahi_glib_poll_get(AvahiGLibPoll *g) { assert(g); return &g->api;