From: barbieri Date: Thu, 13 Nov 2008 20:42:01 +0000 (+0000) Subject: runtime configurable timer precision X-Git-Tag: 2.0_alpha~194^2~1718 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=b259924ac5272991dc14e4fe77c09e117d5df5d6;p=framework%2Fuifw%2Fecore.git runtime configurable timer precision One can now configure the maximum acceptable delay to be introduced by Ecore so possibly more timers will be dispatched together, reducing wakeups and saving more power. git-svn-id: svn+ssh://svn.enlightenment.org/var/svn/e/trunk/ecore@37607 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33 --- diff --git a/src/lib/ecore/Ecore.h b/src/lib/ecore/Ecore.h index ba16915..7403442 100644 --- a/src/lib/ecore/Ecore.h +++ b/src/lib/ecore/Ecore.h @@ -302,6 +302,9 @@ extern "C" { EAPI void ecore_timer_delay(Ecore_Timer *timer, double add); EAPI double ecore_timer_pending_get(Ecore_Timer *timer); + EAPI double ecore_timer_precision_get(void); + EAPI void ecore_timer_precision_set(double precision); + EAPI Ecore_Animator *ecore_animator_add(int (*func) (void *data), const void *data); EAPI void *ecore_animator_del(Ecore_Animator *animator); EAPI void ecore_animator_frametime_set(double frametime); diff --git a/src/lib/ecore/ecore_timer.c b/src/lib/ecore/ecore_timer.c index c270b7f..f795eff 100644 --- a/src/lib/ecore/ecore_timer.c +++ b/src/lib/ecore/ecore_timer.c @@ -8,6 +8,7 @@ static int timers_delete_me = 0; static Ecore_Timer *timers = NULL; static Ecore_Timer *suspended = NULL; static double last_check = 0.0; +static double precision = 10.0 / 1000000.0; /** * @defgroup Ecore_Time_Group Ecore Time Functions @@ -17,6 +18,52 @@ static double last_check = 0.0; */ /** + * Retrieves the current precision used by timer infrastructure. + * + * @see ecore_timer_precision_set() + */ +EAPI double +ecore_timer_precision_get(void) +{ + return precision; +} + +/** + * Sets the precision to be used by timer infrastructure. + * + * When system calculates time to expire the next timer we'll be able + * to delay the timer by the given amount so more timers will fit in + * the same dispatch, waking up the system less often and thus being + * able to save power. + * + * Be aware that kernel may delay delivery even further, these delays + * are always possible due other tasks having higher priorities or + * other scheduler policies. + * + * Example: + * We have 2 timers, one that expires in a 2.0s and another that + * expires in 2.1s, if precision is 0.1s, then the Ecore will request + * for the next expire to happen in 2.1s and not 2.0s and another one + * of 0.1 as it would before. + * + * @note Ecore is smart enough to see if there are timers in the + * precision range, if it does not, in our example if no second timer + * in (T + precision) existed, then it would use the minimum timeout. + * + * @param value allowed introduced timeout delay, in seconds. + */ +EAPI void +ecore_timer_precision_set(double value) +{ + if (value < 0.0) + { + fprintf(stderr, "ERROR: precision %f less than zero, ignored\n", value); + return; + } + precision = value; +} + +/** * 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 @@ -281,23 +328,51 @@ _ecore_timer_enable_new(void) } } +static inline Ecore_Timer * +_ecore_timer_first_get(void) +{ + Ecore_Timer *timer = (Ecore_Timer *)timers; + + while ((timer) && ((timer->delete_me) || (timer->just_added))) + timer = (Ecore_Timer *)((Ecore_List2 *)timer)->next; + + return timer; +} + +static inline Ecore_Timer * +_ecore_timer_after_get(Ecore_Timer *base) +{ + Ecore_Timer *timer = (Ecore_Timer *)((Ecore_List2 *)base)->next; + double maxtime = base->at + precision; + + while ((timer) && ((timer->delete_me) || (timer->just_added)) && (timer->at <= maxtime)) + timer = (Ecore_Timer *)((Ecore_List2 *)timer)->next; + + if ((!timer) || (timer->at > maxtime)) + return NULL; + + return timer; +} + double _ecore_timer_next_get(void) { double now; double in; - Ecore_Timer *timer; - - if (!timers) return -1; + Ecore_Timer *first, *second; + + first = _ecore_timer_first_get(); + if (!first) return -1; + + second = _ecore_timer_after_get(first); + if (second) + first = second; + now = ecore_loop_time_get(); - timer = (Ecore_Timer *)timers; - while ((timer) && ((timer->delete_me) || (timer->just_added))) - timer = (Ecore_Timer *)((Ecore_List2 *)timer)->next; - if (!timer) return -1; - in = timer->at - now; + in = first->at - now; if (in < 0) in = 0; return in; -} +} int _ecore_timer_call(double when)