aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/ecore/src/lib/ecore/ecore_timer.c
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/ecore/src/lib/ecore/ecore_timer.c')
-rw-r--r--libraries/ecore/src/lib/ecore/ecore_timer.c833
1 files changed, 0 insertions, 833 deletions
diff --git a/libraries/ecore/src/lib/ecore/ecore_timer.c b/libraries/ecore/src/lib/ecore/ecore_timer.c
deleted file mode 100644
index d76733b..0000000
--- a/libraries/ecore/src/lib/ecore/ecore_timer.c
+++ /dev/null
@@ -1,833 +0,0 @@
1#ifdef HAVE_CONFIG_H
2# include <config.h>
3#endif
4
5#include <stdlib.h>
6#include <stdio.h>
7
8#include "Ecore.h"
9#include "ecore_private.h"
10
11#ifdef WANT_ECORE_TIMER_DUMP
12# include <string.h>
13# include <execinfo.h>
14# define ECORE_TIMER_DEBUG_BT_NUM 64
15typedef void (*Ecore_Timer_Bt_Func)();
16#endif
17
18struct _Ecore_Timer
19{
20 EINA_INLIST;
21 ECORE_MAGIC;
22 double in;
23 double at;
24 double pending;
25 Ecore_Task_Cb func;
26 void *data;
27
28#ifdef WANT_ECORE_TIMER_DUMP
29 Ecore_Timer_Bt_Func timer_bt[ECORE_TIMER_DEBUG_BT_NUM];
30 int timer_bt_num;
31#endif
32
33 int references;
34 unsigned char delete_me : 1;
35 unsigned char just_added : 1;
36 unsigned char frozen : 1;
37};
38GENERIC_ALLOC_SIZE_DECLARE(Ecore_Timer);
39
40static void _ecore_timer_set(Ecore_Timer *timer,
41 double at,
42 double in,
43 Ecore_Task_Cb func,
44 void *data);
45#ifdef WANT_ECORE_TIMER_DUMP
46static int _ecore_timer_cmp(const void *d1,
47 const void *d2);
48#endif
49
50static int timers_added = 0;
51static int timers_delete_me = 0;
52static Ecore_Timer *timers = NULL;
53static Ecore_Timer *timer_current = NULL;
54static Ecore_Timer *suspended = NULL;
55static double last_check = 0.0;
56static double precision = 10.0 / 1000000.0;
57
58/**
59 * @addtogroup Ecore_Timer_Group
60 *
61 * @{
62 */
63
64/**
65 * Retrieves the current precision used by timer infrastructure.
66 *
67 * @see ecore_timer_precision_set()
68 */
69EAPI double
70ecore_timer_precision_get(void)
71{
72 return precision;
73}
74
75/**
76 * @brief Sets the precision to be used by timer infrastructure.
77 *
78 * @param value allowed introduced timeout delay, in seconds.
79 *
80 * This sets the precision for @b all timers. The precision determines how much
81 * of an difference from the requested interval is acceptable. One common reason
82 * to use this function is to @b increase the allowed timeout and thus @b
83 * decrease precision of the timers, this is because less precise the timers
84 * result in the system waking up less often and thus consuming less resources.
85 *
86 * Be aware that kernel may delay delivery even further, these delays
87 * are always possible due other tasks having higher priorities or
88 * other scheduler policies.
89 *
90 * Example:
91 * We have 2 timers, one that expires in a 2.0s and another that
92 * expires in 2.1s, if precision is 0.1s, then the Ecore will request
93 * for the next expire to happen in 2.1s and not 2.0s and another one
94 * of 0.1 as it would before.
95 *
96 * @note Ecore is smart enough to see if there are timers in the
97 * precision range, if it does not, in our example if no second timer
98 * in (T + precision) existed, then it would use the minimum timeout.
99 */
100EAPI void
101ecore_timer_precision_set(double value)
102{
103 _ecore_lock();
104
105 if (value < 0.0)
106 {
107 ERR("Precision %f less than zero, ignored", value);
108 goto unlock;
109 }
110 precision = value;
111
112unlock:
113 _ecore_unlock();
114}
115
116/**
117 * Creates a timer to call the given function in the given period of time.
118 * @param in The interval in seconds.
119 * @param func The given function. If @p func returns 1, the timer is
120 * rescheduled for the next interval @p in.
121 * @param data Data to pass to @p func when it is called.
122 * @return A timer object on success. @c NULL on failure.
123 *
124 * This function adds a timer and returns its handle on success and NULL on
125 * failure. The function @p func will be called every @p in seconds. The
126 * function will be passed the @p data pointer as its parameter.
127 *
128 * When the timer @p func is called, it must return a value of either 1
129 * (or ECORE_CALLBACK_RENEW) or 0 (or ECORE_CALLBACK_CANCEL).
130 * If it returns 1, it will be called again at the next tick, or if it returns
131 * 0 it will be deleted automatically making any references/handles for it
132 * invalid.
133 */
134EAPI Ecore_Timer *
135ecore_timer_add(double in,
136 Ecore_Task_Cb func,
137 const void *data)
138{
139 double now;
140 Ecore_Timer *timer = NULL;
141
142 _ecore_lock();
143 if (!func) goto unlock;
144 if (in < 0.0) in = 0.0;
145 timer = ecore_timer_calloc(1);
146 if (!timer) goto unlock;
147 ECORE_MAGIC_SET(timer, ECORE_MAGIC_TIMER);
148 now = ecore_time_get();
149
150#ifdef WANT_ECORE_TIMER_DUMP
151 timer->timer_bt_num = backtrace((void **)(timer->timer_bt),
152 ECORE_TIMER_DEBUG_BT_NUM);
153#endif
154
155 _ecore_timer_set(timer, now + in, in, func, (void *)data);
156unlock:
157 _ecore_unlock();
158 return timer;
159}
160
161/**
162 * Creates a timer to call the given function in the given period of time.
163 * @param in The interval in seconds from current loop time.
164 * @param func The given function. If @p func returns 1, the timer is
165 * rescheduled for the next interval @p in.
166 * @param data Data to pass to @p func when it is called.
167 * @return A timer object on success. @c NULL on failure.
168 *
169 * This is the same as ecore_timer_add(), but "now" is the time from
170 * ecore_loop_time_get() not ecore_time_get() as ecore_timer_add() uses. See
171 * ecore_timer_add() for more details.
172 */
173EAPI Ecore_Timer *
174ecore_timer_loop_add(double in,
175 Ecore_Task_Cb func,
176 const void *data)
177{
178 Ecore_Timer *timer;
179
180 _ecore_lock();
181 timer = _ecore_timer_loop_add(in, func, data);
182 _ecore_unlock();
183
184 return timer;
185}
186
187/**
188 * Delete the specified timer from the timer list.
189 * @param timer The timer to delete.
190 * @return The data pointer set for the timer when @ref ecore_timer_add was
191 * called. @c NULL is returned if the function is unsuccessful.
192 *
193 * Note: @p timer must be a valid handle. If the timer function has already
194 * returned 0, the handle is no longer valid (and does not need to be delete).
195 */
196EAPI void *
197ecore_timer_del(Ecore_Timer *timer)
198{
199 void *data = NULL;
200
201 _ecore_lock();
202
203 if (!ECORE_MAGIC_CHECK(timer, ECORE_MAGIC_TIMER))
204 {
205 ECORE_MAGIC_FAIL(timer, ECORE_MAGIC_TIMER,
206 "ecore_timer_del");
207 goto unlock;
208 }
209
210 data = _ecore_timer_del(timer);
211
212unlock:
213 _ecore_unlock();
214 return data;
215}
216
217/**
218 * Change the interval the timer ticks of. If set during
219 * a timer call, this will affect the next interval.
220 *
221 * @param timer The timer to change.
222 * @param in The interval in seconds.
223 */
224EAPI void
225ecore_timer_interval_set(Ecore_Timer *timer,
226 double in)
227{
228 _ecore_lock();
229
230 if (!ECORE_MAGIC_CHECK(timer, ECORE_MAGIC_TIMER))
231 {
232 ECORE_MAGIC_FAIL(timer, ECORE_MAGIC_TIMER,
233 "ecore_timer_interval_set");
234 goto unlock;
235 }
236 timer->in = in;
237unlock:
238 _ecore_unlock();
239}
240
241/**
242 * Get the interval the timer ticks on.
243 *
244 * @param timer The timer to retrieve the interval from
245 * @return The interval on success. -1 on failure.
246 */
247EAPI double
248ecore_timer_interval_get(Ecore_Timer *timer)
249{
250 double interval;
251
252 _ecore_lock();
253
254 if (!ECORE_MAGIC_CHECK(timer, ECORE_MAGIC_TIMER))
255 {
256 ECORE_MAGIC_FAIL(timer, ECORE_MAGIC_TIMER,
257 "ecore_timer_interval_get");
258 interval = -1.0;
259 goto unlock;
260 }
261
262 interval = timer->in;
263unlock:
264 _ecore_unlock();
265 return interval;
266}
267
268/**
269 * Add some delay for the next occurrence of a timer.
270 * This doesn't affect the interval of a timer.
271 *
272 * @param timer The timer to change.
273 * @param add The dalay to add to the next iteration.
274 */
275EAPI void
276ecore_timer_delay(Ecore_Timer *timer,
277 double add)
278{
279 if (!ECORE_MAGIC_CHECK(timer, ECORE_MAGIC_TIMER))
280 {
281 ECORE_MAGIC_FAIL(timer, ECORE_MAGIC_TIMER,
282 "ecore_timer_delay");
283 return;
284 }
285
286 _ecore_lock();
287 _ecore_timer_delay(timer, add);
288 _ecore_unlock();
289}
290
291/**
292 * Reset a timer to its full interval
293 * This doesn't affect the interval of a timer
294 * @param timer The timer
295 * @since 1.2
296 * @note This is equivalent to (but faster than)
297 * @code
298 * ecore_timer_delay(timer, ecore_timer_interval_get(timer) - ecore_timer_pending_get(timer));
299 * @endcode
300 */
301EAPI void
302ecore_timer_reset(Ecore_Timer *timer)
303{
304 double now, add;
305 if (!ECORE_MAGIC_CHECK(timer, ECORE_MAGIC_TIMER))
306 {
307 ECORE_MAGIC_FAIL(timer, ECORE_MAGIC_TIMER,
308 __func__);
309 return;
310 }
311 _ecore_lock();
312 now = ecore_time_get();
313
314 if (timer->frozen)
315 add = timer->pending;
316 else
317 add = timer->at - now;
318 _ecore_timer_delay(timer, timer->in - add);
319 _ecore_unlock();
320}
321
322/**
323 * Get the pending time regarding a timer.
324 *
325 * @param timer The timer to learn from.
326 * @ingroup Ecore_Timer_Group
327 */
328EAPI double
329ecore_timer_pending_get(Ecore_Timer *timer)
330{
331 double now;
332 double ret = 0.0;
333
334 _ecore_lock();
335
336 if (!ECORE_MAGIC_CHECK(timer, ECORE_MAGIC_TIMER))
337 {
338 ECORE_MAGIC_FAIL(timer, ECORE_MAGIC_TIMER,
339 "ecore_timer_pending_get");
340 goto unlock;
341 }
342
343 now = ecore_time_get();
344
345 if (timer->frozen)
346 ret = timer->pending;
347 else
348 ret = timer->at - now;
349unlock:
350 _ecore_unlock();
351 return ret;
352}
353
354/**
355 * Pauses a running timer.
356 *
357 * @param timer The timer to be paused.
358 *
359 * The timer callback won't be called while the timer is paused. The remaining
360 * time until the timer expires will be saved, so the timer can be resumed with
361 * that same remaining time to expire, instead of expiring instantly. Use
362 * ecore_timer_thaw() to resume it.
363 *
364 * @note Nothing happens if the timer was already paused.
365 *
366 * @see ecore_timer_thaw()
367 */
368EAPI void
369ecore_timer_freeze(Ecore_Timer *timer)
370{
371 double now;
372
373 _ecore_lock();
374
375 if (!ECORE_MAGIC_CHECK(timer, ECORE_MAGIC_TIMER))
376 {
377 ECORE_MAGIC_FAIL(timer, ECORE_MAGIC_TIMER,
378 "ecore_timer_freeze");
379 goto unlock;
380 }
381
382 /* Timer already frozen */
383 if (timer->frozen)
384 goto unlock;
385
386 timers = (Ecore_Timer *)eina_inlist_remove(EINA_INLIST_GET(timers), EINA_INLIST_GET(timer));
387 suspended = (Ecore_Timer *)eina_inlist_prepend(EINA_INLIST_GET(suspended), EINA_INLIST_GET(timer));
388
389 now = ecore_time_get();
390
391 timer->pending = timer->at - now;
392 timer->at = 0.0;
393 timer->frozen = 1;
394unlock:
395 _ecore_unlock();
396}
397
398/**
399 * Resumes a frozen (paused) timer.
400 *
401 * @param timer The timer to be resumed.
402 *
403 * The timer will be resumed from its previous relative position in time. That
404 * means, if it had X seconds remaining until expire when it was paused, it will
405 * be started now with those same X seconds remaining to expire again. But
406 * notice that the interval time won't be touched by this call or by
407 * ecore_timer_freeze().
408 *
409 * @see ecore_timer_freeze()
410 */
411EAPI void
412ecore_timer_thaw(Ecore_Timer *timer)
413{
414 double now;
415
416 _ecore_lock();
417
418 if (!ECORE_MAGIC_CHECK(timer, ECORE_MAGIC_TIMER))
419 {
420 ECORE_MAGIC_FAIL(timer, ECORE_MAGIC_TIMER,
421 "ecore_timer_thaw");
422 goto unlock;
423 }
424
425 /* Timer not frozen */
426 if (!timer->frozen)
427 goto unlock;
428
429 suspended = (Ecore_Timer *)eina_inlist_remove(EINA_INLIST_GET(suspended), EINA_INLIST_GET(timer));
430 now = ecore_time_get();
431
432 _ecore_timer_set(timer, timer->pending + now, timer->in, timer->func, timer->data);
433unlock:
434 _ecore_unlock();
435}
436
437EAPI char *
438ecore_timer_dump(void)
439{
440#ifdef WANT_ECORE_TIMER_DUMP
441 Eina_Strbuf *result;
442 char *out;
443 Ecore_Timer *tm;
444 Eina_List *tmp = NULL;
445 int living_timer = 0;
446 int unknow_timer = 0;
447
448 _ecore_lock();
449 result = eina_strbuf_new();
450
451 EINA_INLIST_FOREACH(timers, tm)
452 tmp = eina_list_sorted_insert(tmp, _ecore_timer_cmp, tm);
453
454 EINA_LIST_FREE(tmp, tm)
455 {
456 char **strings;
457 int j;
458
459 if (!tm->frozen && !tm->delete_me)
460 living_timer++;
461
462 strings = backtrace_symbols((void **)tm->timer_bt, tm->timer_bt_num);
463 if (tm->timer_bt_num <= 0 || strings == NULL)
464 {
465 unknow_timer++;
466 continue;
467 }
468
469 eina_strbuf_append_printf(result, "*** timer: %f ***\n", tm->in);
470 if (tm->frozen)
471 eina_strbuf_append(result, "FROZEN\n");
472 if (tm->delete_me)
473 eina_strbuf_append(result, "DELETED\n");
474 for (j = 0; j < tm->timer_bt_num; j++)
475 eina_strbuf_append_printf(result, "%s\n", strings[j]);
476
477 free(strings);
478 }
479
480 eina_strbuf_append_printf(result, "\n***\nThere is %i living timer.\nWe did lost track of %i timers.\n", living_timer, unknow_timer);
481
482 out = eina_strbuf_string_steal(result);
483 eina_strbuf_free(result);
484 _ecore_unlock();
485
486 return out;
487#else
488 return NULL;
489#endif
490}
491
492/**
493 * @}
494 */
495
496Ecore_Timer *
497_ecore_timer_loop_add(double in,
498 Ecore_Task_Cb func,
499 const void *data)
500{
501 double now;
502 Ecore_Timer *timer = NULL;
503
504 if (!func) return timer;
505 if (in < 0.0) in = 0.0;
506 timer = ecore_timer_calloc(1);
507 if (!timer) return timer;
508 ECORE_MAGIC_SET(timer, ECORE_MAGIC_TIMER);
509 now = ecore_loop_time_get();
510
511#ifdef WANT_ECORE_TIMER_DUMP
512 timer->timer_bt_num = backtrace((void **)(timer->timer_bt),
513 ECORE_TIMER_DEBUG_BT_NUM);
514#endif
515 _ecore_timer_set(timer, now + in, in, func, (void *)data);
516 return timer;
517}
518
519EAPI void
520_ecore_timer_delay(Ecore_Timer *timer,
521 double add)
522{
523 if (timer->frozen)
524 {
525 timer->pending += add;
526 }
527 else
528 {
529 timers = (Ecore_Timer *)eina_inlist_remove(EINA_INLIST_GET(timers), EINA_INLIST_GET(timer));
530 _ecore_timer_set(timer, timer->at + add, timer->in, timer->func, timer->data);
531 }
532}
533
534void *
535_ecore_timer_del(Ecore_Timer *timer)
536{
537 if (timer->frozen && !timer->references)
538 {
539 void *data = timer->data;
540
541 suspended = (Ecore_Timer *)eina_inlist_remove(EINA_INLIST_GET(suspended), EINA_INLIST_GET(timer));
542
543 if (timer->delete_me)
544 timers_delete_me--;
545
546 ecore_timer_mp_free(timer);
547 return data;
548 }
549
550 EINA_SAFETY_ON_TRUE_RETURN_VAL(timer->delete_me, NULL);
551 timer->delete_me = 1;
552 timers_delete_me++;
553 return timer->data;
554}
555
556void
557_ecore_timer_shutdown(void)
558{
559 Ecore_Timer *timer;
560
561 while ((timer = timers))
562 {
563 timers = (Ecore_Timer *)eina_inlist_remove(EINA_INLIST_GET(timers), EINA_INLIST_GET(timers));
564 ECORE_MAGIC_SET(timer, ECORE_MAGIC_NONE);
565 ecore_timer_mp_free(timer);
566 }
567
568 while ((timer = suspended))
569 {
570 suspended = (Ecore_Timer *)eina_inlist_remove(EINA_INLIST_GET(suspended), EINA_INLIST_GET(suspended));
571 ECORE_MAGIC_SET(timer, ECORE_MAGIC_NONE);
572 ecore_timer_mp_free(timer);
573 }
574
575 timer_current = NULL;
576}
577
578void
579_ecore_timer_cleanup(void)
580{
581 Ecore_Timer *l;
582 int in_use = 0, todo = timers_delete_me, done = 0;
583
584 if (!timers_delete_me) return;
585 for (l = timers; l; )
586 {
587 Ecore_Timer *timer = l;
588
589 l = (Ecore_Timer *)EINA_INLIST_GET(l)->next;
590 if (timer->delete_me)
591 {
592 if (timer->references)
593 {
594 in_use++;
595 continue;
596 }
597 timers = (Ecore_Timer *)eina_inlist_remove(EINA_INLIST_GET(timers), EINA_INLIST_GET(timer));
598 ECORE_MAGIC_SET(timer, ECORE_MAGIC_NONE);
599 ecore_timer_mp_free(timer);
600 timers_delete_me--;
601 done++;
602 if (timers_delete_me == 0) return;
603 }
604 }
605 for (l = suspended; l; )
606 {
607 Ecore_Timer *timer = l;
608
609 l = (Ecore_Timer *)EINA_INLIST_GET(l)->next;
610 if (timer->delete_me)
611 {
612 if (timer->references)
613 {
614 in_use++;
615 continue;
616 }
617 suspended = (Ecore_Timer *)eina_inlist_remove(EINA_INLIST_GET(suspended), EINA_INLIST_GET(timer));
618 ECORE_MAGIC_SET(timer, ECORE_MAGIC_NONE);
619 ecore_timer_mp_free(timer);
620 timers_delete_me--;
621 done++;
622 if (timers_delete_me == 0) return;
623 }
624 }
625
626 if ((!in_use) && (timers_delete_me))
627 {
628 ERR("%d timers to delete, but they were not found!"
629 "Stats: todo=%d, done=%d, pending=%d, in_use=%d. "
630 "reset counter.",
631 timers_delete_me, todo, done, todo - done, in_use);
632 timers_delete_me = 0;
633 }
634}
635
636void
637_ecore_timer_enable_new(void)
638{
639 Ecore_Timer *timer;
640
641 if (!timers_added) return;
642 timers_added = 0;
643 EINA_INLIST_FOREACH(timers, timer) timer->just_added = 0;
644}
645
646int
647_ecore_timers_exists(void)
648{
649 Ecore_Timer *timer = timers;
650
651 while ((timer) && (timer->delete_me))
652 timer = (Ecore_Timer *)EINA_INLIST_GET(timer)->next;
653
654 return !!timer;
655}
656
657static inline Ecore_Timer *
658_ecore_timer_first_get(void)
659{
660 Ecore_Timer *timer = timers;
661
662 while ((timer) && ((timer->delete_me) || (timer->just_added)))
663 timer = (Ecore_Timer *)EINA_INLIST_GET(timer)->next;
664
665 return timer;
666}
667
668static inline Ecore_Timer *
669_ecore_timer_after_get(Ecore_Timer *base)
670{
671 Ecore_Timer *timer = (Ecore_Timer *)EINA_INLIST_GET(base)->next;
672 Ecore_Timer *valid_timer = NULL;
673 double maxtime = base->at + precision;
674
675 while ((timer) && (timer->at < maxtime))
676 {
677 if (!((timer->delete_me) || (timer->just_added)))
678 valid_timer = timer;
679 timer = (Ecore_Timer *)EINA_INLIST_GET(timer)->next;
680 }
681
682 return valid_timer;
683}
684
685double
686_ecore_timer_next_get(void)
687{
688 double now;
689 double in;
690 Ecore_Timer *first, *second;
691
692 first = _ecore_timer_first_get();
693 if (!first) return -1;
694
695 second = _ecore_timer_after_get(first);
696 if (second) first = second;
697
698 now = ecore_loop_time_get();
699 in = first->at - now;
700 if (in < 0) in = 0;
701 return in;
702}
703
704static inline void
705_ecore_timer_reschedule(Ecore_Timer *timer,
706 double when)
707{
708 if ((timer->delete_me) || (timer->frozen)) return;
709
710 timers = (Ecore_Timer *)eina_inlist_remove(EINA_INLIST_GET(timers), EINA_INLIST_GET(timer));
711
712 /* if the timer would have gone off more than 15 seconds ago,
713 * assume that the system hung and set the timer to go off
714 * timer->in from now. this handles system hangs, suspends
715 * and more, so ecore will only "replay" the timers while
716 * the system is suspended if it is suspended for less than
717 * 15 seconds (basically). this also handles if the process
718 * is stopped in a debugger or IO and other handling gets
719 * really slow within the main loop.
720 */
721 if ((timer->at + timer->in) < (when - 15.0))
722 _ecore_timer_set(timer, when + timer->in, timer->in, timer->func, timer->data);
723 else
724 _ecore_timer_set(timer, timer->at + timer->in, timer->in, timer->func, timer->data);
725}
726
727/* assume that we hold the ecore lock when entering this function */
728void
729_ecore_timer_expired_timers_call(double when)
730{
731 /* call the first expired timer until no expired timers exist */
732 while (_ecore_timer_expired_call(when)) ;
733}
734
735/* assume that we hold the ecore lock when entering this function */
736int
737_ecore_timer_expired_call(double when)
738{
739 if (!timers) return 0;
740 if (last_check > when)
741 {
742 Ecore_Timer *timer;
743 /* User set time backwards */
744 EINA_INLIST_FOREACH(timers, timer) timer->at -= (last_check - when);
745 }
746 last_check = when;
747
748 if (!timer_current)
749 {
750 /* regular main loop, start from head */
751 timer_current = timers;
752 }
753 else
754 {
755 /* recursive main loop, continue from where we were */
756 Ecore_Timer *timer_old = timer_current;
757 timer_current = (Ecore_Timer *)EINA_INLIST_GET(timer_current)->next;
758 _ecore_timer_reschedule(timer_old, when);
759 }
760
761 while (timer_current)
762 {
763 Ecore_Timer *timer = timer_current;
764
765 if (timer->at > when)
766 {
767 timer_current = NULL; /* ended walk, next should restart. */
768 return 0;
769 }
770
771 if ((timer->just_added) || (timer->delete_me))
772 {
773 timer_current = (Ecore_Timer *)EINA_INLIST_GET(timer_current)->next;
774 continue;
775 }
776
777 timer->references++;
778 if (!_ecore_call_task_cb(timer->func, timer->data))
779 {
780 if (!timer->delete_me) _ecore_timer_del(timer);
781 }
782 timer->references--;
783
784 if (timer_current) /* may have changed in recursive main loops */
785 timer_current = (Ecore_Timer *)EINA_INLIST_GET(timer_current)->next;
786
787 _ecore_timer_reschedule(timer, when);
788 }
789 return 0;
790}
791
792static void
793_ecore_timer_set(Ecore_Timer *timer,
794 double at,
795 double in,
796 Ecore_Task_Cb func,
797 void *data)
798{
799 Ecore_Timer *t2;
800
801 timers_added = 1;
802 timer->at = at;
803 timer->in = in;
804 timer->func = func;
805 timer->data = data;
806 timer->just_added = 1;
807 timer->frozen = 0;
808 timer->pending = 0.0;
809 if (timers)
810 {
811 EINA_INLIST_REVERSE_FOREACH(EINA_INLIST_GET(timers), t2)
812 {
813 if (timer->at > t2->at)
814 {
815 timers = (Ecore_Timer *)eina_inlist_append_relative(EINA_INLIST_GET(timers), EINA_INLIST_GET(timer), EINA_INLIST_GET(t2));
816 return;
817 }
818 }
819 }
820 timers = (Ecore_Timer *)eina_inlist_prepend(EINA_INLIST_GET(timers), EINA_INLIST_GET(timer));
821}
822
823#ifdef WANT_ECORE_TIMER_DUMP
824static int
825_ecore_timer_cmp(const void *d1,
826 const void *d2)
827{
828 const Ecore_Timer *t1 = d1;
829 const Ecore_Timer *t2 = d2;
830
831 return (int)((t1->in - t2->in) * 100);
832}
833#endif