2 This file is part of catta.
4 catta is free software; you can redistribute it and/or modify it
5 under the terms of the GNU Lesser General Public License as
6 published by the Free Software Foundation; either version 2.1 of the
7 License, or (at your option) any later version.
9 catta is distributed in the hope that it will be useful, but WITHOUT
10 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
12 Public License for more details.
14 You should have received a copy of the GNU Lesser General Public
15 License along with catta; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
27 #include <catta/timeval.h>
28 #include <catta/malloc.h>
29 #include <catta/log.h>
31 #include "timeeventq.h"
33 struct CattaTimeEvent {
34 CattaTimeEventQueue *queue;
35 CattaPrioQueueNode *node;
36 struct timeval expiry;
37 struct timeval last_run;
38 CattaTimeEventCallback callback;
42 struct CattaTimeEventQueue {
43 const CattaPoll *poll_api;
44 CattaPrioQueue *prioq;
45 CattaTimeout *timeout;
48 static int compare(const void* _a, const void* _b) {
49 const CattaTimeEvent *a = _a, *b = _b;
52 if ((ret = catta_timeval_compare(&a->expiry, &b->expiry)) != 0)
55 /* If both exevents are scheduled for the same time, put the entry
56 * that has been run earlier the last time first. */
57 return catta_timeval_compare(&a->last_run, &b->last_run);
60 static CattaTimeEvent* time_event_queue_root(CattaTimeEventQueue *q) {
63 return q->prioq->root ? q->prioq->root->data : NULL;
66 static void update_timeout(CattaTimeEventQueue *q) {
70 if ((e = time_event_queue_root(q)))
71 q->poll_api->timeout_update(q->timeout, &e->expiry);
73 q->poll_api->timeout_update(q->timeout, NULL);
76 static void expiration_event(CATTA_GCC_UNUSED CattaTimeout *timeout, void *userdata) {
77 CattaTimeEventQueue *q = userdata;
80 if ((e = time_event_queue_root(q))) {
83 gettimeofday(&now, NULL);
85 /* Check if expired */
86 if (catta_timeval_compare(&now, &e->expiry) >= 0) {
88 /* Make sure to move the entry away from the front */
90 catta_prio_queue_shuffle(q->prioq, e->node);
94 e->callback(e, e->userdata);
101 catta_log_debug(__FILE__": Strange, expiration_event() called, but nothing really happened.");
105 static void fix_expiry_time(CattaTimeEvent *e) {
109 return; /*** DO WE REALLY NEED THIS? ***/
111 gettimeofday(&now, NULL);
113 if (catta_timeval_compare(&now, &e->expiry) > 0)
117 CattaTimeEventQueue* catta_time_event_queue_new(const CattaPoll *poll_api) {
118 CattaTimeEventQueue *q;
120 if (!(q = catta_new(CattaTimeEventQueue, 1))) {
121 catta_log_error(__FILE__": Out of memory");
125 q->poll_api = poll_api;
127 if (!(q->prioq = catta_prio_queue_new(compare)))
130 if (!(q->timeout = poll_api->timeout_new(poll_api, NULL, expiration_event, q)))
141 catta_prio_queue_free(q->prioq);
147 void catta_time_event_queue_free(CattaTimeEventQueue *q) {
152 while ((e = time_event_queue_root(q)))
153 catta_time_event_free(e);
154 catta_prio_queue_free(q->prioq);
156 q->poll_api->timeout_free(q->timeout);
161 CattaTimeEvent* catta_time_event_new(
162 CattaTimeEventQueue *q,
163 const struct timeval *timeval,
164 CattaTimeEventCallback callback,
173 if (!(e = catta_new(CattaTimeEvent, 1))) {
174 catta_log_error(__FILE__": Out of memory");
175 return NULL; /* OOM */
179 e->callback = callback;
180 e->userdata = userdata;
183 e->expiry = *timeval;
185 e->expiry.tv_sec = 0;
186 e->expiry.tv_usec = 0;
191 e->last_run.tv_sec = 0;
192 e->last_run.tv_usec = 0;
194 if (!(e->node = catta_prio_queue_put(q->prioq, e))) {
203 void catta_time_event_free(CattaTimeEvent *e) {
204 CattaTimeEventQueue *q;
209 catta_prio_queue_remove(q->prioq, e->node);
215 void catta_time_event_update(CattaTimeEvent *e, const struct timeval *timeval) {
219 e->expiry = *timeval;
221 catta_prio_queue_shuffle(e->queue->prioq, e->node);
223 update_timeout(e->queue);