9 #include "ecore_private.h"
11 #ifdef WANT_ECORE_TIMER_DUMP
13 # include <execinfo.h>
14 # define ECORE_TIMER_DEBUG_BT_NUM 64
15 typedef void (*Ecore_Timer_Bt_Func)();
28 #ifdef WANT_ECORE_TIMER_DUMP
29 Ecore_Timer_Bt_Func timer_bt[ECORE_TIMER_DEBUG_BT_NUM];
34 unsigned char delete_me : 1;
35 unsigned char just_added : 1;
36 unsigned char frozen : 1;
38 GENERIC_ALLOC_SIZE_DECLARE(Ecore_Timer);
40 static void _ecore_timer_set(Ecore_Timer *timer,
45 #ifdef WANT_ECORE_TIMER_DUMP
46 static int _ecore_timer_cmp(const void *d1,
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;
59 * @addtogroup Ecore_Timer_Group
65 * Retrieves the current precision used by timer infrastructure.
66 * @return Current precision.
67 * @see ecore_timer_precision_set()
70 ecore_timer_precision_get(void)
72 EINA_MAIN_LOOP_CHECK_RETURN_VAL(0.0);
77 * @brief Sets the precision to be used by timer infrastructure.
79 * @param value allowed introduced timeout delay, in seconds.
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.
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.
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.
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.
102 ecore_timer_precision_set(double value)
104 EINA_MAIN_LOOP_CHECK_RETURN;
109 ERR("Precision %f less than zero, ignored", value);
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.
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.
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
137 ecore_timer_add(double in,
142 Ecore_Timer *timer = NULL;
144 EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
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();
153 #ifdef WANT_ECORE_TIMER_DUMP
154 timer->timer_bt_num = backtrace((void **)(timer->timer_bt),
155 ECORE_TIMER_DEBUG_BT_NUM);
158 _ecore_timer_set(timer, now + in, in, func, (void *)data);
165 * Creates a timer to call the given function in the given period of time.
166 * @param in The interval in seconds from current loop time.
167 * @param func The given function. If @p func returns 1, the timer is
168 * rescheduled for the next interval @p in.
169 * @param data Data to pass to @p func when it is called.
170 * @return A timer object on success. @c NULL on failure.
172 * This is the same as ecore_timer_add(), but "now" is the time from
173 * ecore_loop_time_get() not ecore_time_get() as ecore_timer_add() uses. See
174 * ecore_timer_add() for more details.
177 ecore_timer_loop_add(double in,
183 EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
185 timer = _ecore_timer_loop_add(in, func, data);
192 * Delete the specified timer from the timer list.
193 * @param timer The timer to delete.
194 * @return The data pointer set for the timer when @ref ecore_timer_add was
195 * called. @c NULL is returned if the function is unsuccessful.
197 * Note: @p timer must be a valid handle. If the timer function has already
198 * returned 0, the handle is no longer valid (and does not need to be delete).
201 ecore_timer_del(Ecore_Timer *timer)
205 EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
208 if (!ECORE_MAGIC_CHECK(timer, ECORE_MAGIC_TIMER))
210 ECORE_MAGIC_FAIL(timer, ECORE_MAGIC_TIMER,
215 data = _ecore_timer_del(timer);
223 * Change the interval the timer ticks of. If set during
224 * a timer call, this will affect the next interval.
226 * @param timer The timer to change.
227 * @param in The interval in seconds.
230 ecore_timer_interval_set(Ecore_Timer *timer,
233 EINA_MAIN_LOOP_CHECK_RETURN;
235 if (in < 0.0) in = 0.0;
236 if (!ECORE_MAGIC_CHECK(timer, ECORE_MAGIC_TIMER))
238 ECORE_MAGIC_FAIL(timer, ECORE_MAGIC_TIMER,
239 "ecore_timer_interval_set");
248 * Get the interval the timer ticks on.
250 * @param timer The timer to retrieve the interval from
251 * @return The interval on success. -1 on failure.
254 ecore_timer_interval_get(Ecore_Timer *timer)
258 EINA_MAIN_LOOP_CHECK_RETURN_VAL(0.0);
261 if (!ECORE_MAGIC_CHECK(timer, ECORE_MAGIC_TIMER))
263 ECORE_MAGIC_FAIL(timer, ECORE_MAGIC_TIMER,
264 "ecore_timer_interval_get");
269 interval = timer->in;
276 * Add some delay for the next occurrence of a timer.
277 * This doesn't affect the interval of a timer.
279 * @param timer The timer to change.
280 * @param add The delay to add to the next iteration.
283 ecore_timer_delay(Ecore_Timer *timer,
286 EINA_MAIN_LOOP_CHECK_RETURN;
287 if (!ECORE_MAGIC_CHECK(timer, ECORE_MAGIC_TIMER))
289 ECORE_MAGIC_FAIL(timer, ECORE_MAGIC_TIMER,
290 "ecore_timer_delay");
295 _ecore_timer_delay(timer, add);
300 * Reset a timer to its full interval
301 * This doesn't affect the interval of a timer
302 * @param timer The timer
304 * @note This is equivalent to (but faster than)
306 * ecore_timer_delay(timer, ecore_timer_interval_get(timer) - ecore_timer_pending_get(timer));
310 ecore_timer_reset(Ecore_Timer *timer)
313 EINA_MAIN_LOOP_CHECK_RETURN;
314 if (!ECORE_MAGIC_CHECK(timer, ECORE_MAGIC_TIMER))
316 ECORE_MAGIC_FAIL(timer, ECORE_MAGIC_TIMER,
321 now = ecore_time_get();
324 add = timer->pending;
326 add = timer->at - now;
327 _ecore_timer_delay(timer, timer->in - add);
332 * Get the pending time regarding a timer.
334 * @param timer The timer to learn from.
335 * @return The pending time.
336 * @ingroup Ecore_Timer_Group
339 ecore_timer_pending_get(Ecore_Timer *timer)
344 EINA_MAIN_LOOP_CHECK_RETURN_VAL(0.0);
347 if (!ECORE_MAGIC_CHECK(timer, ECORE_MAGIC_TIMER))
349 ECORE_MAGIC_FAIL(timer, ECORE_MAGIC_TIMER,
350 "ecore_timer_pending_get");
354 now = ecore_time_get();
357 ret = timer->pending;
359 ret = timer->at - now;
366 * Pauses a running timer.
368 * @param timer The timer to be paused.
370 * The timer callback won't be called while the timer is paused. The remaining
371 * time until the timer expires will be saved, so the timer can be resumed with
372 * that same remaining time to expire, instead of expiring instantly. Use
373 * ecore_timer_thaw() to resume it.
375 * @note Nothing happens if the timer was already paused.
377 * @see ecore_timer_thaw()
380 ecore_timer_freeze(Ecore_Timer *timer)
384 EINA_MAIN_LOOP_CHECK_RETURN;
387 if (!ECORE_MAGIC_CHECK(timer, ECORE_MAGIC_TIMER))
389 ECORE_MAGIC_FAIL(timer, ECORE_MAGIC_TIMER,
390 "ecore_timer_freeze");
394 /* Timer already frozen */
398 timers = (Ecore_Timer *)eina_inlist_remove(EINA_INLIST_GET(timers), EINA_INLIST_GET(timer));
399 suspended = (Ecore_Timer *)eina_inlist_prepend(EINA_INLIST_GET(suspended), EINA_INLIST_GET(timer));
401 now = ecore_time_get();
403 timer->pending = timer->at - now;
411 * Resumes a frozen (paused) timer.
413 * @param timer The timer to be resumed.
415 * The timer will be resumed from its previous relative position in time. That
416 * means, if it had X seconds remaining until expire when it was paused, it will
417 * be started now with those same X seconds remaining to expire again. But
418 * notice that the interval time won't be touched by this call or by
419 * ecore_timer_freeze().
421 * @see ecore_timer_freeze()
424 ecore_timer_thaw(Ecore_Timer *timer)
428 EINA_MAIN_LOOP_CHECK_RETURN;
431 if (!ECORE_MAGIC_CHECK(timer, ECORE_MAGIC_TIMER))
433 ECORE_MAGIC_FAIL(timer, ECORE_MAGIC_TIMER,
438 /* Timer not frozen */
442 suspended = (Ecore_Timer *)eina_inlist_remove(EINA_INLIST_GET(suspended), EINA_INLIST_GET(timer));
443 now = ecore_time_get();
445 _ecore_timer_set(timer, timer->pending + now, timer->in, timer->func, timer->data);
451 ecore_timer_dump(void)
453 #ifdef WANT_ECORE_TIMER_DUMP
457 Eina_List *tmp = NULL;
458 int living_timer = 0;
459 int unknow_timer = 0;
461 EINA_MAIN_LOOP_CHECK_RETURN(NULL);
463 result = eina_strbuf_new();
465 EINA_INLIST_FOREACH(timers, tm)
466 tmp = eina_list_sorted_insert(tmp, _ecore_timer_cmp, tm);
468 EINA_LIST_FREE(tmp, tm)
473 if (!tm->frozen && !tm->delete_me)
476 strings = backtrace_symbols((void **)tm->timer_bt, tm->timer_bt_num);
477 if (tm->timer_bt_num <= 0 || strings == NULL)
483 eina_strbuf_append_printf(result, "*** timer: %f ***\n", tm->in);
485 eina_strbuf_append(result, "FROZEN\n");
487 eina_strbuf_append(result, "DELETED\n");
488 for (j = 0; j < tm->timer_bt_num; j++)
489 eina_strbuf_append_printf(result, "%s\n", strings[j]);
494 eina_strbuf_append_printf(result, "\n***\nThere is %i living timer.\nWe did lost track of %i timers.\n", living_timer, unknow_timer);
496 out = eina_strbuf_string_steal(result);
497 eina_strbuf_free(result);
511 _ecore_timer_loop_add(double in,
516 Ecore_Timer *timer = NULL;
518 if (!func) return timer;
519 if (in < 0.0) in = 0.0;
520 timer = ecore_timer_calloc(1);
521 if (!timer) return timer;
522 ECORE_MAGIC_SET(timer, ECORE_MAGIC_TIMER);
523 now = ecore_loop_time_get();
525 #ifdef WANT_ECORE_TIMER_DUMP
526 timer->timer_bt_num = backtrace((void **)(timer->timer_bt),
527 ECORE_TIMER_DEBUG_BT_NUM);
529 _ecore_timer_set(timer, now + in, in, func, (void *)data);
534 _ecore_timer_delay(Ecore_Timer *timer,
539 timer->pending += add;
543 timers = (Ecore_Timer *)eina_inlist_remove(EINA_INLIST_GET(timers), EINA_INLIST_GET(timer));
544 _ecore_timer_set(timer, timer->at + add, timer->in, timer->func, timer->data);
549 _ecore_timer_del(Ecore_Timer *timer)
551 if (timer->frozen && !timer->references)
553 void *data = timer->data;
555 suspended = (Ecore_Timer *)eina_inlist_remove(EINA_INLIST_GET(suspended), EINA_INLIST_GET(timer));
557 if (timer->delete_me)
560 ecore_timer_mp_free(timer);
564 EINA_SAFETY_ON_TRUE_RETURN_VAL(timer->delete_me, NULL);
565 timer->delete_me = 1;
571 _ecore_timer_shutdown(void)
575 while ((timer = timers))
577 timers = (Ecore_Timer *)eina_inlist_remove(EINA_INLIST_GET(timers), EINA_INLIST_GET(timers));
578 ECORE_MAGIC_SET(timer, ECORE_MAGIC_NONE);
579 ecore_timer_mp_free(timer);
582 while ((timer = suspended))
584 suspended = (Ecore_Timer *)eina_inlist_remove(EINA_INLIST_GET(suspended), EINA_INLIST_GET(suspended));
585 ECORE_MAGIC_SET(timer, ECORE_MAGIC_NONE);
586 ecore_timer_mp_free(timer);
589 timer_current = NULL;
593 _ecore_timer_cleanup(void)
596 int in_use = 0, todo = timers_delete_me, done = 0;
598 if (!timers_delete_me) return;
599 for (l = timers; l; )
601 Ecore_Timer *timer = l;
603 l = (Ecore_Timer *)EINA_INLIST_GET(l)->next;
604 if (timer->delete_me)
606 if (timer->references)
611 timers = (Ecore_Timer *)eina_inlist_remove(EINA_INLIST_GET(timers), EINA_INLIST_GET(timer));
612 ECORE_MAGIC_SET(timer, ECORE_MAGIC_NONE);
613 ecore_timer_mp_free(timer);
616 if (timers_delete_me == 0) return;
619 for (l = suspended; l; )
621 Ecore_Timer *timer = l;
623 l = (Ecore_Timer *)EINA_INLIST_GET(l)->next;
624 if (timer->delete_me)
626 if (timer->references)
631 suspended = (Ecore_Timer *)eina_inlist_remove(EINA_INLIST_GET(suspended), EINA_INLIST_GET(timer));
632 ECORE_MAGIC_SET(timer, ECORE_MAGIC_NONE);
633 ecore_timer_mp_free(timer);
636 if (timers_delete_me == 0) return;
640 if ((!in_use) && (timers_delete_me))
642 ERR("%d timers to delete, but they were not found!"
643 "Stats: todo=%d, done=%d, pending=%d, in_use=%d. "
645 timers_delete_me, todo, done, todo - done, in_use);
646 timers_delete_me = 0;
651 _ecore_timer_enable_new(void)
655 if (!timers_added) return;
657 EINA_INLIST_FOREACH(timers, timer) timer->just_added = 0;
661 _ecore_timers_exists(void)
663 Ecore_Timer *timer = timers;
665 while ((timer) && (timer->delete_me))
666 timer = (Ecore_Timer *)EINA_INLIST_GET(timer)->next;
671 static inline Ecore_Timer *
672 _ecore_timer_first_get(void)
674 Ecore_Timer *timer = timers;
676 while ((timer) && ((timer->delete_me) || (timer->just_added)))
677 timer = (Ecore_Timer *)EINA_INLIST_GET(timer)->next;
682 static inline Ecore_Timer *
683 _ecore_timer_after_get(Ecore_Timer *base)
685 Ecore_Timer *timer = (Ecore_Timer *)EINA_INLIST_GET(base)->next;
686 Ecore_Timer *valid_timer = NULL;
687 double maxtime = base->at + precision;
689 while ((timer) && (timer->at < maxtime))
691 if (!((timer->delete_me) || (timer->just_added)))
693 timer = (Ecore_Timer *)EINA_INLIST_GET(timer)->next;
700 _ecore_timer_next_get(void)
704 Ecore_Timer *first, *second;
706 first = _ecore_timer_first_get();
707 if (!first) return -1;
709 second = _ecore_timer_after_get(first);
710 if (second) first = second;
712 now = ecore_loop_time_get();
713 in = first->at - now;
719 _ecore_timer_reschedule(Ecore_Timer *timer,
722 if ((timer->delete_me) || (timer->frozen)) return;
724 timers = (Ecore_Timer *)eina_inlist_remove(EINA_INLIST_GET(timers), EINA_INLIST_GET(timer));
726 /* if the timer would have gone off more than 15 seconds ago,
727 * assume that the system hung and set the timer to go off
728 * timer->in from now. this handles system hangs, suspends
729 * and more, so ecore will only "replay" the timers while
730 * the system is suspended if it is suspended for less than
731 * 15 seconds (basically). this also handles if the process
732 * is stopped in a debugger or IO and other handling gets
733 * really slow within the main loop.
735 if ((timer->at + timer->in) < (when - 15.0))
736 _ecore_timer_set(timer, when + timer->in, timer->in, timer->func, timer->data);
738 _ecore_timer_set(timer, timer->at + timer->in, timer->in, timer->func, timer->data);
741 /* assume that we hold the ecore lock when entering this function */
743 _ecore_timer_expired_timers_call(double when)
745 /* call the first expired timer until no expired timers exist */
746 while (_ecore_timer_expired_call(when)) ;
749 /* assume that we hold the ecore lock when entering this function */
751 _ecore_timer_expired_call(double when)
753 if (!timers) return 0;
754 if (last_check > when)
757 /* User set time backwards */
758 EINA_INLIST_FOREACH(timers, timer) timer->at -= (last_check - when);
764 /* regular main loop, start from head */
765 timer_current = timers;
769 /* recursive main loop, continue from where we were */
770 Ecore_Timer *timer_old = timer_current;
771 timer_current = (Ecore_Timer *)EINA_INLIST_GET(timer_current)->next;
772 _ecore_timer_reschedule(timer_old, when);
775 while (timer_current)
777 Ecore_Timer *timer = timer_current;
779 if (timer->at > when)
781 timer_current = NULL; /* ended walk, next should restart. */
785 if ((timer->just_added) || (timer->delete_me))
787 timer_current = (Ecore_Timer *)EINA_INLIST_GET(timer_current)->next;
792 if (!_ecore_call_task_cb(timer->func, timer->data))
794 if (!timer->delete_me) _ecore_timer_del(timer);
798 if (timer_current) /* may have changed in recursive main loops */
799 timer_current = (Ecore_Timer *)EINA_INLIST_GET(timer_current)->next;
801 _ecore_timer_reschedule(timer, when);
807 _ecore_timer_set(Ecore_Timer *timer,
820 timer->just_added = 1;
822 timer->pending = 0.0;
825 EINA_INLIST_REVERSE_FOREACH(EINA_INLIST_GET(timers), t2)
827 if (timer->at > t2->at)
829 timers = (Ecore_Timer *)eina_inlist_append_relative(EINA_INLIST_GET(timers), EINA_INLIST_GET(timer), EINA_INLIST_GET(t2));
834 timers = (Ecore_Timer *)eina_inlist_prepend(EINA_INLIST_GET(timers), EINA_INLIST_GET(timer));
837 #ifdef WANT_ECORE_TIMER_DUMP
839 _ecore_timer_cmp(const void *d1,
842 const Ecore_Timer *t1 = d1;
843 const Ecore_Timer *t2 = d2;
845 return (int)((t1->in - t2->in) * 100);