14679526c6eda48985534afa2bbde8a2e7e6d561
[profile/ivi/ecore.git] / src / lib / ecore / ecore_poll.c
1 #ifdef HAVE_CONFIG_H
2 # include <config.h>
3 #endif
4
5 #include <stdlib.h>
6
7 #include "Ecore.h"
8 #include "ecore_private.h"
9
10
11 struct _Ecore_Poller
12 {
13    EINA_INLIST;
14    ECORE_MAGIC;
15    int           ibit;
16    unsigned char delete_me : 1;
17    Ecore_Task_Cb func;
18    void          *data;
19 };
20
21
22 static Ecore_Timer    *timer = NULL;
23 static int             min_interval = -1;
24 static int             interval_incr = 0;
25 static int             at_tick = 0;
26 static int             just_added_poller = 0;
27 static int             poller_delete_count = 0;
28 static int             poller_walking = 0;
29 static double          poll_interval = 0.125;
30 static double          poll_cur_interval = 0.0;
31 static double          last_tick = 0.0;
32 static Ecore_Poller   *pollers[16] =
33 {
34    NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
35    NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL
36 };
37 static unsigned short  poller_counters[16] =
38 {
39    0,0,0,0,0,0,0,0,
40    0,0,0,0,0,0,0,0
41 };
42
43 static void _ecore_poller_next_tick_eval(void);
44 static Eina_Bool _ecore_poller_cb_timer(void *data);
45
46 static void
47 _ecore_poller_next_tick_eval(void)
48 {
49    int i;
50    double interval;
51
52    min_interval = -1;
53    for (i = 0; i < 15; i++)
54      {
55         if (pollers[i])
56           {
57              min_interval = i;
58              break;
59           }
60      }
61    if (min_interval < 0)
62      {
63         /* no pollers */
64         if (timer)
65           {
66              ecore_timer_del(timer);
67              timer = NULL;
68           }
69         return;
70      }
71    interval_incr = (1 << min_interval);
72    interval = interval_incr * poll_interval;
73    /* we are at the tick callback - so no need to do inter-tick adjustments
74     * so we can fasttrack this as t -= last_tick in theory is 0.0 (though
75     * in practice it will be a very very very small value. also the tick
76     * callback will adjust the timer interval at the end anyway */
77    if (at_tick)
78      {
79         if (!timer)
80           timer = ecore_timer_add(interval, _ecore_poller_cb_timer, NULL);
81      }
82    else
83      {
84         double t;
85
86         if (!timer)
87           timer = ecore_timer_add(interval, _ecore_poller_cb_timer, NULL);
88         else
89           {
90              t = ecore_time_get();
91              if (interval != poll_cur_interval)
92                {
93                   t -= last_tick; /* time since we last ticked */
94                   /* delete the timer and reset it to tick off in the new
95                    * time interval. at the tick this will be adjusted */
96                   ecore_timer_del(timer);
97                   timer = ecore_timer_add(interval - t,
98                                           _ecore_poller_cb_timer, NULL);
99                }
100           }
101      }
102    poll_cur_interval = interval;
103 }
104
105 static Eina_Bool
106 _ecore_poller_cb_timer(void *data __UNUSED__)
107 {
108    int i;
109    Ecore_Poller *poller, *l;
110    int changes = 0;
111
112    at_tick++;
113    last_tick = ecore_time_get();
114    /* we have 16 counters - each incriments every time the poller counter
115     * "ticks". it incriments by the minimum interval (which can be 1, 2, 4,
116     * 7, 16 etc. up to 32768) */
117    for (i = 0; i < 15; i++)
118      {
119         poller_counters[i] += interval_incr;
120         /* wrap back to 0 if we exceed out loop count for the counter */
121         if (poller_counters[i] >= (1 << i)) poller_counters[i] = 0;
122      }
123
124    just_added_poller = 0;
125    /* walk the pollers now */
126    poller_walking++;
127    for (i = 0; i < 15; i++)
128      {
129         /* if the counter is @ 0 - this means that counter "went off" this
130          * tick interval, so run all pollers hooked to that counter */
131         if (poller_counters[i] == 0)
132           {
133              EINA_INLIST_FOREACH(pollers[i], poller)
134                {
135                   if (!poller->delete_me)
136                     {
137                        if (!poller->func(poller->data))
138                          {
139                             if (!poller->delete_me)
140                               {
141                                  poller->delete_me = 1;
142                                  poller_delete_count++;
143                               }
144                          }
145                     }
146                }
147           }
148      }
149    poller_walking--;
150
151    /* handle deletes afterwards */
152    if (poller_delete_count > 0)
153      {
154         /* FIXME: walk all pollers and remove deleted ones */
155         for (i = 0; i < 15; i++)
156           {
157              for (l = pollers[i]; l;)
158                {
159                   poller = l;
160                   l = (Ecore_Poller *) EINA_INLIST_GET(l)->next;
161                   if (poller->delete_me)
162                     {
163                        pollers[i] = (Ecore_Poller *) eina_inlist_remove(EINA_INLIST_GET(pollers[i]), EINA_INLIST_GET(poller));
164                        free(poller);
165                        poller_delete_count--;
166                        changes++;
167                        if (poller_delete_count <= 0) break;
168                     }
169                }
170              if (poller_delete_count <= 0) break;
171           }
172      }
173    /* if we deleted or added any pollers, then we need to re-evaluate our
174     * minimum poll interval */
175    if ((changes > 0) || (just_added_poller > 0))
176      _ecore_poller_next_tick_eval();
177
178    just_added_poller = 0;
179    poller_delete_count = 0;
180
181    at_tick--;
182
183    /* if the timer was deleted then there is no point returning 1 - ambiguous
184     * if we do as it im plies "keep running me" but we have been deleted
185     * anyway */
186    if (!timer) return ECORE_CALLBACK_CANCEL;
187
188    /* adjust interval */
189    ecore_timer_interval_set(timer, poll_cur_interval);
190    return ECORE_CALLBACK_RENEW;
191 }
192
193 /**
194  * @defgroup Ecore_Poll_Group Ecore Poll Functions
195  *
196  * These functions are for the need to poll information, but provide a shared
197  * abstracted API to pool such polling to minimise wakeup and ensure all the
198  * polling happens in as few spots as possible areound a core poll interval.
199  * For now only 1 core poller type is supprted: ECORE_POLLER_CORE
200  */
201
202
203 /**
204  * Sets the time between ticks (in seconds) for the given ticker clock.
205  * @param   type The ticker type to adjust
206  * @param   poll_time The time (in seconds) between ticks of the clock
207  * @ingroup Ecore_Poller_Group
208  *
209  * This will adjust the time between ticks of the given ticker type defined
210  * by @p type to the time period defined by @p poll_time.
211  */
212 EAPI void
213 ecore_poller_poll_interval_set(Ecore_Poller_Type type __UNUSED__, double poll_time)
214 {
215    poll_interval = poll_time;
216    _ecore_poller_next_tick_eval();
217 }
218
219 /**
220  * Gets the time between ticks (in seconds) for the given ticker clock.
221  * @param   type The ticker type to query
222  * @return  The time in seconds between ticks of the ticker clock
223  * @ingroup Ecore_Poller_Group
224  *
225  * This will get the time between ticks of the specifider ticker clock.
226  */
227 EAPI double
228 ecore_poller_poll_interval_get(Ecore_Poller_Type type __UNUSED__)
229 {
230    return poll_interval;
231 }
232
233 /**
234  * Creates a poller to call the given function at a particular tick interval.
235  * @param   type The ticker type to attach the poller to
236  * @param   interval The poll interval
237  * @param   func The given function.  If @p func returns 1, the poller is
238  *               rescheduled for the next tick interval.
239  * @param   data Data to pass to @p func when it is called.
240  * @return  A poller object on success.  @c NULL on failure.
241  * @ingroup Ecore_Poller_Group
242  *
243  * This function adds a poller callback that is to be called regularly
244  * along with all other poller callbacks so the pollers are synchronized with
245  * all other pollers running off the same poller type and at the same tick
246  * interval. This should be used for polling things when polling is desired
247  * or required, and you do not have specific requirements on the exact times
248  * to poll and want to avoid extra process wakeups for polling. This will
249  * save power as the CPU has more of a chance to go into a low power state
250  * the longer it is asleep for, so this should be used if you are at all
251  * power conscious.
252  *
253  * The @p type parameter defines the poller tick type (there is a virtual
254  * clock ticking all the time - though ecore avoids making it tick when
255  * there will not be any work to do at that tick point). There is only one
256  * ticker at the moment - that is ECORE_POLLER_CORE. This is here for future
257  * expansion if multiple clocks with different frequencies are really required.
258  * The default time between ticks for the ECORE_POLLER_CORE ticker is 0.125
259  * seconds.
260  *
261  * The @p interval is the number of ticker ticks that will pass by in between
262  * invocations of the @p func callback. This must be between 1 and 32768
263  * inclusive, and must be a power of 2 (i.e. 1, 2, 4, 8, 16, ... 16384, 32768).
264  * If it is 1, then the function will be called every tick. if it is 2, then it
265  * will be called every 2nd tick, if it is 8, then every 8th tick etc. Exactly
266  * which tick is undefined, as only the interval between calls can be defined.
267  * Ecore will endeavour to keep pollers synchronised and to call as many in
268  * 1 wakeup event as possible.
269  *
270  * This function adds a poller and returns its handle on success and NULL on
271  * failure. The function @p func will be called at tick intervals described
272  * above. The function will be passed the @p data pointer as its parameter.
273  *
274  * When the poller @p func is called, it must return a value of either
275  * 1 (or ECORE_CALLBACK_RENEW) or 0 (or ECORE_CALLBACK_CANCEL). If it
276  * returns 1, it will be called again at the next tick, or if it returns
277  * 0 it will be deleted automatically making any references/handles for it
278  * invalid.
279  */
280 EAPI Ecore_Poller *
281 ecore_poller_add(Ecore_Poller_Type type __UNUSED__, int interval, Ecore_Task_Cb func, const void *data)
282 {
283    Ecore_Poller *poller;
284    int ibit;
285
286    if (!func) return NULL;
287    if (interval < 1) interval = 1;
288
289    poller = calloc(1, sizeof(Ecore_Poller));
290    if (!poller) return NULL;
291    ECORE_MAGIC_SET(poller, ECORE_MAGIC_POLLER);
292    /* interval MUST be a power of 2, so enforce it */
293    if (interval < 1) interval = 1;
294    ibit = -1;
295    while (interval != 0)
296      {
297         ibit++;
298         interval >>= 1;
299      }
300    /* only allow up to 32768 - i.e. ibit == 15, so limit it */
301    if (ibit > 15) ibit = 15;
302
303    poller->ibit = ibit;
304    poller->func = func;
305    poller->data = (void *)data;
306    pollers[poller->ibit] = (Ecore_Poller *) eina_inlist_prepend(EINA_INLIST_GET(pollers[poller->ibit]), EINA_INLIST_GET(poller));
307    if (poller_walking)
308      just_added_poller++;
309    else
310      _ecore_poller_next_tick_eval();
311    return poller;
312 }
313
314 /**
315  * Changes the polling interval rate of @p poller.
316  *
317  * @param poller The Ecore_Poller to change the interval of
318  * @param interval The tick interval to set; must be a power of 2 but <= 32768
319  * @return Returns true on success, false on failure
320  *
321  * This allows the changing of a poller's polling interval.  It is useful when you want to alter
322  * a poll rate without deleting and re-creating a poller.
323  * @ingroup Ecore_Poller_Group
324  */
325 EAPI Eina_Bool
326 ecore_poller_poller_interval_set(Ecore_Poller *poller, int interval)
327 {
328    int ibit;
329
330    if (!ECORE_MAGIC_CHECK(poller, ECORE_MAGIC_POLLER))
331      {
332         ECORE_MAGIC_FAIL(poller, ECORE_MAGIC_POLLER,
333            "ecore_poller_poller_interval_set");
334         return EINA_FALSE;
335      }
336
337    /* interval MUST be a power of 2, so enforce it */
338    if (interval < 1) interval = 1;
339    ibit = -1;
340    while (interval != 0)
341      {
342        ibit++;
343        interval >>= 1;
344      }
345    /* only allow up to 32768 - i.e. ibit == 15, so limit it */
346    if (ibit > 15) ibit = 15;
347    /* if interval specified is the same as interval set, return true without wasting time */
348    if (poller->ibit == ibit)
349      return EINA_TRUE;
350    pollers[poller->ibit] = (Ecore_Poller *) eina_inlist_remove(EINA_INLIST_GET(pollers[poller->ibit]), EINA_INLIST_GET(poller));
351    poller->ibit = ibit;
352    pollers[poller->ibit] = (Ecore_Poller *) eina_inlist_prepend(EINA_INLIST_GET(pollers[poller->ibit]), EINA_INLIST_GET(poller));
353    if (poller_walking)
354      just_added_poller++;
355    else
356      _ecore_poller_next_tick_eval();
357    return EINA_TRUE;
358 }
359
360 /**
361  * Gets the polling interval rate of @p poller.
362  *
363  * @param poller The Ecore_Poller to change the interval of
364  * @return Returns the interval, in ticks, that @p poller polls at
365  *
366  * This returns a poller's polling interval, or 0 on error.
367  * @ingroup Ecore_Poller_Group
368  */
369 EAPI int
370 ecore_poller_poller_interval_get(Ecore_Poller *poller)
371 {
372    int ibit, interval = 1;
373
374    if (!ECORE_MAGIC_CHECK(poller, ECORE_MAGIC_POLLER))
375      {
376         ECORE_MAGIC_FAIL(poller, ECORE_MAGIC_POLLER,
377            "ecore_poller_poller_interval_get");
378         return 0;
379      }
380
381    ibit = poller->ibit;
382    while (ibit != 0)
383      {
384        ibit--;
385        interval <<= 1;
386      }
387    return interval;
388 }
389
390 /**
391  * Delete the specified poller from the timer list.
392  * @param   poller The poller to delete.
393  * @return  The data pointer set for the timer when @ref ecore_poller_add was
394  *          called.  @c NULL is returned if the function is unsuccessful.
395  * @ingroup Ecore_Poller_Group
396  *
397  * Note: @p poller must be a valid handle. If the poller function has already
398  * returned 0, the handle is no longer valid (and does not need to be delete).
399  */
400 EAPI void *
401 ecore_poller_del(Ecore_Poller *poller)
402 {
403    void *data;
404
405    if (!ECORE_MAGIC_CHECK(poller, ECORE_MAGIC_POLLER))
406      {
407         ECORE_MAGIC_FAIL(poller, ECORE_MAGIC_POLLER,
408            "ecore_poller_del");
409         return NULL;
410      }
411    /* we are walking the poller list - a bad idea to remove from it while
412     * walking it, so just flag it as delete_me and come back to it after
413     * the loop has finished */
414    if (poller_walking > 0)
415      {
416         poller_delete_count++;
417         poller->delete_me = 1;
418         return poller->data;
419      }
420    /* not in loop so safe - delete immediately */
421    data = poller->data;
422    pollers[poller->ibit] = (Ecore_Poller *) eina_inlist_remove(EINA_INLIST_GET(pollers[poller->ibit]), EINA_INLIST_GET(poller));
423    free(poller);
424    _ecore_poller_next_tick_eval();
425    return data;
426 }
427
428 void
429 _ecore_poller_shutdown(void)
430 {
431    int i;
432    Ecore_Poller *poller;
433
434    for (i = 0; i < 15; i++)
435      {
436         while ((poller = pollers[i]))
437           {
438              pollers[i] = (Ecore_Poller *) eina_inlist_remove(EINA_INLIST_GET(pollers[i]), EINA_INLIST_GET(pollers[i]));
439              free(poller);
440           }
441      }
442 }