summaryrefslogtreecommitdiffstats
path: root/avahi-glib
diff options
context:
space:
mode:
Diffstat (limited to 'avahi-glib')
-rw-r--r--avahi-glib/glib-watch-test.c16
-rw-r--r--avahi-glib/glib-watch.c195
-rw-r--r--avahi-glib/glib-watch.h6
3 files changed, 150 insertions, 67 deletions
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);