tizen 2.3.1 release
[framework/uifw/ecore.git] / src / lib / ecore / ecore_timer.c
1 #ifdef HAVE_CONFIG_H
2 # include <config.h>
3 #endif
4
5 #include <stdlib.h>
6 #include <stdio.h>
7
8 #include "Ecore.h"
9 #include "ecore_private.h"
10
11 #ifdef WANT_ECORE_TIMER_DUMP
12 # include <string.h>
13 # include <execinfo.h>
14 # define ECORE_TIMER_DEBUG_BT_NUM 64
15 typedef void (*Ecore_Timer_Bt_Func)();
16 #endif
17
18 struct _Ecore_Timer
19 {
20    EINA_INLIST;
21                        ECORE_MAGIC;
22    double              in;
23    double              at;
24    double              pending;
25    Ecore_Task_Cb       func;
26    void               *data;
27
28 #ifdef WANT_ECORE_TIMER_DUMP
29    Ecore_Timer_Bt_Func timer_bt[ECORE_TIMER_DEBUG_BT_NUM];
30    int                 timer_bt_num;
31 #endif
32
33    int                 references;
34    unsigned char       delete_me : 1;
35    unsigned char       just_added : 1;
36    unsigned char       frozen : 1;
37 };
38 GENERIC_ALLOC_SIZE_DECLARE(Ecore_Timer);
39
40 static void _ecore_timer_set(Ecore_Timer  *timer,
41                              double        at,
42                              double        in,
43                              Ecore_Task_Cb func,
44                              void         *data);
45 #ifdef WANT_ECORE_TIMER_DUMP
46 static int _ecore_timer_cmp(const void *d1,
47                             const void *d2);
48 #endif
49
50 static int timers_added = 0;
51 static int timers_delete_me = 0;
52 static Ecore_Timer *timers = NULL;
53 static Ecore_Timer *timer_current = NULL;
54 static Ecore_Timer *suspended = NULL;
55 static double last_check = 0.0;
56 static double precision = 10.0 / 1000000.0;
57
58 /**
59  * @addtogroup Ecore_Timer_Group
60  *
61  * @{
62  */
63
64 /**
65  * Retrieves the current precision used by timer infrastructure.
66  * @return Current precision.
67  * @see ecore_timer_precision_set()
68  */
69 EAPI double
70 ecore_timer_precision_get(void)
71 {
72    EINA_MAIN_LOOP_CHECK_RETURN_VAL(0.0);
73    return precision;
74 }
75
76 /**
77  * @brief Sets the precision to be used by timer infrastructure.
78  *
79  * @param value allowed introduced timeout delay, in seconds.
80  *
81  * This sets the precision for @b all timers. The precision determines how much
82  * of an difference from the requested interval is acceptable. One common reason
83  * to use this function is to @b increase the allowed timeout and thus @b
84  * decrease precision of the timers, this is because less precise the timers
85  * result in the system waking up less often and thus consuming less resources.
86  *
87  * Be aware that kernel may delay delivery even further, these delays
88  * are always possible due other tasks having higher priorities or
89  * other scheduler policies.
90  *
91  * Example:
92  *  We have 2 timers, one that expires in a 2.0s and another that
93  *  expires in 2.1s, if precision is 0.1s, then the Ecore will request
94  *  for the next expire to happen in 2.1s and not 2.0s and another one
95  *  of 0.1 as it would before.
96  *
97  * @note Ecore is smart enough to see if there are timers in the
98  * precision range, if it does not, in our example if no second timer
99  * in (T + precision) existed, then it would use the minimum timeout.
100  */
101 EAPI void
102 ecore_timer_precision_set(double value)
103 {
104    EINA_MAIN_LOOP_CHECK_RETURN;
105    _ecore_lock();
106
107    if (value < 0.0)
108      {
109         ERR("Precision %f less than zero, ignored", value);
110         goto unlock;
111      }
112    precision = value;
113
114 unlock:
115    _ecore_unlock();
116 }
117
118 /**
119  * Creates a timer to call the given function in the given period of time.
120  * @param   in   The interval in seconds.
121  * @param   func The given function.  If @p func returns 1, the timer is
122  *               rescheduled for the next interval @p in.
123  * @param   data Data to pass to @p func when it is called.
124  * @return  A timer object on success.  @c NULL on failure.
125  *
126  * This function adds a timer and returns its handle on success and NULL on
127  * failure. The function @p func will be called every @p in seconds. The
128  * function will be passed the @p data pointer as its parameter.
129  *
130  * When the timer @p func is called, it must return a value of either 1
131  * (or ECORE_CALLBACK_RENEW) or 0 (or ECORE_CALLBACK_CANCEL).
132  * If it returns 1, it will be called again at the next tick, or if it returns
133  * 0 it will be deleted automatically making any references/handles for it
134  * invalid.
135  */
136 EAPI Ecore_Timer *
137 ecore_timer_add(double        in,
138                 Ecore_Task_Cb func,
139                 const void   *data)
140 {
141    double now;
142    Ecore_Timer *timer = NULL;
143
144    EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
145    _ecore_lock();
146    if (!func) goto unlock;
147    if (in < 0.0) in = 0.0;
148    timer = ecore_timer_calloc(1);
149    if (!timer) goto unlock;
150    ECORE_MAGIC_SET(timer, ECORE_MAGIC_TIMER);
151    now = ecore_time_get();
152
153 #ifdef WANT_ECORE_TIMER_DUMP
154    timer->timer_bt_num = backtrace((void **)(timer->timer_bt),
155                                    ECORE_TIMER_DEBUG_BT_NUM);
156 #endif
157
158    _ecore_timer_set(timer, now + in, in, func, (void *)data);
159 unlock:
160    _ecore_unlock();
161    return timer;
162 }
163
164 EAPI Ecore_Timer *
165 ecore_timer_loop_add(double        in,
166                      Ecore_Task_Cb func,
167                      const void   *data)
168 {
169    Ecore_Timer *timer;
170
171    EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
172    _ecore_lock();
173    timer = _ecore_timer_loop_add(in, func, data);
174    _ecore_unlock();
175
176    return timer;
177 }
178
179 /**
180  * Delete the specified timer from the timer list.
181  * @param   timer The timer to delete.
182  * @return  The data pointer set for the timer when @ref ecore_timer_add was
183  *          called.  @c NULL is returned if the function is unsuccessful.
184  *
185  * Note: @p timer must be a valid handle. If the timer function has already
186  * returned 0, the handle is no longer valid (and does not need to be delete).
187  */
188 EAPI void *
189 ecore_timer_del(Ecore_Timer *timer)
190 {
191    void *data = NULL;
192    if (!timer) return NULL;
193
194    EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
195    _ecore_lock();
196
197    if (!ECORE_MAGIC_CHECK(timer, ECORE_MAGIC_TIMER))
198      {
199         ECORE_MAGIC_FAIL(timer, ECORE_MAGIC_TIMER,
200                          "ecore_timer_del");
201         goto unlock;
202      }
203
204    data = _ecore_timer_del(timer);
205
206 unlock:
207    _ecore_unlock();
208    return data;
209 }
210
211 /**
212  * Change the interval the timer ticks of. If set during
213  * a timer call, this will affect the next interval.
214  *
215  * @param   timer The timer to change.
216  * @param   in    The interval in seconds.
217  */
218 EAPI void
219 ecore_timer_interval_set(Ecore_Timer *timer,
220                          double       in)
221 {
222    EINA_MAIN_LOOP_CHECK_RETURN;
223    _ecore_lock();
224    if (in < 0.0) in = 0.0;
225    if (!ECORE_MAGIC_CHECK(timer, ECORE_MAGIC_TIMER))
226      {
227         ECORE_MAGIC_FAIL(timer, ECORE_MAGIC_TIMER,
228                          "ecore_timer_interval_set");
229         goto unlock;
230      }
231    timer->in = in;
232 unlock:
233    _ecore_unlock();
234 }
235
236 /**
237  * Get the interval the timer ticks on.
238  *
239  * @param   timer The timer to retrieve the interval from
240  * @return  The interval on success. -1 on failure.
241  */
242 EAPI double
243 ecore_timer_interval_get(Ecore_Timer *timer)
244 {
245    double interval;
246
247    EINA_MAIN_LOOP_CHECK_RETURN_VAL(0.0);
248    _ecore_lock();
249
250    if (!ECORE_MAGIC_CHECK(timer, ECORE_MAGIC_TIMER))
251      {
252         ECORE_MAGIC_FAIL(timer, ECORE_MAGIC_TIMER,
253                          "ecore_timer_interval_get");
254         interval = -1.0;
255         goto unlock;
256      }
257
258    interval = timer->in;
259 unlock:
260    _ecore_unlock();
261    return interval;
262 }
263
264 /**
265  * Add some delay for the next occurrence of a timer.
266  * This doesn't affect the interval of a timer.
267  *
268  * @param   timer The timer to change.
269  * @param   add   The delay to add to the next iteration.
270  */
271 EAPI void
272 ecore_timer_delay(Ecore_Timer *timer,
273                   double       add)
274 {
275    EINA_MAIN_LOOP_CHECK_RETURN;
276    if (!ECORE_MAGIC_CHECK(timer, ECORE_MAGIC_TIMER))
277      {
278         ECORE_MAGIC_FAIL(timer, ECORE_MAGIC_TIMER,
279                          "ecore_timer_delay");
280         return;
281      }
282
283    _ecore_lock();
284    _ecore_timer_delay(timer, add);
285    _ecore_unlock();
286 }
287
288 /**
289  * Reset a timer to its full interval
290  * This doesn't affect the interval of a timer
291  * @param timer The timer
292  * @since 1.2
293  * @note This is equivalent to (but faster than)
294  * @code
295  * ecore_timer_delay(timer, ecore_timer_interval_get(timer) - ecore_timer_pending_get(timer));
296  * @endcode
297  */
298 EAPI void
299 ecore_timer_reset(Ecore_Timer *timer)
300 {
301    double now, add;
302    EINA_MAIN_LOOP_CHECK_RETURN;
303    if (!ECORE_MAGIC_CHECK(timer, ECORE_MAGIC_TIMER))
304      {
305         ECORE_MAGIC_FAIL(timer, ECORE_MAGIC_TIMER,
306                          __func__);
307         return;
308      }
309    _ecore_lock();
310    now = ecore_time_get();
311
312    if (timer->frozen)
313      add = timer->pending;
314    else
315      add = timer->at - now;
316    _ecore_timer_delay(timer, timer->in - add);
317    _ecore_unlock();
318 }
319
320 /**
321  * Get the pending time regarding a timer.
322  *
323  * @param        timer The timer to learn from.
324  * @return The pending time.
325  * @ingroup        Ecore_Timer_Group
326  */
327 EAPI double
328 ecore_timer_pending_get(Ecore_Timer *timer)
329 {
330    double now;
331    double ret = 0.0;
332
333    EINA_MAIN_LOOP_CHECK_RETURN_VAL(0.0);
334    _ecore_lock();
335
336    if (!ECORE_MAGIC_CHECK(timer, ECORE_MAGIC_TIMER))
337      {
338         ECORE_MAGIC_FAIL(timer, ECORE_MAGIC_TIMER,
339                          "ecore_timer_pending_get");
340         goto unlock;
341      }
342
343    now = ecore_time_get();
344
345    if (timer->frozen)
346      ret = timer->pending;
347    else
348      ret = timer->at - now;
349 unlock:
350    _ecore_unlock();
351    return ret;
352 }
353
354 /**
355  * Pauses a running timer.
356  *
357  * @param timer The timer to be paused.
358  *
359  * The timer callback won't be called while the timer is paused. The remaining
360  * time until the timer expires will be saved, so the timer can be resumed with
361  * that same remaining time to expire, instead of expiring instantly.  Use
362  * ecore_timer_thaw() to resume it.
363  *
364  * @note Nothing happens if the timer was already paused.
365  *
366  * @see ecore_timer_thaw()
367  */
368 EAPI void
369 ecore_timer_freeze(Ecore_Timer *timer)
370 {
371    double now;
372
373    EINA_MAIN_LOOP_CHECK_RETURN;
374    _ecore_lock();
375
376    if (!ECORE_MAGIC_CHECK(timer, ECORE_MAGIC_TIMER))
377      {
378         ECORE_MAGIC_FAIL(timer, ECORE_MAGIC_TIMER,
379                          "ecore_timer_freeze");
380         goto unlock;
381      }
382
383    /* Timer already frozen */
384    if (timer->frozen)
385      goto unlock;
386
387    timers = (Ecore_Timer *)eina_inlist_remove(EINA_INLIST_GET(timers), EINA_INLIST_GET(timer));
388    suspended = (Ecore_Timer *)eina_inlist_prepend(EINA_INLIST_GET(suspended), EINA_INLIST_GET(timer));
389
390    now = ecore_time_get();
391
392    timer->pending = timer->at - now;
393    timer->at = 0.0;
394    timer->frozen = 1;
395 unlock:
396    _ecore_unlock();
397 }
398
399 /**
400  * Resumes a frozen (paused) timer.
401  *
402  * @param timer The timer to be resumed.
403  *
404  * The timer will be resumed from its previous relative position in time. That
405  * means, if it had X seconds remaining until expire when it was paused, it will
406  * be started now with those same X seconds remaining to expire again. But
407  * notice that the interval time won't be touched by this call or by
408  * ecore_timer_freeze().
409  *
410  * @see ecore_timer_freeze()
411  */
412 EAPI void
413 ecore_timer_thaw(Ecore_Timer *timer)
414 {
415    double now;
416
417    EINA_MAIN_LOOP_CHECK_RETURN;
418    _ecore_lock();
419
420    if (!ECORE_MAGIC_CHECK(timer, ECORE_MAGIC_TIMER))
421      {
422         ECORE_MAGIC_FAIL(timer, ECORE_MAGIC_TIMER,
423                          "ecore_timer_thaw");
424         goto unlock;
425      }
426
427    /* Timer not frozen */
428    if (!timer->frozen)
429      goto unlock;
430
431    suspended = (Ecore_Timer *)eina_inlist_remove(EINA_INLIST_GET(suspended), EINA_INLIST_GET(timer));
432    now = ecore_time_get();
433
434    _ecore_timer_set(timer, timer->pending + now, timer->in, timer->func, timer->data);
435 unlock:
436    _ecore_unlock();
437 }
438
439 EAPI char *
440 ecore_timer_dump(void)
441 {
442 #ifdef WANT_ECORE_TIMER_DUMP
443    Eina_Strbuf *result;
444    char *out;
445    Ecore_Timer *tm;
446    Eina_List *tmp = NULL;
447    int living_timer = 0;
448    int unknow_timer = 0;
449
450    EINA_MAIN_LOOP_CHECK_RETURN(NULL);
451    _ecore_lock();
452    result = eina_strbuf_new();
453
454    EINA_INLIST_FOREACH(timers, tm)
455      tmp = eina_list_sorted_insert(tmp, _ecore_timer_cmp, tm);
456
457    EINA_LIST_FREE(tmp, tm)
458      {
459         char **strings;
460         int j;
461
462         if (!tm->frozen && !tm->delete_me)
463           living_timer++;
464
465         strings = backtrace_symbols((void **)tm->timer_bt, tm->timer_bt_num);
466         if (tm->timer_bt_num <= 0 || strings == NULL)
467           {
468              unknow_timer++;
469              continue;
470           }
471
472         eina_strbuf_append_printf(result, "*** timer: %f ***\n", tm->in);
473         if (tm->frozen)
474           eina_strbuf_append(result, "FROZEN\n");
475         if (tm->delete_me)
476           eina_strbuf_append(result, "DELETED\n");
477         for (j = 0; j < tm->timer_bt_num; j++)
478           eina_strbuf_append_printf(result, "%s\n", strings[j]);
479
480         free(strings);
481      }
482
483    eina_strbuf_append_printf(result, "\n***\nThere is %i living timer.\nWe did lost track of %i timers.\n", living_timer, unknow_timer);
484
485    out = eina_strbuf_string_steal(result);
486    eina_strbuf_free(result);
487    _ecore_unlock();
488
489    return out;
490 #else
491    return NULL;
492 #endif
493 }
494
495 /**
496  * @}
497  */
498
499 Ecore_Timer *
500 _ecore_timer_loop_add(double        in,
501                       Ecore_Task_Cb func,
502                       const void   *data)
503 {
504    double now;
505    Ecore_Timer *timer = NULL;
506
507    if (!func) return timer;
508    if (in < 0.0) in = 0.0;
509    timer = ecore_timer_calloc(1);
510    if (!timer) return timer;
511    ECORE_MAGIC_SET(timer, ECORE_MAGIC_TIMER);
512    now = ecore_loop_time_get();
513
514 #ifdef WANT_ECORE_TIMER_DUMP
515    timer->timer_bt_num = backtrace((void **)(timer->timer_bt),
516                                    ECORE_TIMER_DEBUG_BT_NUM);
517 #endif
518    _ecore_timer_set(timer, now + in, in, func, (void *)data);
519    return timer;
520 }
521
522 EAPI void
523 _ecore_timer_delay(Ecore_Timer *timer,
524                    double       add)
525 {
526    if (timer->frozen)
527      {
528         timer->pending += add;
529      }
530    else
531      {
532         timers = (Ecore_Timer *)eina_inlist_remove(EINA_INLIST_GET(timers), EINA_INLIST_GET(timer));
533         _ecore_timer_set(timer, timer->at + add, timer->in, timer->func, timer->data);
534      }
535 }
536
537 void *
538 _ecore_timer_del(Ecore_Timer *timer)
539 {
540    if (timer->frozen && !timer->references)
541      {
542         void *data = timer->data;
543
544         suspended = (Ecore_Timer *)eina_inlist_remove(EINA_INLIST_GET(suspended), EINA_INLIST_GET(timer));
545
546         if (timer->delete_me)
547           timers_delete_me--;
548
549         ecore_timer_mp_free(timer);
550         return data;
551      }
552
553    EINA_SAFETY_ON_TRUE_RETURN_VAL(timer->delete_me, NULL);
554    timer->delete_me = 1;
555    timers_delete_me++;
556    return timer->data;
557 }
558
559 void
560 _ecore_timer_shutdown(void)
561 {
562    Ecore_Timer *timer;
563
564    while ((timer = timers))
565      {
566         timers = (Ecore_Timer *)eina_inlist_remove(EINA_INLIST_GET(timers), EINA_INLIST_GET(timers));
567         ECORE_MAGIC_SET(timer, ECORE_MAGIC_NONE);
568         ecore_timer_mp_free(timer);
569      }
570
571    while ((timer = suspended))
572      {
573         suspended = (Ecore_Timer *)eina_inlist_remove(EINA_INLIST_GET(suspended), EINA_INLIST_GET(suspended));
574         ECORE_MAGIC_SET(timer, ECORE_MAGIC_NONE);
575         ecore_timer_mp_free(timer);
576      }
577
578    timer_current = NULL;
579 }
580
581 void
582 _ecore_timer_cleanup(void)
583 {
584    Ecore_Timer *l;
585    int in_use = 0, todo = timers_delete_me, done = 0;
586
587    if (!timers_delete_me) return;
588    for (l = timers; l; )
589      {
590         Ecore_Timer *timer = l;
591
592         l = (Ecore_Timer *)EINA_INLIST_GET(l)->next;
593         if (timer->delete_me)
594           {
595              if (timer->references)
596                {
597                   in_use++;
598                   continue;
599                }
600              timers = (Ecore_Timer *)eina_inlist_remove(EINA_INLIST_GET(timers), EINA_INLIST_GET(timer));
601              ECORE_MAGIC_SET(timer, ECORE_MAGIC_NONE);
602              ecore_timer_mp_free(timer);
603              timers_delete_me--;
604              done++;
605              if (timers_delete_me == 0) return;
606           }
607      }
608    for (l = suspended; l; )
609      {
610         Ecore_Timer *timer = l;
611
612         l = (Ecore_Timer *)EINA_INLIST_GET(l)->next;
613         if (timer->delete_me)
614           {
615              if (timer->references)
616                {
617                   in_use++;
618                   continue;
619                }
620              suspended = (Ecore_Timer *)eina_inlist_remove(EINA_INLIST_GET(suspended), EINA_INLIST_GET(timer));
621              ECORE_MAGIC_SET(timer, ECORE_MAGIC_NONE);
622              ecore_timer_mp_free(timer);
623              timers_delete_me--;
624              done++;
625              if (timers_delete_me == 0) return;
626           }
627      }
628
629    if ((!in_use) && (timers_delete_me))
630      {
631         ERR("%d timers to delete, but they were not found!"
632             "Stats: todo=%d, done=%d, pending=%d, in_use=%d. "
633             "reset counter.",
634             timers_delete_me, todo, done, todo - done, in_use);
635         timers_delete_me = 0;
636      }
637 }
638
639 void
640 _ecore_timer_enable_new(void)
641 {
642    Ecore_Timer *timer;
643
644    if (!timers_added) return;
645    timers_added = 0;
646    EINA_INLIST_FOREACH(timers, timer) timer->just_added = 0;
647 }
648
649 int
650 _ecore_timers_exists(void)
651 {
652    Ecore_Timer *timer = timers;
653
654    while ((timer) && (timer->delete_me))
655      timer = (Ecore_Timer *)EINA_INLIST_GET(timer)->next;
656
657    return !!timer;
658 }
659
660 static inline Ecore_Timer *
661 _ecore_timer_first_get(void)
662 {
663    Ecore_Timer *timer = timers;
664
665    while ((timer) && ((timer->delete_me) || (timer->just_added)))
666      timer = (Ecore_Timer *)EINA_INLIST_GET(timer)->next;
667
668    return timer;
669 }
670
671 static inline Ecore_Timer *
672 _ecore_timer_after_get(Ecore_Timer *base)
673 {
674    Ecore_Timer *timer = (Ecore_Timer *)EINA_INLIST_GET(base)->next;
675    Ecore_Timer *valid_timer = NULL;
676    double maxtime = base->at + precision;
677
678    while ((timer) && (timer->at < maxtime))
679      {
680         if (!((timer->delete_me) || (timer->just_added)))
681           valid_timer = timer;
682         timer = (Ecore_Timer *)EINA_INLIST_GET(timer)->next;
683      }
684
685    return valid_timer;
686 }
687
688 double
689 _ecore_timer_next_get(void)
690 {
691    double now;
692    double in;
693    Ecore_Timer *first, *second;
694
695    first = _ecore_timer_first_get();
696    if (!first) return -1;
697
698    second = _ecore_timer_after_get(first);
699    if (second) first = second;
700
701    now = ecore_loop_time_get();
702    in = first->at - now;
703    if (in < 0) in = 0;
704    return in;
705 }
706
707 static inline void
708 _ecore_timer_reschedule(Ecore_Timer *timer,
709                         double       when)
710 {
711    if ((timer->delete_me) || (timer->frozen)) return;
712
713    timers = (Ecore_Timer *)eina_inlist_remove(EINA_INLIST_GET(timers), EINA_INLIST_GET(timer));
714
715    /* if the timer would have gone off more than 15 seconds ago,
716     * assume that the system hung and set the timer to go off
717     * timer->in from now. this handles system hangs, suspends
718     * and more, so ecore will only "replay" the timers while
719     * the system is suspended if it is suspended for less than
720     * 15 seconds (basically). this also handles if the process
721     * is stopped in a debugger or IO and other handling gets
722     * really slow within the main loop.
723     */
724    if ((timer->at + timer->in) < (when - 15.0))
725      _ecore_timer_set(timer, when + timer->in, timer->in, timer->func, timer->data);
726    else
727      _ecore_timer_set(timer, timer->at + timer->in, timer->in, timer->func, timer->data);
728 }
729
730 /* assume that we hold the ecore lock when entering this function */
731 void
732 _ecore_timer_expired_timers_call(double when)
733 {
734    /* call the first expired timer until no expired timers exist */
735     while (_ecore_timer_expired_call(when)) ;
736 }
737
738 /* assume that we hold the ecore lock when entering this function */
739 int
740 _ecore_timer_expired_call(double when)
741 {
742    if (!timers) return 0;
743    if (last_check > when)
744      {
745         Ecore_Timer *timer;
746         /* User set time backwards */
747         EINA_INLIST_FOREACH(timers, timer) timer->at -= (last_check - when);
748      }
749    last_check = when;
750
751    if (!timer_current)
752      {
753         /* regular main loop, start from head */
754          timer_current = timers;
755      }
756    else
757      {
758         /* recursive main loop, continue from where we were */
759          Ecore_Timer *timer_old = timer_current;
760          timer_current = (Ecore_Timer *)EINA_INLIST_GET(timer_current)->next;
761          _ecore_timer_reschedule(timer_old, when);
762      }
763
764    while (timer_current)
765      {
766         Ecore_Timer *timer = timer_current;
767
768         if (timer->at > when)
769           {
770              timer_current = NULL; /* ended walk, next should restart. */
771              return 0;
772           }
773
774         if ((timer->just_added) || (timer->delete_me))
775           {
776              timer_current = (Ecore_Timer *)EINA_INLIST_GET(timer_current)->next;
777              continue;
778           }
779
780         timer->references++;
781         if (!_ecore_call_task_cb(timer->func, timer->data))
782           {
783              if (!timer->delete_me) _ecore_timer_del(timer);
784           }
785         timer->references--;
786
787         if (timer_current) /* may have changed in recursive main loops */
788           timer_current = (Ecore_Timer *)EINA_INLIST_GET(timer_current)->next;
789
790         _ecore_timer_reschedule(timer, when);
791      }
792    return 0;
793 }
794
795 static void
796 _ecore_timer_set(Ecore_Timer  *timer,
797                  double        at,
798                  double        in,
799                  Ecore_Task_Cb func,
800                  void         *data)
801 {
802    Ecore_Timer *t2;
803
804    timers_added = 1;
805    timer->at = at;
806    timer->in = in;
807    timer->func = func;
808    timer->data = data;
809    timer->just_added = 1;
810    timer->frozen = 0;
811    timer->pending = 0.0;
812    if (timers)
813      {
814         EINA_INLIST_REVERSE_FOREACH(EINA_INLIST_GET(timers), t2)
815           {
816              if (timer->at > t2->at)
817                {
818                   timers = (Ecore_Timer *)eina_inlist_append_relative(EINA_INLIST_GET(timers), EINA_INLIST_GET(timer), EINA_INLIST_GET(t2));
819                   return;
820                }
821           }
822      }
823    timers = (Ecore_Timer *)eina_inlist_prepend(EINA_INLIST_GET(timers), EINA_INLIST_GET(timer));
824 }
825
826 #ifdef WANT_ECORE_TIMER_DUMP
827 static int
828 _ecore_timer_cmp(const void *d1,
829                  const void *d2)
830 {
831    const Ecore_Timer *t1 = d1;
832    const Ecore_Timer *t2 = d2;
833
834    return (int)((t1->in - t2->in) * 100);
835 }
836 #endif