]> git.meshlink.io Git - catta/blob - avahi-core/timeeventq.c
* strip glib from avahi-core
[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 <assert.h>
27 #include <stdlib.h>
28
29 #include <avahi-common/timeval.h>
30 #include <avahi-common/malloc.h>
31
32 #include "timeeventq.h"
33 #include "log.h"
34
35 struct AvahiTimeEvent {
36     AvahiTimeEventQueue *queue;
37     AvahiPrioQueueNode *node;
38     struct timeval expiry;
39     struct timeval last_run;
40     AvahiTimeEventCallback callback;
41     void* userdata;
42 };
43
44 struct AvahiTimeEventQueue {
45     AvahiPoll *poll_api;
46     AvahiPrioQueue *prioq;
47 };
48
49 static int compare(const void* _a, const void* _b) {
50     const AvahiTimeEvent *a = _a,  *b = _b;
51     int ret;
52
53     if ((ret = avahi_timeval_compare(&a->expiry, &b->expiry)) != 0)
54         return ret;
55
56     /* If both exevents are scheduled for the same time, put the entry
57      * that has been run earlier the last time first. */
58     return avahi_timeval_compare(&a->last_run, &b->last_run);
59 }
60
61 static void expiration_event(AvahiPoll *poll_api, void *userdata);
62
63 static void update_wakeup(AvahiTimeEventQueue *q) {
64     assert(q);
65
66     if (q->prioq->root) {
67         AvahiTimeEvent *e = q->prioq->root->data;
68         q->poll_api->set_wakeup(q->poll_api, &e->expiry, expiration_event, q);
69     } else
70         q->poll_api->set_wakeup(q->poll_api, NULL, NULL, NULL);
71 }
72
73 void expiration_event(AvahiPoll *poll_api, void *userdata) {
74     struct timeval now;
75     AvahiTimeEventQueue *q = userdata;
76     AvahiTimeEvent *e;
77
78     gettimeofday(&now, NULL);
79     
80     if ((e = avahi_time_event_queue_root(q))) {
81
82         /* Check if expired */
83         if (avahi_timeval_compare(&now, &e->expiry) >= 0) {
84
85             /* Make sure to move the entry away from the front */
86             e->last_run = now;
87             avahi_prio_queue_shuffle(q->prioq, e->node);
88
89             /* Run it */
90             assert(e->callback);
91             e->callback(e, e->userdata);
92         }
93     }
94
95     update_wakeup(q);
96 }
97
98 static void fix_expiry_time(AvahiTimeEvent *e) {
99     struct timeval now;
100     assert(e);
101
102     gettimeofday(&now, NULL);
103
104     if (avahi_timeval_compare(&now, &e->expiry) > 0)
105         e->expiry = now;
106 }
107
108 AvahiTimeEventQueue* avahi_time_event_queue_new(AvahiPoll *poll_api) {
109     AvahiTimeEventQueue *q;
110
111     if (!(q = avahi_new(AvahiTimeEventQueue, 1))) {
112         avahi_log_error(__FILE__": Out of memory");
113         goto oom;
114     }
115
116     if (!(q->prioq = avahi_prio_queue_new(compare)))
117         goto oom;
118
119     q->poll_api = poll_api;
120     return q;
121
122 oom:
123
124     if (q)
125         avahi_free(q);
126     
127     return NULL;
128 }
129
130 void avahi_time_event_queue_free(AvahiTimeEventQueue *q) {
131     assert(q);
132
133     while (q->prioq->root)
134         avahi_time_event_free(q->prioq->root->data);
135     avahi_prio_queue_free(q->prioq);
136
137     avahi_free(q);
138 }
139
140 AvahiTimeEvent* avahi_time_event_new(
141     AvahiTimeEventQueue *q,
142     const struct timeval *timeval,
143     AvahiTimeEventCallback callback,
144     void* userdata) {
145     
146     AvahiTimeEvent *e;
147     
148     assert(q);
149     assert(callback);
150     assert(userdata);
151
152     if (!(e = avahi_new(AvahiTimeEvent, 1))) {
153         avahi_log_error(__FILE__": Out of memory");
154         return NULL; /* OOM */
155     }
156     
157     e->queue = q;
158     e->callback = callback;
159     e->userdata = userdata;
160
161     if (timeval)
162         e->expiry = *timeval;
163     else {
164         e->expiry.tv_sec = 0;
165         e->expiry.tv_usec = 0;
166     }
167     
168     fix_expiry_time(e);
169     
170     e->last_run.tv_sec = 0;
171     e->last_run.tv_usec = 0;
172
173     if (!(e->node = avahi_prio_queue_put(q->prioq, e))) {
174         avahi_free(e);
175         return NULL;
176     }
177
178     update_wakeup(q);
179     return e;
180 }
181
182 void avahi_time_event_free(AvahiTimeEvent *e) {
183     AvahiTimeEventQueue *q;
184     assert(e);
185
186     q = e->queue;
187
188     avahi_prio_queue_remove(q->prioq, e->node);
189     avahi_free(e);
190
191     update_wakeup(q);
192 }
193
194 void avahi_time_event_update(AvahiTimeEvent *e, const struct timeval *timeval) {
195     assert(e);
196     assert(timeval);
197
198     e->expiry = *timeval;
199     fix_expiry_time(e);
200     avahi_prio_queue_shuffle(e->queue->prioq, e->node);
201     
202     update_wakeup(e->queue);
203 }
204
205 AvahiTimeEvent* avahi_time_event_queue_root(AvahiTimeEventQueue *q) {
206     assert(q);
207
208     return q->prioq->root ? q->prioq->root->data : NULL;
209 }
210
211 AvahiTimeEvent* avahi_time_event_next(AvahiTimeEvent *e) {
212     assert(e);
213
214     return e->node->next->data;
215 }
216
217