rewrite ecore_timer internals to make it simpler and do better with
recursive main loops. Unlike idlers, timers seems to work reasonably well with main loops, I *think* they might fail since it used a boolean to flag running as opposed to a reference count with incremental increments/decrements. I could not write a test case to demonstrate so. The now code should be simpler, particularly the _ecore_timer_call(). It will also consider the previous position when entering recursive main loops, preserving the order. Deletion of timers are delegated to ecore_main.c, that was already calling _ecore_timer_cleanup() after timers were executed. SVN revision: 46416
This commit is contained in:
parent
34f6da920a
commit
0bdbf9d147
|
@ -23,10 +23,10 @@ struct _Ecore_Timer
|
|||
int (*func) (void *data);
|
||||
void *data;
|
||||
|
||||
int references;
|
||||
unsigned char delete_me : 1;
|
||||
unsigned char just_added : 1;
|
||||
unsigned char frozen : 1;
|
||||
unsigned char running : 1;
|
||||
};
|
||||
|
||||
|
||||
|
@ -35,6 +35,7 @@ static void _ecore_timer_set(Ecore_Timer *timer, double at, double in, int (*fun
|
|||
static int timers_added = 0;
|
||||
static int timers_delete_me = 0;
|
||||
static Ecore_Timer *timers = NULL;
|
||||
static Ecore_Timer *timer_current = NULL;
|
||||
static Ecore_Timer *suspended = NULL;
|
||||
static double last_check = 0.0;
|
||||
static double precision = 10.0 / 1000000.0;
|
||||
|
@ -176,7 +177,7 @@ ecore_timer_del(Ecore_Timer *timer)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if (timer->frozen && !timer->running)
|
||||
if (timer->frozen && !timer->references)
|
||||
{
|
||||
void *data = timer->data;
|
||||
|
||||
|
@ -309,8 +310,7 @@ ecore_timer_freeze(Ecore_Timer *timer)
|
|||
if (timer->frozen)
|
||||
return ;
|
||||
|
||||
if (!timer->running)
|
||||
timers = (Ecore_Timer *) eina_inlist_remove(EINA_INLIST_GET(timers), EINA_INLIST_GET(timer));
|
||||
timers = (Ecore_Timer *) eina_inlist_remove(EINA_INLIST_GET(timers), EINA_INLIST_GET(timer));
|
||||
suspended = (Ecore_Timer *) eina_inlist_prepend(EINA_INLIST_GET(suspended), EINA_INLIST_GET(timer));
|
||||
|
||||
now = ecore_time_get();
|
||||
|
@ -360,12 +360,15 @@ _ecore_timer_shutdown(void)
|
|||
ECORE_MAGIC_SET(timer, ECORE_MAGIC_NONE);
|
||||
free(timer);
|
||||
}
|
||||
|
||||
timer_current = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
_ecore_timer_cleanup(void)
|
||||
{
|
||||
Ecore_Timer *l;
|
||||
int in_use = 0;
|
||||
|
||||
if (!timers_delete_me) return;
|
||||
for (l = timers; l;)
|
||||
|
@ -375,6 +378,11 @@ _ecore_timer_cleanup(void)
|
|||
l = (Ecore_Timer *) EINA_INLIST_GET(l)->next;
|
||||
if (timer->delete_me)
|
||||
{
|
||||
if (timer->references)
|
||||
{
|
||||
in_use++;
|
||||
continue;
|
||||
}
|
||||
timers = (Ecore_Timer *) eina_inlist_remove(EINA_INLIST_GET(timers), EINA_INLIST_GET(timer));
|
||||
ECORE_MAGIC_SET(timer, ECORE_MAGIC_NONE);
|
||||
free(timer);
|
||||
|
@ -389,6 +397,11 @@ _ecore_timer_cleanup(void)
|
|||
l = (Ecore_Timer *) EINA_INLIST_GET(l)->next;
|
||||
if (timer->delete_me)
|
||||
{
|
||||
if (timer->references)
|
||||
{
|
||||
in_use++;
|
||||
continue;
|
||||
}
|
||||
suspended = (Ecore_Timer *) eina_inlist_remove(EINA_INLIST_GET(suspended), EINA_INLIST_GET(timer));
|
||||
ECORE_MAGIC_SET(timer, ECORE_MAGIC_NONE);
|
||||
free(timer);
|
||||
|
@ -396,7 +409,13 @@ _ecore_timer_cleanup(void)
|
|||
if (timers_delete_me == 0) return;
|
||||
}
|
||||
}
|
||||
timers_delete_me = 0;
|
||||
|
||||
if ((!in_use) && (timers_delete_me))
|
||||
{
|
||||
ERR("%d timers to delete, but they were not found! reset counter.",
|
||||
timers_delete_me);
|
||||
timers_delete_me = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -469,58 +488,66 @@ _ecore_timer_next_get(void)
|
|||
int
|
||||
_ecore_timer_call(double when)
|
||||
{
|
||||
Ecore_Timer *timer, *l;
|
||||
|
||||
if (!timers) return 0;
|
||||
if (last_check > when)
|
||||
{
|
||||
Ecore_Timer *timer;
|
||||
/* User set time backwards */
|
||||
EINA_INLIST_FOREACH(timers, timer) timer->at -= (last_check - when);
|
||||
}
|
||||
last_check = when;
|
||||
for (l = timers; l;)
|
||||
|
||||
if (!timer_current)
|
||||
{
|
||||
timer = l;
|
||||
l = (Ecore_Timer *) EINA_INLIST_GET(l)->next;
|
||||
// printf("_ecore_timer_call %3.3f <= %3.3f %i %i %p\n",
|
||||
// timer->at, when, timer->just_added, timer->delete_me, timer);
|
||||
if ((timer->at <= when) &&
|
||||
(timer->just_added == 0) &&
|
||||
(timer->delete_me == 0))
|
||||
/* regular main loop, start from head */
|
||||
timer_current = timers;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* recursive main loop, continue from where we were */
|
||||
timer_current = (Ecore_Timer *)EINA_INLIST_GET(timer_current)->next;
|
||||
}
|
||||
|
||||
while (timer_current)
|
||||
{
|
||||
Ecore_Timer *timer = timer_current;
|
||||
|
||||
if (timer->at > when)
|
||||
{
|
||||
timer->running = EINA_TRUE;
|
||||
timer_current = NULL; /* ended walk, next should restart. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((timer->just_added) || (timer->delete_me))
|
||||
{
|
||||
timer_current = (Ecore_Timer*)EINA_INLIST_GET(timer_current)->next;
|
||||
continue;
|
||||
}
|
||||
|
||||
timer->references++;
|
||||
if (!timer->func(timer->data)) ecore_timer_del(timer);
|
||||
timer->references--;
|
||||
|
||||
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 ((!timer->delete_me) && (timer->func(timer->data)))
|
||||
{
|
||||
/* 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->delete_me)
|
||||
{
|
||||
timer->running = EINA_FALSE;
|
||||
|
||||
if (!timer->frozen)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
else
|
||||
free(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
|
||||
free(timer);
|
||||
_ecore_timer_call(when);
|
||||
return 1;
|
||||
_ecore_timer_set(timer, timer->at + timer->in, timer->in, timer->func, timer->data);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
|
Loading…
Reference in New Issue