]>
Dogcows Code - chaz/tint2/blob - src/util/timer.c
1 /**************************************************************************
3 * Copyright (C) 2009 Andreas.Fink (Andreas.Fink85@gmail.com)
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License version 2
7 * as published by the Free Software Foundation.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 **************************************************************************/
23 GSList
* timeout_list
= 0;
24 struct timespec next_timeout
;
26 void add_timeout_intern(int value_msec
, int interval_msec
, void(*_callback
)(), struct timeout
* t
);
27 gint
compare_timeouts(gconstpointer t1
, gconstpointer t2
);
28 gint
compare_timespecs(const struct timespec
* t1
, const struct timespec
* t2
);
29 int timespec_subtract(struct timespec
* result
, struct timespec
* x
, struct timespec
* y
);
32 const struct timeout
* add_timeout(int value_msec
, int interval_msec
, void (*_callback
)())
34 struct timeout
* t
= malloc(sizeof(struct timeout
));
35 add_timeout_intern(value_msec
, interval_msec
, _callback
, t
);
40 void change_timeout(const struct timeout
*t
, int value_msec
, int interval_msec
, void(*_callback
)())
42 timeout_list
= g_slist_remove(timeout_list
, t
);
43 add_timeout_intern(value_msec
, interval_msec
, _callback
, (struct timeout
*)t
);
47 void update_next_timeout()
50 struct timeout
* t
= timeout_list
->data
;
51 struct timespec cur_time
;
52 clock_gettime(CLOCK_MONOTONIC
, &cur_time
);
53 if (timespec_subtract(&next_timeout
, &t
->timeout_expires
, &cur_time
)) {
54 next_timeout
.tv_sec
= 0;
55 next_timeout
.tv_nsec
= 0;
59 next_timeout
.tv_sec
= -1;
63 void callback_timeout_expired()
65 struct timespec cur_time
;
67 while (timeout_list
) {
68 clock_gettime(CLOCK_MONOTONIC
, &cur_time
);
69 t
= timeout_list
->data
;
70 if (compare_timespecs(&t
->timeout_expires
, &cur_time
) <= 0) {
71 // it's time for the callback function
73 if (g_slist_find(timeout_list
, t
)) {
74 // if _callback() calls stop_timeout(t) the timeout 't' does not exist anymore
75 timeout_list
= g_slist_remove(timeout_list
, t
);
76 if (t
->interval_msec
> 0)
77 add_timeout_intern(t
->interval_msec
, t
->interval_msec
, t
->_callback
, t
);
88 void stop_timeout(const struct timeout
* t
)
90 if (g_slist_find(timeout_list
, t
)) {
91 timeout_list
= g_slist_remove(timeout_list
, t
);
97 void stop_all_timeouts()
99 while (timeout_list
) {
100 free(timeout_list
->data
);
101 timeout_list
= g_slist_remove(timeout_list
, timeout_list
->data
);
106 void add_timeout_intern(int value_msec
, int interval_msec
, void(*_callback
)(), struct timeout
*t
)
108 t
->interval_msec
= interval_msec
;
109 t
->_callback
= _callback
;
110 struct timespec expire
;
111 clock_gettime(CLOCK_MONOTONIC
, &expire
);
112 expire
.tv_sec
+= value_msec
/ 1000;
113 expire
.tv_nsec
+= (value_msec
% 1000)*1000000;
114 if (expire
.tv_nsec
>= 1000000000) { // 10^9
116 expire
.tv_nsec
-= 1000000000;
118 t
->timeout_expires
= expire
;
119 timeout_list
= g_slist_insert_sorted(timeout_list
, t
, compare_timeouts
);
123 gint
compare_timeouts(gconstpointer t1
, gconstpointer t2
)
125 return compare_timespecs(&((const struct timeout
*)t1
)->timeout_expires
,
126 &((const struct timeout
*)t2
)->timeout_expires
);
130 gint
compare_timespecs(const struct timespec
* t1
, const struct timespec
* t2
)
132 if (t1
->tv_sec
< t2
->tv_sec
)
134 else if (t1
->tv_sec
== t2
->tv_sec
) {
135 if (t1
->tv_nsec
< t2
->tv_nsec
)
137 else if (t1
->tv_nsec
== t2
->tv_nsec
)
146 int timespec_subtract(struct timespec
* result
, struct timespec
* x
, struct timespec
* y
)
148 /* Perform the carry for the later subtraction by updating y. */
149 if (x
->tv_nsec
< y
->tv_nsec
) {
150 int nsec
= (y
->tv_nsec
- x
->tv_nsec
) / 1000000000 + 1;
151 y
->tv_nsec
-= 1000000000 * nsec
;
154 if (x
->tv_nsec
- y
->tv_nsec
> 1000000000) {
155 int nsec
= (x
->tv_nsec
- y
->tv_nsec
) / 1000000000;
156 y
->tv_nsec
+= 1000000000 * nsec
;
160 /* Compute the time remaining to wait. tv_nsec is certainly positive. */
161 result
->tv_sec
= x
->tv_sec
- y
->tv_sec
;
162 result
->tv_nsec
= x
->tv_nsec
- y
->tv_nsec
;
164 /* Return 1 if result is negative. */
165 return x
->tv_sec
< y
->tv_sec
;
This page took 0.044035 seconds and 5 git commands to generate.