74eee7f645aacd946b0a579870f632c15d0bf603
[framework/uifw/ecore.git] / src / lib / ecore / ecore_poll.c
1 #include "ecore_private.h"
2 #include "Ecore.h"
3
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] = 
15 {
16    NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
17    NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL
18 };
19 static unsigned short  poller_counters[16] = 
20 {
21    0,0,0,0,0,0,0,0,
22    0,0,0,0,0,0,0,0
23 };
24
25 static void _ecore_poller_next_tick_eval(void);
26 static int _ecore_poller_cb_timer(void *data);
27
28 static void
29 _ecore_poller_next_tick_eval(void)
30 {
31    int i;
32    double interval;
33    
34    min_interval = -1;
35    for (i = 0; i < 15; i++)
36      {
37         if (pollers[i])
38           {
39              min_interval = i;
40              break;
41           }
42      }
43    if (min_interval < 0)
44      {
45         /* no pollers */
46         if (timer)
47           {
48              ecore_timer_del(timer);
49              timer = NULL;
50           }
51         return;
52      }
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 */
59    if (at_tick)
60      {
61         if (!timer)
62           timer = ecore_timer_add(interval, _ecore_poller_cb_timer, NULL);
63      }
64    else
65      {
66         double t;
67         
68         if (!timer)
69           timer = ecore_timer_add(interval, _ecore_poller_cb_timer, NULL);
70         else
71           {
72              t = ecore_time_get();
73              if (interval != poll_cur_interval)
74                {
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);
81                }
82           }
83      }
84    poll_cur_interval = interval;
85 }
86
87 static int
88 _ecore_poller_cb_timer(void *data)
89 {
90    int i;
91    Ecore_List2 *l;
92    Ecore_Poller *poller;
93    int changes = 0;
94
95    at_tick++;
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++)
101      {
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;
105      }
106    
107    just_added_poller = 0;
108    /* walk the pollers now */
109    poller_walking++;
110    for (i = 0; i < 15; i++)
111      {
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)
115           {
116              for (l = (Ecore_List2 *)pollers[i]; l; l = l->next)
117                {
118                   poller = (Ecore_Poller *)l;
119                   if (!poller->delete_me)
120                     {
121                        if (!poller->func(poller->data))
122                          {
123                             if (!poller->delete_me)
124                               {
125                                  poller->delete_me = 1;
126                                  poller_delete_count++;
127                               }
128                          }
129                     }
130                }
131           }
132      }
133    poller_walking--;
134         
135    /* handle deletes afterwards */
136    if (poller_delete_count > 0)
137      {
138         /* FIXME: walk all pollers and remove deleted ones */
139         for (i = 0; i < 15; i++)
140           {
141              for (l = (Ecore_List2 *)pollers[i]; l;)
142                {
143                   poller = (Ecore_Poller *)l;
144                   l = l->next;
145                   if (poller->delete_me)
146                     {
147                        pollers[poller->ibit] = _ecore_list2_remove(pollers[poller->ibit], poller);
148                        free(poller);
149                        poller_delete_count--;
150                        changes++;
151                        if (poller_delete_count <= 0) break;
152                     }
153                }
154              if (poller_delete_count <= 0) break;
155           }
156      }
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();
161
162    just_added_poller = 0;
163    poller_delete_count = 0;
164    
165    at_tick--;
166    
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 
169     * anyway */
170    if (!timer) return 0;
171
172    /* adjust interval */
173    ecore_timer_interval_set(timer, poll_cur_interval);
174    return 1;
175 }
176
177 /**
178  * @defgroup Ecore_Poll_Group Ecore Poll Functions
179  *
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
184  */
185
186
187 /**
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
192  * 
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.
195  */
196 EAPI void
197 ecore_poller_poll_interval_set(Ecore_Poller_Type type, double poll_time)
198 {
199    poll_interval = poll_time;
200    _ecore_poller_next_tick_eval();
201 }
202
203 /**
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
208  * 
209  * This will get the time between ticks of the specifider ticker clock.
210  */
211 EAPI double
212 ecore_poller_poll_interval_get(Ecore_Poller_Type type)
213 {
214    return poll_interval;
215 }
216
217 /**
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
226  *
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
235  * power conscious.
236  * 
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
243  * seconds.
244  * 
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.
253  * 
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.
257  * 
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
262  * invalid.
263  */
264 EAPI Ecore_Poller *
265 ecore_poller_add(Ecore_Poller_Type type, int interval, int (*func) (void *data), const void *data)
266 {
267    Ecore_Poller *poller;
268    int ibit;
269    
270    if (!func) return NULL;
271    if (interval < 1) interval = 1;
272    
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;
278    ibit = -1;
279    while (interval != 0)
280      {
281         ibit++;
282         interval >>= 1;
283      }
284    /* only allow up to 32768 - i.e. ibit == 15, so limit it */
285    if (ibit > 15) ibit = 15;
286    
287    poller->ibit = ibit;
288    poller->func = func;
289    poller->data = (void *)data;
290    pollers[poller->ibit] = _ecore_list2_prepend(pollers[poller->ibit], poller);
291    if (poller_walking)
292      just_added_poller++;
293    else
294      _ecore_poller_next_tick_eval();
295    return poller;
296 }
297
298 /**
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
304  *
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).
307  */
308 EAPI void *
309 ecore_poller_del(Ecore_Poller *poller)
310 {
311    void *data;
312    
313    if (!ECORE_MAGIC_CHECK(poller, ECORE_MAGIC_POLLER))
314      {
315         ECORE_MAGIC_FAIL(poller, ECORE_MAGIC_POLLER,
316                          "ecore_poller_del");
317         return NULL;
318      }
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)
323      {
324         poller_delete_count++;
325         poller->delete_me = 1;
326         return poller->data;
327      }
328    /* not in loop so safe - delete immediately */
329    data = poller->data;
330    pollers[poller->ibit] = _ecore_list2_remove(pollers[poller->ibit], poller);
331    free(poller);
332    _ecore_poller_next_tick_eval();
333    return data;
334 }
335
336 void
337 _ecore_poller_shutdown(void)
338 {
339    int i;
340    Ecore_List2 *l;
341    Ecore_Poller *poller;
342    
343    for (i = 0; i < 15; i++)
344      {
345         for (l = (Ecore_List2 *)pollers[i]; l;)
346           {
347              poller = (Ecore_Poller *)l;
348              l = l->next;
349              pollers[poller->ibit] = _ecore_list2_remove(pollers[poller->ibit], poller);
350              free(poller);
351           }
352      }
353 }