chiark / gitweb /
Imported Debian patch 1.0.0-5
[e16] / src / timers.c
1 /*
2  * Copyright (C) 2000-2007 Carsten Haitzler, Geoff Harrison and various contributors
3  * Copyright (C) 2006-2009 Kim Woelders
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a copy
6  * of this software and associated documentation files (the "Software"), to
7  * deal in the Software without restriction, including without limitation the
8  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
9  * sell copies of the Software, and to permit persons to whom the Software is
10  * furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in
13  * all copies of the Software, its documentation and marketing & publicity
14  * materials, and acknowledgment shall be given in the documentation, materials
15  * and software packages that this Software was used.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20  * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  */
24 #include "E.h"
25 #include "e16-ecore_list.h"
26 #include "timers.h"
27 #include <sys/time.h>
28
29 #define DEBUG_TIMERS 0
30
31 struct _timer {
32    double              in_time;
33    double              at_time;
34    struct _timer      *next;
35    int                 (*func) (void *data);
36    void               *data;
37    char                again;
38 };
39
40 double
41 GetTime(void)
42 {
43    struct timeval      timev;
44
45    gettimeofday(&timev, NULL);
46    return (double)timev.tv_sec + (((double)timev.tv_usec) / 1000000);
47 }
48
49 static Timer       *q_first = NULL;
50
51 static void
52 _TimerSet(Timer * timer)
53 {
54    Timer              *ptr, *pptr;
55
56 #if DEBUG_TIMERS
57    if (EDebug(EDBUG_TYPE_TIMERS))
58       Eprintf("_TimerSet %p: func=%p data=%p\n", timer, timer->func,
59               timer->data);
60 #endif
61
62    /* if there is no queue it becomes the queue */
63    if (!q_first)
64      {
65         q_first = timer;
66         timer->next = NULL;
67      }
68    else
69      {
70         pptr = NULL;
71         for (ptr = q_first; ptr; pptr = ptr, ptr = ptr->next)
72           {
73              if (ptr->at_time > timer->at_time)
74                 break;
75           }
76         if (pptr)
77            pptr->next = timer;
78         else
79            q_first = timer;
80         timer->next = ptr;
81      }
82 }
83
84 static void
85 _TimerDel(Timer * timer)
86 {
87 #if DEBUG_TIMERS
88    if (EDebug(EDBUG_TYPE_TIMERS))
89       Eprintf("_TimerDel %p: func=%p data=%p\n", timer, timer->func,
90               timer->data);
91 #endif
92    Efree(timer);
93 }
94
95 Timer              *
96 TimerAdd(double in_time, int (*func) (void *data), void *data)
97 {
98    Timer              *timer;
99
100    timer = EMALLOC(Timer, 1);
101    if (!timer)
102       return NULL;
103
104    if (in_time < 0.)            /* No negative in-times */
105       in_time = 0.;
106
107    timer->func = func;
108    timer->in_time = in_time;
109    timer->at_time = GetTime() + in_time;
110    timer->data = data;
111
112    if (EDebug(EDBUG_TYPE_TIMERS))
113       Eprintf("TimerAdd %p: func=%p data=%p: %8.3f\n", timer,
114               timer->func, timer->data, in_time);
115
116    _TimerSet(timer);            /* Add to timer queue */
117
118    return timer;
119 }
120
121 double
122 TimersRun(double tt)
123 {
124    Timer              *timer, *q_old, *q_run;
125    double              t;
126
127    timer = q_first;
128    if (!q_first)
129       return 0.;                /* No timers pending */
130
131    t = tt;
132    if (t <= 0.)
133       t = timer->at_time;
134
135    q_run = q_old = q_first;
136    for (; timer; timer = q_first)
137      {
138         if (timer->at_time > t + 200e-6)        /* Within 200 us is close enough */
139            break;
140
141         if (EDebug(EDBUG_TYPE_TIMERS))
142            Eprintf("TimersRun - run %p: func=%p data=%p: %8.3lf\n", timer,
143                    timer->func, timer->data, timer->at_time - t);
144
145         q_first = timer->next;
146
147         /* Run this callback */
148         timer->again = timer->func(timer->data);
149         q_run = timer;
150      }
151
152    if (q_old != q_first)
153      {
154         /* At least one timer has run */
155         q_run->next = NULL;     /* Terminate expired timer list */
156
157         /* Re-schedule/remove timers that have run */
158         for (timer = q_old; timer; timer = q_old)
159           {
160              q_old = timer->next;
161              if (timer->again)
162                {
163                   timer->at_time += timer->in_time;
164                   _TimerSet(timer);     /* Add to timer queue */
165                }
166              else
167                {
168                   _TimerDel(timer);
169                }
170           }
171      }
172
173    if (tt <= 0.)                /* Avoid some redundant debug output */
174       return tt;
175
176    timer = q_first;
177
178    if (EDebug(EDBUG_TYPE_TIMERS) > 1)
179      {
180         Timer              *qp;
181
182         for (qp = timer; qp; qp = qp->next)
183            Eprintf("TimersRun - pend %p: func=%p data=%p: %8.3lf\n", qp,
184                    qp->func, qp->data, qp->at_time - t);
185      }
186
187    if (timer)
188      {
189         t = timer->at_time - t;
190         if (t <= 0.)
191            t = 1e-6;
192      }
193    else
194      {
195         t = 0.;
196      }
197
198    if (EDebug(EDBUG_TYPE_TIMERS))
199       Eprintf("TimersRun - next in %8.3lf\n", t);
200
201    return t;
202 }
203
204 int
205 TimerDel(Timer * timer)
206 {
207    Timer              *qe, *ptr, *pptr;
208
209    pptr = NULL;
210    for (ptr = q_first; ptr; pptr = ptr, ptr = ptr->next)
211      {
212         qe = ptr;
213         if (qe != timer)
214            continue;
215
216         /* Match - remove it from the queue */
217         if (pptr)
218            pptr->next = qe->next;
219         else
220            q_first = qe->next;
221
222         /* free it */
223         _TimerDel(timer);
224
225         /* done */
226         return 1;
227      }
228
229    return 0;
230 }
231
232 void
233 TimerSetInterval(Timer * timer, double dt)
234 {
235    timer->in_time = dt;
236 }
237
238 /*
239  * Idlers
240  */
241 static Ecore_List  *idler_list = NULL;
242
243 typedef void        (IdlerFunc) (void *data);
244
245 struct _idler {
246    IdlerFunc          *func;
247    void               *data;
248 };
249
250 Idler              *
251 IdlerAdd(IdlerFunc * func, void *data)
252 {
253    Idler              *id;
254
255    id = EMALLOC(Idler, 1);
256    if (!id)
257       return NULL;
258
259    id->func = func;
260    id->data = data;
261
262    if (!idler_list)
263       idler_list = ecore_list_new();
264
265    ecore_list_append(idler_list, id);
266
267    return id;
268 }
269
270 void
271 IdlerDel(Idler * id)
272 {
273    ecore_list_node_remove(idler_list, id);
274    Efree(id);
275 }
276
277 static void
278 _IdlerRun(void *_id, void *prm __UNUSED__)
279 {
280    Idler              *id = (Idler *) _id;
281
282    id->func(id->data);
283 }
284
285 void
286 IdlersRun(void)
287 {
288    if (EDebug(EDBUG_TYPE_IDLERS))
289       Eprintf("IdlersRun\n");
290
291    ecore_list_for_each(idler_list, _IdlerRun, NULL);
292 }
293
294 /*
295  * Animators
296  */
297 #define DEBUG_ANIMATORS 0
298 static Ecore_List  *animator_list = NULL;
299 static Timer       *animator_timer = NULL;
300
301 typedef int         (AnimatorFunc) (void *data);
302
303 struct _animator {
304    AnimatorFunc       *func;
305    void               *data;
306 };
307
308 static void
309 _AnimatorRun(void *_an, void *prm __UNUSED__)
310 {
311    Animator           *an = (Animator *) _an;
312    int                 again;
313
314 #if DEBUG_ANIMATORS > 1
315    Eprintf("AnimatorRun %p\n", an);
316 #endif
317    again = an->func(an->data);
318    if (!again)
319       AnimatorDel(an);
320 }
321
322 static int
323 AnimatorsRun(void *data __UNUSED__)
324 {
325    ecore_list_for_each(animator_list, _AnimatorRun, NULL);
326
327    if (ecore_list_count(animator_list))
328      {
329         TimerSetInterval(animator_timer, 1e-3 * Conf.animation.step);
330         return 1;
331      }
332    else
333      {
334         animator_timer = NULL;
335         return 0;
336      }
337 }
338
339 Animator           *
340 AnimatorAdd(AnimatorFunc * func, void *data)
341 {
342    Animator           *an;
343
344    an = EMALLOC(Animator, 1);
345    if (!an)
346       return NULL;
347
348 #if DEBUG_ANIMATORS
349    Eprintf("AnimatorAdd %p func=%p data=%p\n", an, func, data);
350 #endif
351    an->func = func;
352    an->data = data;
353
354    if (!animator_list)
355       animator_list = ecore_list_new();
356
357    ecore_list_append(animator_list, an);
358
359    if (ecore_list_count(animator_list) == 1)
360      {
361         if (Conf.animation.step <= 0)
362            Conf.animation.step = 1;
363         /* Animator list was empty - Add to timer qeueue */
364         TIMER_ADD(animator_timer, 1e-3 * Conf.animation.step,
365                   AnimatorsRun, NULL);
366      }
367
368    return an;
369 }
370
371 void
372 AnimatorDel(Animator * an)
373 {
374 #if DEBUG_ANIMATORS
375    Eprintf("AnimatorDel %p func=%p data=%p\n", an, an->func, an->data);
376 #endif
377
378    ecore_list_node_remove(animator_list, an);
379    Efree(an);
380
381    if (ecore_list_count(animator_list) == 0)
382      {
383         /* Animator list is empty - Remove from timer qeueue */
384         TIMER_DEL(animator_timer);
385      }
386 }