static inline void _ecore_timer_reschedule(Ecore_Timer * timer, double when) { if ((timer->delete_me) || (timer->frozen)) return; timers = (Ecore_Timer *) eina_inlist_remove(EINA_INLIST_GET(timers), EINA_INLIST_GET(timer)); /* if the timer would have gone off more than 15 seconds ago, * assume that the system hung and set the timer to go off * timer->in from now. this handles system hangs, suspends * and more, so ecore will only "replay" the timers while * the system is suspended if it is suspended for less than * 15 seconds (basically). this also handles if the process * is stopped in a debugger or IO and other handling gets * really slow within the main loop. */ if ((timer->at + timer->in) < (when - 15.0)) _ecore_timer_set(timer, when + timer->in, timer->in, timer->func, timer->data); else _ecore_timer_set(timer, timer->at + timer->in, timer->in, timer->func, timer->data); }
static Eina_Bool _ecore_timer_add(Ecore_Timer *obj, Ecore_Timer_Private_Data *timer, double now, double in, Ecore_Task_Cb func, const void *data) { if (EINA_UNLIKELY(!eina_main_loop_is())) { eo_error_set(obj); EINA_MAIN_LOOP_CHECK_RETURN_VAL(EINA_FALSE); } timer->obj = obj; eo_do_super(obj, eo_constructor()); eo_manual_free_set(obj, EINA_TRUE); if (!func) { eo_error_set(obj); ERR("callback function must be set up for an object of class: '%s'", MY_CLASS_NAME); return EINA_FALSE; } if (in < 0.0) in = 0.0; #ifdef WANT_ECORE_TIMER_DUMP timer->timer_bt_num = backtrace((void **)(timer->timer_bt), ECORE_TIMER_DEBUG_BT_NUM); #endif _ecore_timer_set(obj, now + in, in, func, (void *)data); return EINA_TRUE; }
/** * Resumes a frozen (paused) timer. * * @param timer The timer to be resumed. * * The timer will be resumed from its previous relative position in time. That * means, if it had X seconds remaining until expire when it was paused, it will * be started now with those same X seconds remaining to expire again. But * notice that the interval time won't be touched by this call or by * ecore_timer_freeze(). * * @see ecore_timer_freeze() */ EAPI void ecore_timer_thaw(Ecore_Timer *timer) { double now; _ecore_lock(); if (!ECORE_MAGIC_CHECK(timer, ECORE_MAGIC_TIMER)) { ECORE_MAGIC_FAIL(timer, ECORE_MAGIC_TIMER, "ecore_timer_thaw"); goto unlock; } /* Timer not frozen */ if (!timer->frozen) goto unlock; suspended = (Ecore_Timer *)eina_inlist_remove(EINA_INLIST_GET(suspended), EINA_INLIST_GET(timer)); now = ecore_time_get(); _ecore_timer_set(timer, timer->pending + now, timer->in, timer->func, timer->data); unlock: _ecore_unlock(); }
/** * Creates a timer to call the given function in the given period of time. * @param in The interval in seconds. * @param func The given function. If @p func returns 1, the timer is * rescheduled for the next interval @p in. * @param data Data to pass to @p func when it is called. * @return A timer object on success. @c NULL on failure. * * This function adds a timer and returns its handle on success and NULL on * failure. The function @p func will be called every @p in seconds. The * function will be passed the @p data pointer as its parameter. * * When the timer @p func is called, it must return a value of either 1 * (or ECORE_CALLBACK_RENEW) or 0 (or ECORE_CALLBACK_CANCEL). * If it returns 1, it will be called again at the next tick, or if it returns * 0 it will be deleted automatically making any references/handles for it * invalid. */ EAPI Ecore_Timer * ecore_timer_add(double in, Ecore_Task_Cb func, const void *data) { double now; Ecore_Timer *timer = NULL; _ecore_lock(); if (!func) goto unlock; if (in < 0.0) in = 0.0; timer = ecore_timer_calloc(1); if (!timer) goto unlock; ECORE_MAGIC_SET(timer, ECORE_MAGIC_TIMER); now = ecore_time_get(); #ifdef WANT_ECORE_TIMER_DUMP timer->timer_bt_num = backtrace((void **)(timer->timer_bt), ECORE_TIMER_DEBUG_BT_NUM); #endif _ecore_timer_set(timer, now + in, in, func, (void *)data); unlock: _ecore_unlock(); return timer; }
/** * Creates a timer to call the given function in the given period of time. * @param in The interval in seconds from current loop time. * @param func The given function. If @p func returns 1, the timer is * rescheduled for the next interval @p in. * @param data Data to pass to @p func when it is called. * @return A timer object on success. @c NULL on failure. * * This is the same as ecore_timer_add(), but "now" is the time from * ecore_loop_time_get() not ecore_time_get() as ecore_timer_add() uses. See * ecore_timer_add() for more details. */ EAPI Ecore_Timer * ecore_timer_loop_add(double in, Ecore_Task_Cb func, const void *data) { double now; Ecore_Timer *timer; if (!func) return NULL; if (in < 0.0) in = 0.0; timer = calloc(1, sizeof(Ecore_Timer)); if (!timer) return NULL; ECORE_MAGIC_SET(timer, ECORE_MAGIC_TIMER); now = ecore_loop_time_get(); _ecore_timer_set(timer, now + in, in, func, (void *)data); return timer; }
/** * Add some delay for the next occurrence of a timer. * This doesn't affect the interval of a timer. * * @param timer The timer to change. * @param add The dalay to add to the next iteration. * @ingroup Ecore_Time_Group */ EAPI void ecore_timer_delay(Ecore_Timer * timer, double add) { if (!ECORE_MAGIC_CHECK(timer, ECORE_MAGIC_TIMER)) { ECORE_MAGIC_FAIL(timer, ECORE_MAGIC_TIMER, "ecore_timer_delay"); return; } if (timer->frozen) { timer->pending += add; } else { timers = (Ecore_Timer *) eina_inlist_remove(EINA_INLIST_GET(timers), EINA_INLIST_GET(timer)); _ecore_timer_set(timer, timer->at + add, timer->in, timer->func, timer->data); } }