]> git.meshlink.io Git - catta/blob - timeeventq.c
some more inomcplete work
[catta] / timeeventq.c
1 #include "timeeventq.h"
2 #include "util.h"
3
4 static gint compare(gconstpointer _a, gconstpointer _b) {
5     const flxTimeEvent *a = _a,  *b = _b;
6
7     return flx_timeval_compare(&a->expiry, &b->expiry);
8 }
9
10 static gboolean prepare_func(GSource *source, gint *timeout) {
11     flxTimeEventQueue *q = (flxTimeEventQueue*) source;
12     flxTimeEvent *e;
13     GTimeVal now;
14
15     g_assert(source);
16     g_assert(timeout);
17
18     if (!q->prioq->root) {
19         *timeout = -1;
20         return FALSE;
21     }
22     
23     e = q->prioq->root->data;
24     g_assert(e);
25
26     g_source_get_current_time(source, &now);
27
28     if (flx_timeval_compare(&now, &e->expiry) >= 0) {
29         *timeout = -1;
30         return TRUE;
31     }
32
33     *timeout = (gint) (flx_timeval_diff(&e->expiry, &now)/1000);
34     
35     return FALSE;
36 }
37
38 static gboolean check_func(GSource *source) {
39     flxTimeEventQueue *q = (flxTimeEventQueue*) source;
40     flxTimeEvent *e;
41     GTimeVal now;
42
43     g_assert(source);
44
45     if (!q->prioq->root)
46         return FALSE;
47
48     e = q->prioq->root->data;
49     g_assert(e);
50
51     g_source_get_current_time(source, &now);
52     
53     return flx_timeval_compare(&now, &e->expiry) >= 0;
54 }
55
56 static gboolean dispatch_func(GSource *source, GSourceFunc callback, gpointer user_data) {
57     flxTimeEventQueue *q = (flxTimeEventQueue*) source;
58     GTimeVal now;
59
60     g_assert(source);
61
62     g_source_get_current_time(source, &now);
63
64     while (q->prioq->root) {
65         flxTimeEvent *e = q->prioq->root->data;
66
67         if (flx_timeval_compare(&now, &e->expiry) < 0)
68             break;
69
70         g_assert(e->callback);
71         e->callback(e, e->userdata);
72     }
73
74     return TRUE;
75 }
76
77 flxTimeEventQueue* flx_time_event_queue_new(GMainContext *context) {
78     flxTimeEventQueue *q;
79
80     static GSourceFuncs source_funcs = {
81         prepare_func,
82         check_func,
83         dispatch_func,
84         NULL,
85         NULL,
86         NULL
87     };
88
89     q = (flxTimeEventQueue*) g_source_new(&source_funcs, sizeof(flxTimeEventQueue));
90     q->prioq = flx_prio_queue_new(compare);
91
92     g_source_attach(&q->source, context);
93     
94     return q;
95 }
96
97 void flx_time_event_queue_free(flxTimeEventQueue *q) {
98     g_assert(q);
99
100     while (q->prioq->root)
101         flx_time_event_queue_remove(q, q->prioq->root->data);
102     flx_prio_queue_free(q->prioq);
103
104     g_source_destroy(&q->source);
105     g_source_unref(&q->source);
106 }
107
108 flxTimeEvent* flx_time_event_queue_add(flxTimeEventQueue *q, const GTimeVal *timeval, void (*callback)(flxTimeEvent *e, void *userdata), void *userdata) {
109     flxTimeEvent *e;
110     
111     g_assert(q);
112     g_assert(timeval);
113     g_assert(callback);
114     g_assert(userdata);
115
116     e = g_new(flxTimeEvent, 1);
117     e->queue = q;
118     e->expiry = *timeval;
119     e->callback = callback;
120     e->userdata = userdata;
121
122     e->node = flx_prio_queue_put(q->prioq, e);
123     
124     return e;
125 }
126
127 void flx_time_event_queue_remove(flxTimeEventQueue *q, flxTimeEvent *e) {
128     g_assert(q);
129     g_assert(e);
130     g_assert(e->queue == q);
131
132     flx_prio_queue_remove(q->prioq, e->node);
133     g_free(e);
134 }
135
136 void flx_time_event_update(flxTimeEventQueue *q, flxTimeEvent *e, const GTimeVal *timeval) {
137     g_assert(q);
138     g_assert(e);
139     g_assert(e->queue == q);
140
141     e->expiry = *timeval;
142
143     flx_prio_queue_shuffle(q->prioq, e->node);
144 }