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 <lucas.demarchi@profusion.mobi> SVN revision: 49245
This commit is contained in:
parent
66c015f3cc
commit
98d843e91b
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue