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;
};
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;
return NULL;
}
- if (timer->frozen && !timer->running)
+ if (timer->frozen && !timer->references)
{
void *data = timer->data;
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();
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;)
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);
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);
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
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_current = NULL; /* ended walk, next should restart. */
+ return 0;
+ }
+
+ if ((timer->just_added) || (timer->delete_me))
{
- timer->running = EINA_TRUE;
+ 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;