From 769c00f228ba0d37217aaf1424dedde390e7a01c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 14 Aug 2005 22:11:35 +0000 Subject: * add new priority parameter to avahi_glib_poll_new() * beef up AvahiPoll a little to contain real timeout events * cleanups in avahi-client * drop glib dependency * port to AvahiPoll system * put some "const"s and "static"s in to make gcc shut up * change all uses of malloc/free to avahi_malloc/avahi_new/avahi_free git-svn-id: file:///home/lennart/svn/public/avahi/trunk@324 941a03a8-eaeb-0310-b9a0-b1bbd8fe43fe --- avahi-glib/glib-watch-test.c | 16 ++-- avahi-glib/glib-watch.c | 195 ++++++++++++++++++++++++++++++------------- avahi-glib/glib-watch.h | 6 +- 3 files changed, 150 insertions(+), 67 deletions(-) (limited to 'avahi-glib') diff --git a/avahi-glib/glib-watch-test.c b/avahi-glib/glib-watch-test.c index 17b334d..73114d1 100644 --- a/avahi-glib/glib-watch-test.c +++ b/avahi-glib/glib-watch-test.c @@ -52,7 +52,7 @@ static void callback(AvahiWatch *w, int fd, AvahiWatchEvent event, void *userdat } } -static void wakeup(AvahiPoll *_api, void *userdata) { +static void wakeup(AvahiTimeout *t, void *userdata) { struct timeval tv; static int i = 0; @@ -62,26 +62,28 @@ static void wakeup(AvahiPoll *_api, void *userdata) { g_main_loop_quit(loop); avahi_elapse_time(&tv, 1000, 0); - api->set_wakeup(api, &tv, wakeup, NULL); + api->timeout_update(t, &tv); } int main(int argc, char *argv[]) { - AvahiGLibPoll *s; + AvahiGLibPoll *g; struct timeval tv; - s = avahi_glib_poll_new(NULL); - assert(s); + g = avahi_glib_poll_new(NULL, G_PRIORITY_DEFAULT); + assert(g); - api = avahi_glib_poll_get(s); + api = avahi_glib_poll_get(g); api->watch_new(api, 0, AVAHI_WATCH_IN, callback, NULL); avahi_elapse_time(&tv, 1000, 0); - api->set_wakeup(api, &tv, wakeup, NULL); + api->timeout_new(api, &tv, wakeup, NULL); loop = g_main_loop_new(NULL, FALSE); g_main_loop_run(loop); g_main_loop_unref(loop); + + avahi_glib_poll_free(g); return 0; } diff --git a/avahi-glib/glib-watch.c b/avahi-glib/glib-watch.c index f099e5a..e6def46 100644 --- a/avahi-glib/glib-watch.c +++ b/avahi-glib/glib-watch.c @@ -31,26 +31,39 @@ 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 +77,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,7 +88,7 @@ static void cleanup(AvahiGLibPoll *g, int all) { destroy_watch(w); } - g->req_cleanup = 0; + g->watch_req_cleanup = 0; } static AvahiWatch* watch_new(const AvahiPoll *api, int fd, AvahiWatchEvent event, AvahiWatchCallback callback, void *userdata) { @@ -99,13 +112,13 @@ static AvahiWatch* watch_new(const AvahiPoll *api, int fd, AvahiWatchEvent event (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 +132,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(const 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 +263,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 +277,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; } @@ -227,18 +302,19 @@ static gboolean check_func(GSource *source) { static gboolean dispatch_func(GSource *source, GSourceFunc callback, 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 +330,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 +346,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,14 +372,12 @@ 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"); */ } const AvahiPoll* avahi_glib_poll_get(AvahiGLibPoll *g) { diff --git a/avahi-glib/glib-watch.h b/avahi-glib/glib-watch.h index 4fa8a3b..0833bdc 100644 --- a/avahi-glib/glib-watch.h +++ b/avahi-glib/glib-watch.h @@ -33,14 +33,14 @@ AVAHI_C_DECL_BEGIN #endif -/** GLib main loop adapter */ +/** GLib main loop adapter. You can safely cast this into a GSource */ typedef struct AvahiGLibPoll AvahiGLibPoll; /** Create a new GLib main loop adapter attached to the specified context. If context is NULL, the default main loop context is used. You can attach as many AvahiGLibPoll objects to the same context - as you want. */ -AvahiGLibPoll *avahi_glib_poll_new(GMainContext *context); + as you want. priority takes on of GLib's G_PRIORITY constants. */ +AvahiGLibPoll *avahi_glib_poll_new(GMainContext *context, gint priority); /** Free GLib main loop adapter */ void avahi_glib_poll_free(AvahiGLibPoll *g); -- cgit