1 #ifdef HAVE_CONFIG_H
2 # include <config.h>
3 #endif
4
5 #include <stdlib.h>
6
7 #include <Eo.h>
8
9 #include "Ecore.h"
10 #include "ecore_private.h"
11
12 #define MY_CLASS ECORE_POLLER_CLASS
13
14 #define MY_CLASS_NAME "Ecore_Poller"
15
16 #define ECORE_POLLER_CHECK(obj) \
17 if (!efl_isa((obj), ECORE_POLLER_CLASS)) \
18 return
19
20 struct _Ecore_Poller
21 {
22 EINA_INLIST;
23 ECORE_MAGIC;
24 int ibit;
25 unsigned char delete_me : 1;
26 Ecore_Task_Cb func;
27 void *data;
28 };
29
30 static Ecore_Timer *timer = NULL;
31 static int min_interval = -1;
32 static int interval_incr = 0;
33 static int at_tick = 0;
34 static int just_added_poller = 0;
35 static int poller_delete_count = 0;
36 static int poller_walking = 0;
37 static double poll_interval = 0.125;
38 static double poll_cur_interval = 0.0;
39 static double last_tick = 0.0;
40 static Ecore_Poller *pollers[16] =
41 {
42 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
43 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
44 };
45 static unsigned short poller_counters[16] =
46 {
47 0, 0, 0, 0, 0, 0, 0, 0,
48 0, 0, 0, 0, 0, 0, 0, 0
49 };
50
51 static void _ecore_poller_next_tick_eval(void);
52 static Eina_Bool _ecore_poller_cb_timer(void *data);
53
54 static void *
_ecore_poller_cleanup(Ecore_Poller * poller)55 _ecore_poller_cleanup(Ecore_Poller *poller)
56 {
57 void *data;
58
59 data = poller->data;
60 pollers[poller->ibit] = (Ecore_Poller *)eina_inlist_remove(EINA_INLIST_GET(pollers[poller->ibit]), EINA_INLIST_GET(poller));
61
62 free(poller);
63
64 return data;
65 }
66
67 static void
_ecore_poller_next_tick_eval(void)68 _ecore_poller_next_tick_eval(void)
69 {
70 int i;
71 double interval;
72
73 min_interval = -1;
74 for (i = 0; i < 15; i++)
75 {
76 if (pollers[i])
77 {
78 min_interval = i;
79 break;
80 }
81 }
82 if (min_interval < 0)
83 {
84 /* no pollers */
85 if (timer)
86 {
87 ecore_timer_del(timer);
88 timer = NULL;
89 }
90 return;
91 }
92 interval_incr = (1 << min_interval);
93 interval = interval_incr * poll_interval;
94 /* we are at the tick callback - so no need to do inter-tick adjustments
95 * so we can fasttrack this as t -= last_tick in theory is 0.0 (though
96 * in practice it will be a very very very small value. also the tick
97 * callback will adjust the timer interval at the end anyway */
98 if (at_tick)
99 {
100 if (!timer)
101 timer = ecore_timer_add(interval, _ecore_poller_cb_timer, NULL);
102 }
103 else
104 {
105 double t;
106
107 if (!timer)
108 timer = ecore_timer_add(interval, _ecore_poller_cb_timer, NULL);
109 else
110 {
111 t = ecore_loop_time_get();
112 if (!EINA_DBL_EQ(interval, poll_cur_interval))
113 {
114 t -= last_tick; /* time since we last ticked */
115 /* delete the timer and reset it to tick off in the new
116 * time interval. at the tick this will be adjusted */
117 ecore_timer_del(timer);
118 timer = ecore_timer_loop_add(interval - t,
119 _ecore_poller_cb_timer, NULL);
120 }
121 }
122 }
123 poll_cur_interval = interval;
124 }
125
126 static Eina_Bool
_ecore_poller_cb_timer(void * data EINA_UNUSED)127 _ecore_poller_cb_timer(void *data EINA_UNUSED)
128 {
129 Ecore_Poller *poller;
130 int i;
131 int changes = 0;
132
133 at_tick++;
134 last_tick = ecore_loop_time_get();
135 /* we have 16 counters - each increments every time the poller counter
136 * "ticks". it increments by the minimum interval (which can be 1, 2, 4,
137 * 7, 16 etc. up to 32768) */
138 for (i = 0; i < 15; i++)
139 {
140 poller_counters[i] += interval_incr;
141 /* wrap back to 0 if we exceed out loop count for the counter */
142 if (poller_counters[i] >= (1 << i)) poller_counters[i] = 0;
143 }
144
145 just_added_poller = 0;
146 /* walk the pollers now */
147 poller_walking++;
148 for (i = 0; i < 15; i++)
149 {
150 /* if the counter is @ 0 - this means that counter "went off" this
151 * tick interval, so run all pollers hooked to that counter */
152 if (poller_counters[i] == 0)
153 {
154 EINA_INLIST_FOREACH(pollers[i], poller)
155 {
156 if (!poller->delete_me)
157 {
158 if (!poller->func(poller->data))
159 {
160 if (!poller->delete_me)
161 {
162 poller->delete_me = 1;
163 poller_delete_count++;
164 }
165 }
166 }
167 }
168 }
169 }
170 poller_walking--;
171
172 /* handle deletes afterwards */
173 if (poller_delete_count > 0)
174 {
175 /* FIXME: walk all pollers and remove deleted ones */
176 for (i = 0; i < 15; i++)
177 {
178 Eina_Inlist *l;
179
180 EINA_INLIST_FOREACH_SAFE(pollers[i], l, poller)
181 {
182 if (poller->delete_me)
183 {
184 _ecore_poller_cleanup(poller);
185
186 poller_delete_count--;
187 changes++;
188 if (poller_delete_count <= 0) break;
189 }
190 }
191 if (poller_delete_count <= 0) break;
192 }
193 }
194 /* if we deleted or added any pollers, then we need to re-evaluate our
195 * minimum poll interval */
196 if ((changes > 0) || (just_added_poller > 0))
197 _ecore_poller_next_tick_eval();
198
199 just_added_poller = 0;
200 poller_delete_count = 0;
201
202 at_tick--;
203
204 /* if the timer was deleted then there is no point returning 1 - ambiguous
205 * if we do as it implies keep running me" but we have been deleted
206 * anyway */
207 if (!timer) return ECORE_CALLBACK_CANCEL;
208
209 /* adjust interval */
210 ecore_timer_interval_set(timer, poll_cur_interval);
211 return ECORE_CALLBACK_RENEW;
212 }
213
214 EAPI void
ecore_poller_poll_interval_set(Ecore_Poller_Type type EINA_UNUSED,double poll_time)215 ecore_poller_poll_interval_set(Ecore_Poller_Type type EINA_UNUSED,
216 double poll_time)
217 {
218 EINA_MAIN_LOOP_CHECK_RETURN;
219
220 if (poll_time < 0.0)
221 {
222 ERR("Poll time %f less than zero, ignored", poll_time);
223 return;
224 }
225
226 poll_interval = poll_time;
227 _ecore_poller_next_tick_eval();
228 }
229
230 EAPI double
ecore_poller_poll_interval_get(Ecore_Poller_Type type EINA_UNUSED)231 ecore_poller_poll_interval_get(Ecore_Poller_Type type EINA_UNUSED)
232 {
233 EINA_MAIN_LOOP_CHECK_RETURN_VAL(0.0);
234 return poll_interval;
235 }
236
237 EAPI Ecore_Poller *
ecore_poller_add(Ecore_Poller_Type type EINA_UNUSED,int interval,Ecore_Task_Cb func,const void * data)238 ecore_poller_add(Ecore_Poller_Type type EINA_UNUSED,
239 int interval,
240 Ecore_Task_Cb func,
241 const void *data)
242 {
243 Ecore_Poller *poller;
244 int ibit;
245
246 poller = calloc(1, sizeof (Ecore_Poller));
247 if (!poller) return NULL;
248
249 EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
250
251 if (!func)
252 {
253 ERR("callback function must be set up for an object of class: '%s'", MY_CLASS_NAME);
254 free(poller);
255 return NULL;
256 }
257
258 /* interval MUST be a power of 2, so enforce it */
259 if (interval < 1) interval = 1;
260 ibit = -1;
261 while (interval != 0)
262 {
263 ibit++;
264 interval >>= 1;
265 }
266 /* only allow up to 32768 - i.e. ibit == 15, so limit it */
267 if (ibit > 15) ibit = 15;
268
269 poller->ibit = ibit;
270 poller->func = func;
271 poller->data = (void *)data;
272 pollers[poller->ibit] = (Ecore_Poller *)eina_inlist_prepend(EINA_INLIST_GET(pollers[poller->ibit]), EINA_INLIST_GET(poller));
273 if (poller_walking)
274 just_added_poller++;
275 else
276 _ecore_poller_next_tick_eval();
277
278 return poller;
279 }
280
281 EAPI Eina_Bool
ecore_poller_poller_interval_set(Ecore_Poller * poller,int interval)282 ecore_poller_poller_interval_set(Ecore_Poller *poller, int interval)
283 {
284 int ibit;
285
286 if (!poller) return EINA_FALSE;
287 EINA_MAIN_LOOP_CHECK_RETURN_VAL(EINA_FALSE);
288
289 /* interval MUST be a power of 2, so enforce it */
290 if (interval < 1) interval = 1;
291 ibit = -1;
292 while (interval != 0)
293 {
294 ibit++;
295 interval >>= 1;
296 }
297 /* only allow up to 32768 - i.e. ibit == 15, so limit it */
298 if (ibit > 15) ibit = 15;
299 /* if interval specified is the same as interval set, return true without wasting time */
300 if (poller->ibit == ibit) return EINA_TRUE;
301
302 pollers[poller->ibit] = (Ecore_Poller *)eina_inlist_remove(EINA_INLIST_GET(pollers[poller->ibit]), EINA_INLIST_GET(poller));
303 poller->ibit = ibit;
304 pollers[poller->ibit] = (Ecore_Poller *)eina_inlist_prepend(EINA_INLIST_GET(pollers[poller->ibit]), EINA_INLIST_GET(poller));
305 if (poller_walking)
306 just_added_poller++;
307 else
308 _ecore_poller_next_tick_eval();
309
310 return EINA_TRUE;
311 }
312
313 EAPI int
ecore_poller_poller_interval_get(const Ecore_Poller * poller)314 ecore_poller_poller_interval_get(const Ecore_Poller *poller)
315 {
316 int ibit, interval = 1;
317
318 if (!poller) return -1;
319 EINA_MAIN_LOOP_CHECK_RETURN_VAL(interval);
320
321 ibit = poller->ibit;
322 while (ibit != 0)
323 {
324 ibit--;
325 interval <<= 1;
326 }
327
328 return interval;
329 }
330
331 EAPI void *
ecore_poller_del(Ecore_Poller * poller)332 ecore_poller_del(Ecore_Poller *poller)
333 {
334 void *data;
335
336 if (!poller) return NULL;
337 EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
338 /* we are walking the poller list - a bad idea to remove from it while
339 * walking it, so just flag it as delete_me and come back to it after
340 * the loop has finished */
341 if (poller_walking > 0)
342 {
343 poller_delete_count++;
344 poller->delete_me = 1;
345 return poller->data;
346 }
347 /* not in loop so safe - delete immediately */
348 data = _ecore_poller_cleanup(poller);
349
350 _ecore_poller_next_tick_eval();
351
352 return data;
353 }
354
355 void
_ecore_poller_shutdown(void)356 _ecore_poller_shutdown(void)
357 {
358 Ecore_Poller *poller;
359 int i;
360
361 for (i = 0; i < 15; i++)
362 {
363 while ((poller = pollers[i]))
364 _ecore_poller_cleanup(poller);
365 poller_counters[i] = 0;
366 }
367
368 if (timer)
369 {
370 ecore_timer_del(timer);
371 timer = NULL;
372 }
373 min_interval = -1;
374 interval_incr = 0;
375 at_tick = 0;
376 just_added_poller = 0;
377 poller_delete_count = 0;
378 poller_walking = 0;
379 poll_interval = 0.125;
380 poll_cur_interval = 0.0;
381 last_tick = 0.0;
382 }
383