forked from enlightenment/efl
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);
|
int (*func) (void *data);
|
||||||
void *data;
|
void *data;
|
||||||
|
|
||||||
|
int references;
|
||||||
unsigned char delete_me : 1;
|
unsigned char delete_me : 1;
|
||||||
unsigned char just_added : 1;
|
unsigned char just_added : 1;
|
||||||
unsigned char frozen : 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_added = 0;
|
||||||
static int timers_delete_me = 0;
|
static int timers_delete_me = 0;
|
||||||
static Ecore_Timer *timers = NULL;
|
static Ecore_Timer *timers = NULL;
|
||||||
|
static Ecore_Timer *timer_current = NULL;
|
||||||
static Ecore_Timer *suspended = NULL;
|
static Ecore_Timer *suspended = NULL;
|
||||||
static double last_check = 0.0;
|
static double last_check = 0.0;
|
||||||
static double precision = 10.0 / 1000000.0;
|
static double precision = 10.0 / 1000000.0;
|
||||||
|
@ -176,7 +177,7 @@ ecore_timer_del(Ecore_Timer *timer)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (timer->frozen && !timer->running)
|
if (timer->frozen && !timer->references)
|
||||||
{
|
{
|
||||||
void *data = timer->data;
|
void *data = timer->data;
|
||||||
|
|
||||||
|
@ -309,8 +310,7 @@ ecore_timer_freeze(Ecore_Timer *timer)
|
||||||
if (timer->frozen)
|
if (timer->frozen)
|
||||||
return ;
|
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));
|
suspended = (Ecore_Timer *) eina_inlist_prepend(EINA_INLIST_GET(suspended), EINA_INLIST_GET(timer));
|
||||||
|
|
||||||
now = ecore_time_get();
|
now = ecore_time_get();
|
||||||
|
@ -360,12 +360,15 @@ _ecore_timer_shutdown(void)
|
||||||
ECORE_MAGIC_SET(timer, ECORE_MAGIC_NONE);
|
ECORE_MAGIC_SET(timer, ECORE_MAGIC_NONE);
|
||||||
free(timer);
|
free(timer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
timer_current = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_ecore_timer_cleanup(void)
|
_ecore_timer_cleanup(void)
|
||||||
{
|
{
|
||||||
Ecore_Timer *l;
|
Ecore_Timer *l;
|
||||||
|
int in_use = 0;
|
||||||
|
|
||||||
if (!timers_delete_me) return;
|
if (!timers_delete_me) return;
|
||||||
for (l = timers; l;)
|
for (l = timers; l;)
|
||||||
|
@ -375,6 +378,11 @@ _ecore_timer_cleanup(void)
|
||||||
l = (Ecore_Timer *) EINA_INLIST_GET(l)->next;
|
l = (Ecore_Timer *) EINA_INLIST_GET(l)->next;
|
||||||
if (timer->delete_me)
|
if (timer->delete_me)
|
||||||
{
|
{
|
||||||
|
if (timer->references)
|
||||||
|
{
|
||||||
|
in_use++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
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));
|
||||||
ECORE_MAGIC_SET(timer, ECORE_MAGIC_NONE);
|
ECORE_MAGIC_SET(timer, ECORE_MAGIC_NONE);
|
||||||
free(timer);
|
free(timer);
|
||||||
|
@ -389,6 +397,11 @@ _ecore_timer_cleanup(void)
|
||||||
l = (Ecore_Timer *) EINA_INLIST_GET(l)->next;
|
l = (Ecore_Timer *) EINA_INLIST_GET(l)->next;
|
||||||
if (timer->delete_me)
|
if (timer->delete_me)
|
||||||
{
|
{
|
||||||
|
if (timer->references)
|
||||||
|
{
|
||||||
|
in_use++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
suspended = (Ecore_Timer *) eina_inlist_remove(EINA_INLIST_GET(suspended), EINA_INLIST_GET(timer));
|
suspended = (Ecore_Timer *) eina_inlist_remove(EINA_INLIST_GET(suspended), EINA_INLIST_GET(timer));
|
||||||
ECORE_MAGIC_SET(timer, ECORE_MAGIC_NONE);
|
ECORE_MAGIC_SET(timer, ECORE_MAGIC_NONE);
|
||||||
free(timer);
|
free(timer);
|
||||||
|
@ -396,7 +409,13 @@ _ecore_timer_cleanup(void)
|
||||||
if (timers_delete_me == 0) return;
|
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
|
void
|
||||||
|
@ -469,58 +488,66 @@ _ecore_timer_next_get(void)
|
||||||
int
|
int
|
||||||
_ecore_timer_call(double when)
|
_ecore_timer_call(double when)
|
||||||
{
|
{
|
||||||
Ecore_Timer *timer, *l;
|
|
||||||
|
|
||||||
if (!timers) return 0;
|
if (!timers) return 0;
|
||||||
if (last_check > when)
|
if (last_check > when)
|
||||||
{
|
{
|
||||||
|
Ecore_Timer *timer;
|
||||||
/* User set time backwards */
|
/* User set time backwards */
|
||||||
EINA_INLIST_FOREACH(timers, timer) timer->at -= (last_check - when);
|
EINA_INLIST_FOREACH(timers, timer) timer->at -= (last_check - when);
|
||||||
}
|
}
|
||||||
last_check = when;
|
last_check = when;
|
||||||
for (l = timers; l;)
|
|
||||||
|
if (!timer_current)
|
||||||
{
|
{
|
||||||
timer = l;
|
/* regular main loop, start from head */
|
||||||
l = (Ecore_Timer *) EINA_INLIST_GET(l)->next;
|
timer_current = timers;
|
||||||
// printf("_ecore_timer_call %3.3f <= %3.3f %i %i %p\n",
|
}
|
||||||
// timer->at, when, timer->just_added, timer->delete_me, timer);
|
else
|
||||||
if ((timer->at <= when) &&
|
{
|
||||||
(timer->just_added == 0) &&
|
/* recursive main loop, continue from where we were */
|
||||||
(timer->delete_me == 0))
|
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));
|
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 the timer would have gone off more than 15 seconds ago,
|
||||||
{
|
* assume that the system hung and set the timer to go off
|
||||||
if ((timer->at + timer->in) < (when - 15.0))
|
* timer->in from now. this handles system hangs, suspends
|
||||||
_ecore_timer_set(timer, when + timer->in, timer->in, timer->func, timer->data);
|
* and more, so ecore will only "replay" the timers while
|
||||||
else
|
* the system is suspended if it is suspended for less than
|
||||||
_ecore_timer_set(timer, timer->at + timer->in, timer->in, timer->func, timer->data);
|
* 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.
|
||||||
else
|
*/
|
||||||
free(timer);
|
if ((timer->at + timer->in) < (when - 15.0))
|
||||||
}
|
_ecore_timer_set(timer, when + timer->in, timer->in, timer->func, timer->data);
|
||||||
else
|
else
|
||||||
free(timer);
|
_ecore_timer_set(timer, timer->at + timer->in, timer->in, timer->func, timer->data);
|
||||||
_ecore_timer_call(when);
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
Loading…
Reference in New Issue