svn update: 48958 (latest:48959)
[framework/uifw/ecore.git] / src / lib / ecore / ecore_poll.c
1 /*
2  * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
3  */
4
5 #ifdef HAVE_CONFIG_H
6 # include <config.h>
7 #endif
8
9 #include <stdlib.h>
10
11 #include "Ecore.h"
12 #include "ecore_private.h"
13
14
15 struct _Ecore_Poller
16 {
17    EINA_INLIST;
18    ECORE_MAGIC;
19    int           ibit;
20    unsigned char delete_me : 1;
21    int           (*func) (void *data);
22    void          *data;
23 };
24
25
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] =
37 {
38    NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
39    NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL
40 };
41 static unsigned short  poller_counters[16] =
42 {
43    0,0,0,0,0,0,0,0,
44    0,0,0,0,0,0,0,0
45 };
46
47 static void _ecore_poller_next_tick_eval(void);
48 static int _ecore_poller_cb_timer(void *data);
49
50 static void
51 _ecore_poller_next_tick_eval(void)
52 {
53    int i;
54    double interval;
55
56    min_interval = -1;
57    for (i = 0; i < 15; i++)
58      {
59         if (pollers[i])
60           {
61              min_interval = i;
62              break;
63           }
64      }
65    if (min_interval < 0)
66      {
67         /* no pollers */
68         if (timer)
69           {
70              ecore_timer_del(timer);
71              timer = NULL;
72           }
73         return;
74      }
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 */
81    if (at_tick)
82      {
83         if (!timer)
84           timer = ecore_timer_add(interval, _ecore_poller_cb_timer, NULL);
85      }
86    else
87      {
88         double t;
89
90         if (!timer)
91           timer = ecore_timer_add(interval, _ecore_poller_cb_timer, NULL);
92         else
93           {
94              t = ecore_time_get();
95              if (interval != poll_cur_interval)
96                {
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);
103                }
104           }
105      }
106    poll_cur_interval = interval;
107 }
108
109 static int
110 _ecore_poller_cb_timer(void *data __UNUSED__)
111 {
112    int i;
113    Ecore_Poller *poller, *l;
114    int changes = 0;
115
116    at_tick++;
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++)
122      {
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;
126      }
127
128    just_added_poller = 0;
129    /* walk the pollers now */
130    poller_walking++;
131    for (i = 0; i < 15; i++)
132      {
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)
136           {
137              EINA_INLIST_FOREACH(pollers[i], poller)
138                {
139                   if (!poller->delete_me)
140                     {
141                        if (!poller->func(poller->data))
142                          {
143                             if (!poller->delete_me)
144                               {
145                                  poller->delete_me = 1;
146                                  poller_delete_count++;
147                               }
148                          }
149                     }
150                }
151           }
152      }
153    poller_walking--;
154
155    /* handle deletes afterwards */
156    if (poller_delete_count > 0)
157      {
158         /* FIXME: walk all pollers and remove deleted ones */
159         for (i = 0; i < 15; i++)
160           {
161              for (l = pollers[i]; l;)
162                {
163                   poller = l;
164                   l = (Ecore_Poller *) EINA_INLIST_GET(l)->next;
165                   if (poller->delete_me)
166                     {
167                        pollers[i] = (Ecore_Poller *) eina_inlist_remove(EINA_INLIST_GET(pollers[i]), EINA_INLIST_GET(poller));
168                        free(poller);
169                        poller_delete_count--;
170                        changes++;
171                        if (poller_delete_count <= 0) break;
172                     }
173                }
174              if (poller_delete_count <= 0) break;
175           }
176      }
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();
181
182    just_added_poller = 0;
183    poller_delete_count = 0;
184
185    at_tick--;
186
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
189     * anyway */
190    if (!timer) return 0;
191
192    /* adjust interval */
193    ecore_timer_interval_set(timer, poll_cur_interval);
194    return 1;
195 }
196
197 /**
198  * @defgroup Ecore_Poll_Group Ecore Poll Functions
199  *
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
204  */
205
206
207 /**
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
212  *
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.
215  */
216 EAPI void
217 ecore_poller_poll_interval_set(Ecore_Poller_Type type __UNUSED__, double poll_time)
218 {
219    poll_interval = poll_time;
220    _ecore_poller_next_tick_eval();
221 }
222
223 /**
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
228  *
229  * This will get the time between ticks of the specifider ticker clock.
230  */
231 EAPI double
232 ecore_poller_poll_interval_get(Ecore_Poller_Type type __UNUSED__)
233 {
234    return poll_interval;
235 }
236
237 /**
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
246  *
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
255  * power conscious.
256  *
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
263  * seconds.
264  *
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.
273  *
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.
277  *
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
282  * invalid.
283  */
284 EAPI Ecore_Poller *
285 ecore_poller_add(Ecore_Poller_Type type __UNUSED__, int interval, int (*func) (void *data), const void *data)
286 {
287    Ecore_Poller *poller;
288    int ibit;
289
290    if (!func) return NULL;
291    if (interval < 1) interval = 1;
292
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;
298    ibit = -1;
299    while (interval != 0)
300      {
301         ibit++;
302         interval >>= 1;
303      }
304    /* only allow up to 32768 - i.e. ibit == 15, so limit it */
305    if (ibit > 15) ibit = 15;
306
307    poller->ibit = ibit;
308    poller->func = func;
309    poller->data = (void *)data;
310    pollers[poller->ibit] = (Ecore_Poller *) eina_inlist_prepend(EINA_INLIST_GET(pollers[poller->ibit]), EINA_INLIST_GET(poller));
311    if (poller_walking)
312      just_added_poller++;
313    else
314      _ecore_poller_next_tick_eval();
315    return poller;
316 }
317
318 /**
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
324  *
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).
327  */
328 EAPI void *
329 ecore_poller_del(Ecore_Poller *poller)
330 {
331    void *data;
332
333    if (!ECORE_MAGIC_CHECK(poller, ECORE_MAGIC_POLLER))
334      {
335         ECORE_MAGIC_FAIL(poller, ECORE_MAGIC_POLLER,
336                          "ecore_poller_del");
337         return NULL;
338      }
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)
343      {
344         poller_delete_count++;
345         poller->delete_me = 1;
346         return poller->data;
347      }
348    /* not in loop so safe - delete immediately */
349    data = poller->data;
350    pollers[poller->ibit] = (Ecore_Poller *) eina_inlist_remove(EINA_INLIST_GET(pollers[poller->ibit]), EINA_INLIST_GET(poller));
351    free(poller);
352    _ecore_poller_next_tick_eval();
353    return data;
354 }
355
356 void
357 _ecore_poller_shutdown(void)
358 {
359    int i;
360    Ecore_Poller *poller;
361
362    for (i = 0; i < 15; i++)
363      {
364         while ((poller = pollers[i]))
365           {
366              pollers[i] = (Ecore_Poller *) eina_inlist_remove(EINA_INLIST_GET(pollers[i]), EINA_INLIST_GET(pollers[i]));
367              free(poller);
368           }
369      }
370 }