From c0f511c5cb8f7c85ea32676e30108c26042d5c56 Mon Sep 17 00:00:00 2001 From: lucas Date: Fri, 28 May 2010 02:31:02 +0000 Subject: [PATCH] Reschedule timer_current in case of inner mainloop Timers' list is and *ordered list*. Therefore, timers can be added before timer_current in an inner mainloop. Reschedule timer_current in this case before looping through timers' list. Thanks to Barbieri for the insight. The following test didn't work before and it's ok now (I'm adding it to ecore_suite too). static int _timer3(void *data) { printf("timer 3, do nothing\n"); return 0; } static int _timer2(void *data) { printf("timer 2, quit inner\n"); ecore_main_loop_quit(); return 0; } static int _timer1(void *data) { int *times = data; (*times)++; printf("BEGIN: inner\n"); ecore_timer_add(0.3, _timer2, NULL); ecore_timer_add(0.1, _timer3, NULL); ecore_main_loop_begin(); printf("END: inner\n"); ecore_main_loop_quit(); return 0; } int main(void) { int times = 0; ecore_init(); ecore_timer_add(1.0, _timer1, ×); printf("BEGIN: main\n"); ecore_main_loop_begin(); assert(times == 1); printf("timer1 called %d times \n", times); printf("END: main\n"); return 0; } By: Lucas De Marchi git-svn-id: http://svn.enlightenment.org/svn/e/trunk/ecore@49245 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33 --- src/lib/ecore/ecore_timer.c | 43 +++++++++++++++++++++++++------------------ src/tests/ecore_test_ecore.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 18 deletions(-) diff --git a/src/lib/ecore/ecore_timer.c b/src/lib/ecore/ecore_timer.c index 8d13c06..995d6c2 100644 --- a/src/lib/ecore/ecore_timer.c +++ b/src/lib/ecore/ecore_timer.c @@ -485,6 +485,28 @@ _ecore_timer_next_get(void) return in; } +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); +} + int _ecore_timer_call(double when) { @@ -505,7 +527,9 @@ _ecore_timer_call(double when) else { /* recursive main loop, continue from where we were */ + Ecore_Timer *timer_old = timer_current; timer_current = (Ecore_Timer *)EINA_INLIST_GET(timer_current)->next; + _ecore_timer_reschedule(timer_old, when); } while (timer_current) @@ -531,24 +555,7 @@ _ecore_timer_call(double when) if (timer_current) /* may have changed in recursive main loops */ timer_current = (Ecore_Timer *)EINA_INLIST_GET(timer_current)->next; - if ((!timer->delete_me) && (!timer->frozen)) - { - 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); - } + _ecore_timer_reschedule(timer, when); } return 0; } diff --git a/src/tests/ecore_test_ecore.c b/src/tests/ecore_test_ecore.c index fc0c668..69430ef 100644 --- a/src/tests/ecore_test_ecore.c +++ b/src/tests/ecore_test_ecore.c @@ -150,6 +150,49 @@ START_TEST(ecore_test_ecore_main_loop_timer) } END_TEST +static int _timer3(void *data) +{ + /* timer 3, do nothing */ + return 0; +} + +static int _timer2(void *data) +{ + /* timer 2, quit inner mainloop */ + ecore_main_loop_quit(); + return 0; +} + +static int _timer1(void *data) +{ + /* timer 1, begin inner mainloop */ + int *times = data; + (*times)++; + + ecore_timer_add(0.3, _timer2, NULL); + ecore_timer_add(0.1, _timer3, NULL); + ecore_main_loop_begin(); + + ecore_main_loop_quit(); + + return 0; +} + +START_TEST(ecore_test_ecore_main_loop_timer_inner) +{ + int times = 0; + + ecore_init(); + ecore_timer_add(1.0, _timer1, ×); + + /* BEGIN: outer mainloop */ + ecore_main_loop_begin(); + /*END: outer mainloop */ + + fail_if(times != 1); +} +END_TEST + static int _fd_handler_cb(void *data, Ecore_Fd_Handler *handler __UNUSED__) { @@ -238,4 +281,5 @@ void ecore_test_ecore(TCase *tc) tcase_add_test(tc, ecore_test_ecore_main_loop_timer); tcase_add_test(tc, ecore_test_ecore_main_loop_fd_handler); tcase_add_test(tc, ecore_test_ecore_main_loop_event); + tcase_add_test(tc, ecore_test_ecore_main_loop_timer_inner); } -- 2.7.4