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, &times);
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:
Lucas De Marchi 2010-05-28 02:31:02 +00:00
parent 66c015f3cc
commit 98d843e91b
2 changed files with 69 additions and 18 deletions

View File

@ -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;
}

View File

@ -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, &times);
/* 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);
}