1 #include "ecore_private.h"
4 static Ecore_Timer *timer = NULL;
5 static int min_interval = -1;
6 static int interval_incr = 0;
7 static int at_tick = 0;
8 static int just_added_poller = 0;
9 static int poller_delete_count = 0;
10 static int poller_walking = 0;
11 static double poll_interval = 0.125;
12 static double poll_cur_interval = 0.0;
13 static double last_tick = 0.0;
14 static Ecore_Poller *pollers[16] =
16 NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
17 NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL
19 static unsigned short poller_counters[16] =
25 static void _ecore_poller_next_tick_eval(void);
26 static int _ecore_poller_cb_timer(void *data);
29 _ecore_poller_next_tick_eval(void)
35 for (i = 0; i < 15; i++)
48 ecore_timer_del(timer);
53 interval_incr = (1 << min_interval);
54 interval = interval_incr * poll_interval;
55 /* we are at the tick callback - so no need to do inter-tick adjustments
56 * so we can fasttrack this as t -= last_tick in theory is 0.0 (though
57 * in practice it will be a very very very small value. also the tick
58 * callback will adjust the timer interval at the end anyway */
62 timer = ecore_timer_add(interval, _ecore_poller_cb_timer, NULL);
69 timer = ecore_timer_add(interval, _ecore_poller_cb_timer, NULL);
73 if (interval != poll_cur_interval)
75 t -= last_tick; /* time since we last ticked */
76 /* delete the timer and reset it to tick off in the new
77 * time interval. at the tick this will be adjusted */
78 ecore_timer_del(timer);
79 timer = ecore_timer_add(interval - t,
80 _ecore_poller_cb_timer, NULL);
84 poll_cur_interval = interval;
88 _ecore_poller_cb_timer(void *data)
96 last_tick = ecore_time_get();
97 /* we have 16 counters - each incriments every time the poller counter
98 * "ticks". it incriments by the minimum interval (which can be 1, 2, 4,
99 * 7, 16 etc. up to 32768) */
100 for (i = 0; i < 15; i++)
102 poller_counters[i] += interval_incr;
103 /* wrap back to 0 if we exceed out loop count for the counter */
104 if (poller_counters[i] >= (1 << i)) poller_counters[i] = 0;
107 just_added_poller = 0;
108 /* walk the pollers now */
110 for (i = 0; i < 15; i++)
112 /* if the counter is @ 0 - this means that counter "went off" this
113 * tick interval, so run all pollers hooked to that counter */
114 if (poller_counters[i] == 0)
116 for (l = (Ecore_List2 *)pollers[i]; l; l = l->next)
118 poller = (Ecore_Poller *)l;
119 if (!poller->delete_me)
121 if (!poller->func(poller->data))
123 if (!poller->delete_me)
125 poller->delete_me = 1;
126 poller_delete_count++;
135 /* handle deletes afterwards */
136 if (poller_delete_count > 0)
138 /* FIXME: walk all pollers and remove deleted ones */
139 for (i = 0; i < 15; i++)
141 for (l = (Ecore_List2 *)pollers[i]; l;)
143 poller = (Ecore_Poller *)l;
145 if (poller->delete_me)
147 pollers[poller->ibit] = _ecore_list2_remove(pollers[poller->ibit], poller);
149 poller_delete_count--;
151 if (poller_delete_count <= 0) break;
154 if (poller_delete_count <= 0) break;
157 /* if we deleted or added any pollers, then we need to re-evaluate our
158 * minimum poll interval */
159 if ((changes > 0) || (just_added_poller > 0))
160 _ecore_poller_next_tick_eval();
162 just_added_poller = 0;
163 poller_delete_count = 0;
167 /* if the timer was deleted then there is no point returning 1 - ambiguous
168 * if we do as it im plies "keep running me" but we have been deleted
170 if (!timer) return 0;
172 /* adjust interval */
173 ecore_timer_interval_set(timer, poll_cur_interval);
178 * @defgroup Ecore_Poll_Group Ecore Poll Functions
180 * These functions are for the need to poll information, but provide a shared
181 * abstracted API to pool such polling to minimise wakeup and ensure all the
182 * polling happens in as few spots as possible areound a core poll interval.
183 * For now only 1 core poller type is supprted: ECORE_POLLER_CORE
188 * Sets the time between ticks (in seconds) for the given ticker clock.
189 * @param type The ticker type to adjust
190 * @param poll_time The time (in seconds) between ticks of the clock
191 * @ingroup Ecore_Poller_Group
193 * This will adjust the time between ticks of the given ticker type defined
194 * by @p type to the time period defined by @p poll_time.
197 ecore_poller_poll_interval_set(Ecore_Poller_Type type, double poll_time)
199 poll_interval = poll_time;
200 _ecore_poller_next_tick_eval();
204 * Gets the time between ticks (in seconds) for the fiven ticker clock.
205 * @param type The ticker type to query
206 * @return The time in seconds between ticks of the ticker clock
207 * @ingroup Ecore_Poller_Group
209 * This will get the time between ticks of the specifider ticker clock.
212 ecore_poller_poll_interval_get(Ecore_Poller_Type type)
214 return poll_interval;
218 * Creates a poller to call the given function at a particular tick interval.
219 * @param type The ticker type to attach the poller to
220 * @param interval The poll interval
221 * @param func The given function. If @p func returns 1, the poller is
222 * rescheduled for the next tick interval.
223 * @param data Data to pass to @p func when it is called.
224 * @return A poller object on success. @c NULL on failure.
225 * @ingroup Ecore_Poller_Group
227 * This function adds a poller callback that is to be called regularly
228 * along with all other poller callbacks so the pollers are synchronized with
229 * all other pollers running off the same poller type and at the same tick
230 * interval. This should be used for polling things when polling is desired
231 * or required, and you do not have specific requirements on the exact times
232 * to poll and want to avoid extra process wakeups for polling. This will
233 * save power as the CPU has more of a chance to go into a low power state
234 * the longer it is asleep for, so this should be used if you are at all
237 * The @p type parameter defines the poller tick type (there is a virtual
238 * clock ticking all the time - though ecore avoids making it tick when
239 * there will not be any work to do at that tick point). There is only one
240 * ticker at the moment - that is ECORE_POLLER_CORE. This is here for future
241 * expansion if multiple clocks with different frequencies are really required.
242 * The default time between ticks for the ECORE_POLLER_CORE ticker is 0.125
245 * The @p interval is the number of ticker ticks that will pass by in between
246 * invocations of the @p func callback. This must be between 1 and 32768
247 * inclusive, and must be a power of 2 (i.e. 1, 2, 4, 8, 16, ... 16384, 32768).
248 * If it is 1, then the function will be called every tick. if it is 2, then it
249 * will be called every 2nd tick, if it is 8, then every 8th tick etc. Exactly
250 * which tick is undefined, as only the interval between calls can be defined.
251 * Ecore will endeavour to keep pollers synchronised and to call as many in
252 * 1 wakeup event as possible.
254 * This function adds a poller and returns its handle on success and NULL on
255 * failure. The function @p func will be called at tick intervals described
256 * above. The function will be passed the @p data pointer as its parameter.
258 * When the poller @p func is called, it must return a value of either
259 * 1 (or ECORE_CALLBACK_RENEW) or 0 (or ECORE_CALLBACK_CANCEL). If it
260 * returns 1, it will be called again at the next tick, or if it returns
261 * 0 it will be deleted automatically making any references/handles for it
265 ecore_poller_add(Ecore_Poller_Type type, int interval, int (*func) (void *data), const void *data)
267 Ecore_Poller *poller;
270 if (!func) return NULL;
271 if (interval < 1) interval = 1;
273 poller = calloc(1, sizeof(Ecore_Poller));
274 if (!poller) return NULL;
275 ECORE_MAGIC_SET(poller, ECORE_MAGIC_POLLER);
276 /* interval MUST be a power of 2, so enforce it */
277 if (interval < 1) interval = 1;
279 while (interval != 0)
284 /* only allow up to 32768 - i.e. ibit == 15, so limit it */
285 if (ibit > 15) ibit = 15;
289 poller->data = (void *)data;
290 pollers[poller->ibit] = _ecore_list2_prepend(pollers[poller->ibit], poller);
294 _ecore_poller_next_tick_eval();
299 * Delete the specified poller from the timer list.
300 * @param poller The poller to delete.
301 * @return The data pointer set for the timer when @ref ecore_poller_add was
302 * called. @c NULL is returned if the function is unsuccessful.
303 * @ingroup Ecore_Poller_Group
305 * Note: @p poller must be a valid handle. If the poller function has already
306 * returned 0, the handle is no longer valid (and does not need to be delete).
309 ecore_poller_del(Ecore_Poller *poller)
313 if (!ECORE_MAGIC_CHECK(poller, ECORE_MAGIC_POLLER))
315 ECORE_MAGIC_FAIL(poller, ECORE_MAGIC_POLLER,
319 /* we are walking the poller list - a bad idea to remove from it while
320 * walking it, so just flag it as delete_me and come back to it after
321 * the loop has finished */
322 if (poller_walking > 0)
324 poller_delete_count++;
325 poller->delete_me = 1;
328 /* not in loop so safe - delete immediately */
330 pollers[poller->ibit] = _ecore_list2_remove(pollers[poller->ibit], poller);
332 _ecore_poller_next_tick_eval();
337 _ecore_poller_shutdown(void)
341 Ecore_Poller *poller;
343 for (i = 0; i < 15; i++)
345 for (l = (Ecore_List2 *)pollers[i]; l;)
347 poller = (Ecore_Poller *)l;
349 pollers[poller->ibit] = _ecore_list2_remove(pollers[poller->ibit], poller);