2 * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
12 #include "ecore_private.h"
20 unsigned char delete_me : 1;
21 int (*func) (void *data);
26 static Ecore_Timer *timer = NULL;
27 static int min_interval = -1;
28 static int interval_incr = 0;
29 static int at_tick = 0;
30 static int just_added_poller = 0;
31 static int poller_delete_count = 0;
32 static int poller_walking = 0;
33 static double poll_interval = 0.125;
34 static double poll_cur_interval = 0.0;
35 static double last_tick = 0.0;
36 static Ecore_Poller *pollers[16] =
38 NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
39 NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL
41 static unsigned short poller_counters[16] =
47 static void _ecore_poller_next_tick_eval(void);
48 static int _ecore_poller_cb_timer(void *data);
51 _ecore_poller_next_tick_eval(void)
57 for (i = 0; i < 15; i++)
70 ecore_timer_del(timer);
75 interval_incr = (1 << min_interval);
76 interval = interval_incr * poll_interval;
77 /* we are at the tick callback - so no need to do inter-tick adjustments
78 * so we can fasttrack this as t -= last_tick in theory is 0.0 (though
79 * in practice it will be a very very very small value. also the tick
80 * callback will adjust the timer interval at the end anyway */
84 timer = ecore_timer_add(interval, _ecore_poller_cb_timer, NULL);
91 timer = ecore_timer_add(interval, _ecore_poller_cb_timer, NULL);
95 if (interval != poll_cur_interval)
97 t -= last_tick; /* time since we last ticked */
98 /* delete the timer and reset it to tick off in the new
99 * time interval. at the tick this will be adjusted */
100 ecore_timer_del(timer);
101 timer = ecore_timer_add(interval - t,
102 _ecore_poller_cb_timer, NULL);
106 poll_cur_interval = interval;
110 _ecore_poller_cb_timer(void *data __UNUSED__)
113 Ecore_Poller *poller, *l;
117 last_tick = ecore_time_get();
118 /* we have 16 counters - each incriments every time the poller counter
119 * "ticks". it incriments by the minimum interval (which can be 1, 2, 4,
120 * 7, 16 etc. up to 32768) */
121 for (i = 0; i < 15; i++)
123 poller_counters[i] += interval_incr;
124 /* wrap back to 0 if we exceed out loop count for the counter */
125 if (poller_counters[i] >= (1 << i)) poller_counters[i] = 0;
128 just_added_poller = 0;
129 /* walk the pollers now */
131 for (i = 0; i < 15; i++)
133 /* if the counter is @ 0 - this means that counter "went off" this
134 * tick interval, so run all pollers hooked to that counter */
135 if (poller_counters[i] == 0)
137 EINA_INLIST_FOREACH(pollers[i], poller)
139 if (!poller->delete_me)
141 if (!poller->func(poller->data))
143 if (!poller->delete_me)
145 poller->delete_me = 1;
146 poller_delete_count++;
155 /* handle deletes afterwards */
156 if (poller_delete_count > 0)
158 /* FIXME: walk all pollers and remove deleted ones */
159 for (i = 0; i < 15; i++)
161 for (l = pollers[i]; l;)
164 l = (Ecore_Poller *) EINA_INLIST_GET(l)->next;
165 if (poller->delete_me)
167 pollers[i] = (Ecore_Poller *) eina_inlist_remove(EINA_INLIST_GET(pollers[i]), EINA_INLIST_GET(poller));
169 poller_delete_count--;
171 if (poller_delete_count <= 0) break;
174 if (poller_delete_count <= 0) break;
177 /* if we deleted or added any pollers, then we need to re-evaluate our
178 * minimum poll interval */
179 if ((changes > 0) || (just_added_poller > 0))
180 _ecore_poller_next_tick_eval();
182 just_added_poller = 0;
183 poller_delete_count = 0;
187 /* if the timer was deleted then there is no point returning 1 - ambiguous
188 * if we do as it im plies "keep running me" but we have been deleted
190 if (!timer) return 0;
192 /* adjust interval */
193 ecore_timer_interval_set(timer, poll_cur_interval);
198 * @defgroup Ecore_Poll_Group Ecore Poll Functions
200 * These functions are for the need to poll information, but provide a shared
201 * abstracted API to pool such polling to minimise wakeup and ensure all the
202 * polling happens in as few spots as possible areound a core poll interval.
203 * For now only 1 core poller type is supprted: ECORE_POLLER_CORE
208 * Sets the time between ticks (in seconds) for the given ticker clock.
209 * @param type The ticker type to adjust
210 * @param poll_time The time (in seconds) between ticks of the clock
211 * @ingroup Ecore_Poller_Group
213 * This will adjust the time between ticks of the given ticker type defined
214 * by @p type to the time period defined by @p poll_time.
217 ecore_poller_poll_interval_set(Ecore_Poller_Type type __UNUSED__, double poll_time)
219 poll_interval = poll_time;
220 _ecore_poller_next_tick_eval();
224 * Gets the time between ticks (in seconds) for the given ticker clock.
225 * @param type The ticker type to query
226 * @return The time in seconds between ticks of the ticker clock
227 * @ingroup Ecore_Poller_Group
229 * This will get the time between ticks of the specifider ticker clock.
232 ecore_poller_poll_interval_get(Ecore_Poller_Type type __UNUSED__)
234 return poll_interval;
238 * Creates a poller to call the given function at a particular tick interval.
239 * @param type The ticker type to attach the poller to
240 * @param interval The poll interval
241 * @param func The given function. If @p func returns 1, the poller is
242 * rescheduled for the next tick interval.
243 * @param data Data to pass to @p func when it is called.
244 * @return A poller object on success. @c NULL on failure.
245 * @ingroup Ecore_Poller_Group
247 * This function adds a poller callback that is to be called regularly
248 * along with all other poller callbacks so the pollers are synchronized with
249 * all other pollers running off the same poller type and at the same tick
250 * interval. This should be used for polling things when polling is desired
251 * or required, and you do not have specific requirements on the exact times
252 * to poll and want to avoid extra process wakeups for polling. This will
253 * save power as the CPU has more of a chance to go into a low power state
254 * the longer it is asleep for, so this should be used if you are at all
257 * The @p type parameter defines the poller tick type (there is a virtual
258 * clock ticking all the time - though ecore avoids making it tick when
259 * there will not be any work to do at that tick point). There is only one
260 * ticker at the moment - that is ECORE_POLLER_CORE. This is here for future
261 * expansion if multiple clocks with different frequencies are really required.
262 * The default time between ticks for the ECORE_POLLER_CORE ticker is 0.125
265 * The @p interval is the number of ticker ticks that will pass by in between
266 * invocations of the @p func callback. This must be between 1 and 32768
267 * inclusive, and must be a power of 2 (i.e. 1, 2, 4, 8, 16, ... 16384, 32768).
268 * If it is 1, then the function will be called every tick. if it is 2, then it
269 * will be called every 2nd tick, if it is 8, then every 8th tick etc. Exactly
270 * which tick is undefined, as only the interval between calls can be defined.
271 * Ecore will endeavour to keep pollers synchronised and to call as many in
272 * 1 wakeup event as possible.
274 * This function adds a poller and returns its handle on success and NULL on
275 * failure. The function @p func will be called at tick intervals described
276 * above. The function will be passed the @p data pointer as its parameter.
278 * When the poller @p func is called, it must return a value of either
279 * 1 (or ECORE_CALLBACK_RENEW) or 0 (or ECORE_CALLBACK_CANCEL). If it
280 * returns 1, it will be called again at the next tick, or if it returns
281 * 0 it will be deleted automatically making any references/handles for it
285 ecore_poller_add(Ecore_Poller_Type type __UNUSED__, int interval, int (*func) (void *data), const void *data)
287 Ecore_Poller *poller;
290 if (!func) return NULL;
291 if (interval < 1) interval = 1;
293 poller = calloc(1, sizeof(Ecore_Poller));
294 if (!poller) return NULL;
295 ECORE_MAGIC_SET(poller, ECORE_MAGIC_POLLER);
296 /* interval MUST be a power of 2, so enforce it */
297 if (interval < 1) interval = 1;
299 while (interval != 0)
304 /* only allow up to 32768 - i.e. ibit == 15, so limit it */
305 if (ibit > 15) ibit = 15;
309 poller->data = (void *)data;
310 pollers[poller->ibit] = (Ecore_Poller *) eina_inlist_prepend(EINA_INLIST_GET(pollers[poller->ibit]), EINA_INLIST_GET(poller));
314 _ecore_poller_next_tick_eval();
319 * Delete the specified poller from the timer list.
320 * @param poller The poller to delete.
321 * @return The data pointer set for the timer when @ref ecore_poller_add was
322 * called. @c NULL is returned if the function is unsuccessful.
323 * @ingroup Ecore_Poller_Group
325 * Note: @p poller must be a valid handle. If the poller function has already
326 * returned 0, the handle is no longer valid (and does not need to be delete).
329 ecore_poller_del(Ecore_Poller *poller)
333 if (!ECORE_MAGIC_CHECK(poller, ECORE_MAGIC_POLLER))
335 ECORE_MAGIC_FAIL(poller, ECORE_MAGIC_POLLER,
339 /* we are walking the poller list - a bad idea to remove from it while
340 * walking it, so just flag it as delete_me and come back to it after
341 * the loop has finished */
342 if (poller_walking > 0)
344 poller_delete_count++;
345 poller->delete_me = 1;
348 /* not in loop so safe - delete immediately */
350 pollers[poller->ibit] = (Ecore_Poller *) eina_inlist_remove(EINA_INLIST_GET(pollers[poller->ibit]), EINA_INLIST_GET(poller));
352 _ecore_poller_next_tick_eval();
357 _ecore_poller_shutdown(void)
360 Ecore_Poller *poller;
362 for (i = 0; i < 15; i++)
364 while ((poller = pollers[i]))
366 pollers[i] = (Ecore_Poller *) eina_inlist_remove(EINA_INLIST_GET(pollers[i]), EINA_INLIST_GET(pollers[i]));