1 #include "ecore_private.h"
4 static void _ecore_timer_set(Ecore_Timer *timer, double at, double in, int (*func) (void *data), void *data);
6 static int timers_added = 0;
7 static int timers_delete_me = 0;
8 static Ecore_Timer *timers = NULL;
9 static Ecore_Timer *suspended = NULL;
10 static double last_check = 0.0;
13 * @defgroup Ecore_Time_Group Ecore Time Functions
15 * Functions that deal with time. These functions include those that simply
16 * retrieve it in a given format, and those that create events based on it.
20 * Creates a timer to call the given function in the given period of time.
21 * @param in The interval in seconds.
22 * @param func The given function. If @p func returns 1, the timer is
23 * rescheduled for the next interval @p in.
24 * @param data Data to pass to @p func when it is called.
25 * @return A timer object on success. @c NULL on failure.
26 * @ingroup Ecore_Time_Group
28 * This function adds a timer and returns its handle on success and NULL on
29 * failure. The function @p func will be called every @in@ seconds. The
30 * function will be passed the @p data pointer as its parameter.
32 * When the timer @p func is called, it must return a value of either 1
33 * (or ECORE_CALLBACK_RENEW) or 0 (or ECORE_CALLBACK_CANCEL).
34 * If it returns 1, it will be called again at the next tick, or if it returns
35 * 0 it will be deleted automatically making any references/handles for it
39 ecore_timer_add(double in, int (*func) (void *data), const void *data)
44 if (!func) return NULL;
45 if (in < 0.0) in = 0.0;
46 timer = calloc(1, sizeof(Ecore_Timer));
47 if (!timer) return NULL;
48 ECORE_MAGIC_SET(timer, ECORE_MAGIC_TIMER);
49 now = ecore_time_get();
50 _ecore_timer_set(timer, now + in, in, func, (void *)data);
55 * Delete the specified timer from the timer list.
56 * @param timer The timer to delete.
57 * @return The data pointer set for the timer when @ref ecore_timer_add was
58 * called. @c NULL is returned if the function is unsuccessful.
59 * @ingroup Ecore_Time_Group
61 * Note: @p timer must be a valid handle. If the timer function has already
62 * returned 0, the handle is no longer valid (and does not need to be delete).
65 ecore_timer_del(Ecore_Timer *timer)
67 if (!ECORE_MAGIC_CHECK(timer, ECORE_MAGIC_TIMER))
69 ECORE_MAGIC_FAIL(timer, ECORE_MAGIC_TIMER,
73 if (timer->delete_me) return timer->data;
80 * Change the interval the timer ticks of. If set during
81 * a timer call, this will affect the next interval.
83 * @param timer The timer to change.
84 * @param in The interval in seconds.
85 * @ingroup Ecore_Time_Group
88 ecore_timer_interval_set(Ecore_Timer *timer, double in)
90 if (!ECORE_MAGIC_CHECK(timer, ECORE_MAGIC_TIMER))
92 ECORE_MAGIC_FAIL(timer, ECORE_MAGIC_TIMER,
93 "ecore_timer_interval_set");
100 * Add some delay for the next occurence of a timer.
101 * This doesn't affect the interval of a timer.
103 * @param timer The timer to change.
104 * @param add The dalay to add to the next iteration.
105 * @ingroup Ecore_Time_Group
108 ecore_timer_delay(Ecore_Timer *timer, double add)
110 if (!ECORE_MAGIC_CHECK(timer, ECORE_MAGIC_TIMER))
112 ECORE_MAGIC_FAIL(timer, ECORE_MAGIC_TIMER,
113 "ecore_timer_delay");
119 timer->pending += add;
123 timers = _ecore_list2_remove(timers, timer);
124 _ecore_timer_set(timer, timer->at + add, timer->in, timer->func, timer->data);
129 * Get the pending time regarding a timer.
131 * @param timer The timer to learn from.
132 * @ingroup Ecore_Time_Group
135 ecore_timer_pending_get(Ecore_Timer *timer)
139 if (!ECORE_MAGIC_CHECK(timer, ECORE_MAGIC_TIMER))
141 ECORE_MAGIC_FAIL(timer, ECORE_MAGIC_TIMER,
142 "ecore_timer_pending_get");
146 now = ecore_time_get();
149 return timer->pending;
150 return timer->at - now;
158 ecore_timer_freeze(Ecore_Timer *timer)
162 if (!ECORE_MAGIC_CHECK(timer, ECORE_MAGIC_TIMER))
164 ECORE_MAGIC_FAIL(timer, ECORE_MAGIC_TIMER,
165 "ecore_timer_freeze");
169 /* Timer already frozen */
173 timers = _ecore_list2_remove(timers, timer);
174 suspended = _ecore_list2_prepend(suspended, timer);
176 now = ecore_time_get();
178 timer->pending = timer->at - now;
184 ecore_timer_thaw(Ecore_Timer *timer)
188 if (!ECORE_MAGIC_CHECK(timer, ECORE_MAGIC_TIMER))
190 ECORE_MAGIC_FAIL(timer, ECORE_MAGIC_TIMER,
195 /* Timer not frozen */
199 suspended = _ecore_list2_remove(suspended, timer);
200 now = ecore_time_get();
202 _ecore_timer_set(timer, timer->pending + now, timer->in, timer->func, timer->data);
206 _ecore_timer_shutdown(void)
213 timers = _ecore_list2_remove(timers, timer);
214 ECORE_MAGIC_SET(timer, ECORE_MAGIC_NONE);
223 suspended = _ecore_list2_remove(suspended, timer);
224 ECORE_MAGIC_SET(timer, ECORE_MAGIC_NONE);
230 _ecore_timer_cleanup(void)
234 if (!timers_delete_me) return;
235 for (l = (Ecore_List2 *)timers; l;)
239 timer = (Ecore_Timer *)l;
241 if (timer->delete_me)
243 timers = _ecore_list2_remove(timers, timer);
244 ECORE_MAGIC_SET(timer, ECORE_MAGIC_NONE);
247 if (timers_delete_me == 0) return;
250 for (l = (Ecore_List2 *)suspended; l;)
254 timer = (Ecore_Timer *)l;
256 if (timer->delete_me)
258 suspended = _ecore_list2_remove(suspended, timer);
259 ECORE_MAGIC_SET(timer, ECORE_MAGIC_NONE);
262 if (timers_delete_me == 0) return;
265 timers_delete_me = 0;
269 _ecore_timer_enable_new(void)
273 if (!timers_added) return;
275 for (l = (Ecore_List2 *)timers; l; l = l->next)
279 timer = (Ecore_Timer *)l;
280 timer->just_added = 0;
285 _ecore_timer_next_get(void)
291 if (!timers) return -1;
292 now = ecore_time_get();
293 timer = (Ecore_Timer *)timers;
294 while ((timer) && ((timer->delete_me) || (timer->just_added)))
295 timer = (Ecore_Timer *)((Ecore_List2 *)timer)->next;
296 if (!timer) return -1;
297 in = timer->at - now;
303 _ecore_timer_call(double when)
308 if (!timers) return 0;
309 if (last_check > when)
311 /* User set time backwards */
312 for (l = (Ecore_List2 *)timers; l; l = l->next)
314 timer = (Ecore_Timer *)l;
315 timer->at -= (last_check - when);
319 for (l = (Ecore_List2 *)timers; l; l = l->next)
321 timer = (Ecore_Timer *)l;
322 if ((timer->at <= when) &&
323 (timer->just_added == 0) &&
324 (timer->delete_me == 0))
326 timers = _ecore_list2_remove(timers, timer);
327 _ecore_timer_call(when);
328 if ((!timer->delete_me) && (timer->func(timer->data)))
330 /* if the timer would have gone off more than 15 seconds ago,
331 * assume that the system hung and set the timer to go off
332 * timer->in from now. this handles system hangs, suspends
333 * and more, so ecore will only "replay" the timers while
334 * the system is suspended if it is suspended for less than
335 * 15 seconds (basically). this also handles if the process
336 * is stopped in a debugger or IO and other handling gets
337 * really slow within the main loop.
339 if (!timer->delete_me)
341 if ((timer->at + timer->in) < (when - 15.0))
342 _ecore_timer_set(timer, when + timer->in, timer->in, timer->func, timer->data);
344 _ecore_timer_set(timer, timer->at + timer->in, timer->in, timer->func, timer->data);
358 _ecore_timer_set(Ecore_Timer *timer, double at, double in, int (*func) (void *data), void *data)
367 timer->just_added = 1;
369 timer->pending = 0.0;
372 for (l = ((Ecore_List2 *)(timers))->last; l; l = l->prev)
376 t2 = (Ecore_Timer *)l;
377 if (timer->at > t2->at)
379 timers = _ecore_list2_append_relative(timers, timer, t2);
384 timers = _ecore_list2_prepend(timers, timer);