4 This file is part of avahi.
6 avahi is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as
8 published by the Free Software Foundation; either version 2.1 of the
9 License, or (at your option) any later version.
11 avahi is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
14 Public License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with avahi; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
26 #include "timeeventq.h"
29 static gint compare(gconstpointer _a, gconstpointer _b) {
30 const AvahiTimeEvent *a = _a, *b = _b;
33 if ((ret = avahi_timeval_compare(&a->expiry, &b->expiry)) != 0)
36 /* If both exevents are scheduled for the same time, put the entry
37 * that has been run earlier the last time first. */
38 return avahi_timeval_compare(&a->last_run, &b->last_run);
41 static void source_get_timeval(GSource *source, struct timeval *tv) {
47 g_source_get_current_time(source, >v);
48 tv->tv_sec = gtv.tv_sec;
49 tv->tv_usec = gtv.tv_usec;
52 static gboolean prepare_func(GSource *source, gint *timeout) {
53 AvahiTimeEventQueue *q = (AvahiTimeEventQueue*) source;
60 if (!q->prioq->root) {
65 e = q->prioq->root->data;
68 source_get_timeval(source, &now);
70 if (avahi_timeval_compare(&now, &e->expiry) >= 0 && /* Time elapsed */
71 avahi_timeval_compare(&now, &e->last_run) != 0 /* Not yet run */) {
76 *timeout = (gint) (avahi_timeval_diff(&e->expiry, &now)/1000);
78 /* Wait at least 1 msec */
85 static gboolean check_func(GSource *source) {
86 AvahiTimeEventQueue *q = (AvahiTimeEventQueue*) source;
95 e = q->prioq->root->data;
98 source_get_timeval(source, &now);
101 avahi_timeval_compare(&now, &e->expiry) >= 0 && /* Time elapsed */
102 avahi_timeval_compare(&now, &e->last_run) != 0; /* Not yet run */
105 static gboolean dispatch_func(GSource *source, GSourceFunc callback, gpointer user_data) {
106 AvahiTimeEventQueue *q = (AvahiTimeEventQueue*) source;
111 source_get_timeval(source, &now);
113 while (q->prioq->root) {
114 AvahiTimeEvent *e = q->prioq->root->data;
116 /* Not yet expired */
117 if (avahi_timeval_compare(&now, &e->expiry) < 0)
121 if (avahi_timeval_compare(&now, &e->last_run) == 0)
124 /* Make sure to move the entry away from the front */
126 avahi_prio_queue_shuffle(q->prioq, e->node);
129 g_assert(e->callback);
130 e->callback(e, e->userdata);
136 static void fix_expiry_time(AvahiTimeEvent *e) {
140 source_get_timeval(&e->queue->source, &now);
142 if (avahi_timeval_compare(&now, &e->expiry) > 0)
147 AvahiTimeEventQueue* avahi_time_event_queue_new(GMainContext *context, gint priority) {
148 AvahiTimeEventQueue *q;
150 static GSourceFuncs source_funcs = {
159 q = (AvahiTimeEventQueue*) g_source_new(&source_funcs, sizeof(AvahiTimeEventQueue));
160 q->prioq = avahi_prio_queue_new(compare);
162 g_source_set_priority((GSource*) q, priority);
164 g_source_attach(&q->source, context);
169 void avahi_time_event_queue_free(AvahiTimeEventQueue *q) {
172 while (q->prioq->root)
173 avahi_time_event_queue_remove(q, q->prioq->root->data);
174 avahi_prio_queue_free(q->prioq);
176 g_source_destroy(&q->source);
177 g_source_unref(&q->source);
180 AvahiTimeEvent* avahi_time_event_queue_add(AvahiTimeEventQueue *q, const struct timeval *timeval, AvahiTimeEventCallback callback, gpointer userdata) {
188 e = g_new(AvahiTimeEvent, 1);
190 e->callback = callback;
191 e->userdata = userdata;
193 e->expiry = *timeval;
196 e->last_run.tv_sec = 0;
197 e->last_run.tv_usec = 0;
199 e->node = avahi_prio_queue_put(q->prioq, e);
204 void avahi_time_event_queue_remove(AvahiTimeEventQueue *q, AvahiTimeEvent *e) {
207 g_assert(e->queue == q);
209 avahi_prio_queue_remove(q->prioq, e->node);
213 void avahi_time_event_queue_update(AvahiTimeEventQueue *q, AvahiTimeEvent *e, const struct timeval *timeval) {
216 g_assert(e->queue == q);
219 e->expiry = *timeval;
222 avahi_prio_queue_shuffle(q->prioq, e->node);
225 AvahiTimeEvent* avahi_time_event_queue_root(AvahiTimeEventQueue *q) {
228 return q->prioq->root ? q->prioq->root->data : NULL;
231 AvahiTimeEvent* avahi_time_event_next(AvahiTimeEvent *e) {
234 return e->node->next->data;