]> git.meshlink.io Git - catta/blob - avahi-core/timeeventq.c
* hide some more files
[catta] / avahi-core / timeeventq.c
1 /* $Id$ */
2
3 /***
4   This file is part of avahi.
5  
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.
10  
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.
15  
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
19   USA.
20 ***/
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include "timeeventq.h"
27 #include "util.h"
28
29 static gint compare(gconstpointer _a, gconstpointer _b) {
30     const AvahiTimeEvent *a = _a,  *b = _b;
31     gint ret;
32
33     if ((ret = avahi_timeval_compare(&a->expiry, &b->expiry)) != 0)
34         return ret;
35
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);
39 }
40
41 static gboolean prepare_func(GSource *source, gint *timeout) {
42     AvahiTimeEventQueue *q = (AvahiTimeEventQueue*) source;
43     AvahiTimeEvent *e;
44     GTimeVal now;
45
46     g_assert(source);
47     g_assert(timeout);
48
49     if (!q->prioq->root) {
50         *timeout = -1;
51         return FALSE;
52     }
53     
54     e = q->prioq->root->data;
55     g_assert(e);
56
57     g_source_get_current_time(source, &now);
58
59     if (avahi_timeval_compare(&now, &e->expiry) >= 0 &&  /* Time elapsed */
60         avahi_timeval_compare(&now, &e->last_run) != 0   /* Not yet run */) {
61         *timeout = -1;
62         return TRUE;
63     }
64
65     *timeout = (gint) (avahi_timeval_diff(&e->expiry, &now)/1000);
66
67     /* Wait at least 1 msec */
68     if (*timeout <= 0)
69         *timeout = 1;
70     
71     return FALSE;
72 }
73
74 static gboolean check_func(GSource *source) {
75     AvahiTimeEventQueue *q = (AvahiTimeEventQueue*) source;
76     AvahiTimeEvent *e;
77     GTimeVal now;
78
79     g_assert(source);
80
81     if (!q->prioq->root)
82         return FALSE;
83
84     e = q->prioq->root->data;
85     g_assert(e);
86
87     g_source_get_current_time(source, &now);
88     
89     return
90         avahi_timeval_compare(&now, &e->expiry) >= 0 && /* Time elapsed */
91         avahi_timeval_compare(&now, &e->last_run) != 0;  /* Not yet run */
92 }
93
94 static gboolean dispatch_func(GSource *source, GSourceFunc callback, gpointer user_data) {
95     AvahiTimeEventQueue *q = (AvahiTimeEventQueue*) source;
96     GTimeVal now;
97
98     g_assert(source);
99
100     g_source_get_current_time(source, &now);
101
102     while (q->prioq->root) {
103         AvahiTimeEvent *e = q->prioq->root->data;
104
105         /* Not yet expired */
106         if (avahi_timeval_compare(&now, &e->expiry) < 0)
107             break;
108
109         /* Already ran */
110         if (avahi_timeval_compare(&now, &e->last_run) == 0)
111             break;
112
113         /* Make sure to move the entry away from the front */
114         e->last_run = now;
115         avahi_prio_queue_shuffle(q->prioq, e->node);
116
117         /* Run it */
118         g_assert(e->callback);
119         e->callback(e, e->userdata);
120     }
121
122     return TRUE;
123 }
124
125 static void fix_expiry_time(AvahiTimeEvent *e) {
126     GTimeVal now;
127     g_assert(e);
128
129     g_source_get_current_time(&e->queue->source, &now);
130
131     if (avahi_timeval_compare(&now, &e->expiry) > 0)
132         e->expiry = now;
133     
134 }
135
136 AvahiTimeEventQueue* avahi_time_event_queue_new(GMainContext *context, gint priority) {
137     AvahiTimeEventQueue *q;
138
139     static GSourceFuncs source_funcs = {
140         prepare_func,
141         check_func,
142         dispatch_func,
143         NULL,
144         NULL,
145         NULL
146     };
147
148     q = (AvahiTimeEventQueue*) g_source_new(&source_funcs, sizeof(AvahiTimeEventQueue));
149     q->prioq = avahi_prio_queue_new(compare);
150
151     g_source_set_priority((GSource*) q, priority);
152     
153     g_source_attach(&q->source, context);
154     
155     return q;
156 }
157
158 void avahi_time_event_queue_free(AvahiTimeEventQueue *q) {
159     g_assert(q);
160
161     while (q->prioq->root)
162         avahi_time_event_queue_remove(q, q->prioq->root->data);
163     avahi_prio_queue_free(q->prioq);
164
165     g_source_destroy(&q->source);
166     g_source_unref(&q->source);
167 }
168
169 AvahiTimeEvent* avahi_time_event_queue_add(AvahiTimeEventQueue *q, const GTimeVal *timeval, AvahiTimeEventCallback callback, gpointer userdata) {
170     AvahiTimeEvent *e;
171     
172     g_assert(q);
173     g_assert(timeval);
174     g_assert(callback);
175     g_assert(userdata);
176
177     e = g_new(AvahiTimeEvent, 1);
178     e->queue = q;
179     e->callback = callback;
180     e->userdata = userdata;
181
182     e->expiry = *timeval;
183     fix_expiry_time(e);
184     
185     e->last_run.tv_sec = 0;
186     e->last_run.tv_usec = 0;
187
188     e->node = avahi_prio_queue_put(q->prioq, e);
189     
190     return e;
191 }
192
193 void avahi_time_event_queue_remove(AvahiTimeEventQueue *q, AvahiTimeEvent *e) {
194     g_assert(q);
195     g_assert(e);
196     g_assert(e->queue == q);
197
198     avahi_prio_queue_remove(q->prioq, e->node);
199     g_free(e);
200 }
201
202 void avahi_time_event_queue_update(AvahiTimeEventQueue *q, AvahiTimeEvent *e, const GTimeVal *timeval) {
203     g_assert(q);
204     g_assert(e);
205     g_assert(e->queue == q);
206     g_assert(timeval);
207
208     e->expiry = *timeval;
209     fix_expiry_time(e);
210
211     avahi_prio_queue_shuffle(q->prioq, e->node);
212 }
213
214 AvahiTimeEvent* avahi_time_event_queue_root(AvahiTimeEventQueue *q) {
215     g_assert(q);
216
217     return q->prioq->root ? q->prioq->root->data : NULL;
218 }
219
220 AvahiTimeEvent* avahi_time_event_next(AvahiTimeEvent *e) {
221     g_assert(e);
222
223     return e->node->next->data;
224 }
225
226