]> Dogcows Code - chaz/openbox/blob - otk_c/timerqueue.c
nicer translate()
[chaz/openbox] / otk_c / timerqueue.c
1 // -*- mode: C; indent-tabs-mode: nil; c-basic-offset: 2; -*-
2
3 #include "../config.h"
4 #include "timerqueue.h"
5 #include "display.h"
6
7 #include <X11/Xlib.h>
8 #include <Python.h>
9
10 static PyObject *list = NULL; // PyListObject
11
12 void OtkTimerQueue_Initialize()
13 {
14 list = PyList_New(0);
15 }
16
17 void OtkTimerQueue_Add(OtkTimer* timer)
18 {
19 PyList_Append(list, (PyObject*)timer);
20 PyList_Sort(list);
21 }
22
23 void OtkTimerQueue_Remove(OtkTimer* timer)
24 {
25 int index;
26
27 index = PySequence_Index(list, (PyObject*)timer);
28 if (index >= 0)
29 PySequence_DelItem(list, index);
30 }
31
32 static Bool shouldFire(OtkTimer *timer, const struct timeval *now)
33 {
34 return ! ((now->tv_sec < timer->end.tv_sec) ||
35 (now->tv_sec == timer->end.tv_sec &&
36 now->tv_usec < timer->end.tv_usec));
37 }
38
39 static void normalizeTimeval(struct timeval *time)
40 {
41 while (time->tv_usec < 0) {
42 if (time->tv_sec > 0) {
43 --time->tv_sec;
44 time->tv_usec += 1000000;
45 } else {
46 time->tv_usec = 0;
47 }
48 }
49
50 if (time->tv_usec >= 1000000) {
51 time->tv_sec += time->tv_usec / 1000000;
52 time->tv_usec %= 1000000;
53 }
54
55 if (time->tv_sec < 0) time->tv_sec = 0;
56 }
57
58 void OtkTimerQueue_Fire()
59 {
60 fd_set rfds;
61 struct timeval now, tm, *timeout = NULL;
62
63 const int xfd = ConnectionNumber(OBDisplay->display);
64
65 FD_ZERO(&rfds);
66 FD_SET(xfd, &rfds); // break on any x events
67
68 // check for timer timeout
69 gettimeofday(&now, 0);
70
71 // there is a small chance for deadlock here:
72 // *IF* the timer list keeps getting refreshed *AND* the time between
73 // timer->start() and timer->shouldFire() is within the timer's period
74 // then the timer will keep firing. This should be VERY near impossible.
75 while (PyList_Size(list)) {
76 OtkTimer *timer = (OtkTimer*)PyList_GetItem(list, 0);
77
78 if (! shouldFire(timer, &now)) {
79 tm.tv_sec = timer->end.tv_sec - now.tv_sec;
80 tm.tv_usec = timer->end.tv_usec - now.tv_usec;
81 normalizeTimeval(&tm);
82 timeout = &tm; // set the timeout for the select
83 break; // go on and wait
84 }
85
86 // stop and remove the timer from the queue
87 PySequence_DelItem(list, 0);
88 timer->timing = False;
89
90 if (timer->handler)
91 timer->handler(timer->data);
92
93 if (timer->recur)
94 OtkTimer_Start(timer);
95 }
96
97 select(xfd + 1, &rfds, 0, 0, timeout);
98 }
This page took 0.036709 seconds and 4 git commands to generate.