summaryrefslogtreecommitdiff
path: root/other/unused
diff options
context:
space:
mode:
Diffstat (limited to 'other/unused')
-rw-r--r--other/unused/timer.c290
-rw-r--r--other/unused/timer.h104
2 files changed, 394 insertions, 0 deletions
diff --git a/other/unused/timer.c b/other/unused/timer.c
new file mode 100644
index 00000000..29190921
--- /dev/null
+++ b/other/unused/timer.c
@@ -0,0 +1,290 @@
1#define __STDC_FORMAT_MACROS
2#include <inttypes.h>
3
4#include "timer.h"
5#include "network.h"
6
7/*
8A nested linked list increases efficiency of insertions.
9Depending on the number of timers we have, we might need to have nested linked lists
10in order to improve insertion efficiency.
11The code below is preperation for that end, should it be necessary.
12
13typedef struct {
14 struct timer_package* _next;
15 union {
16 timer_packet* _inner;
17 timer* queue;
18 };
19 uint64_t pkgtime;
20} timer_package;
21
22timer_package* timer_package_pool;
23
24static timer_package* new_package()
25{
26 timer_package* ret;
27 if (timer_package_pool) {
28 ret = timer_package_pool;
29 timer_package_pool = timer_package_pool->_next;
30 } else {
31 ret = calloc(1, sizeof(struct timer_package));
32 }
33 return ret;
34}
35
36static void delete_package(timer_package* p)
37{
38 p->_next = timer_package_pool;
39 timer_package_pool = p;
40}
41*/
42
43enum timer_state {
44 STATE_INACTIVE = 0,
45 STATE_ACTIVE,
46 STATE_CALLBACK
47};
48
49struct timer {
50 enum timer_state state;
51 timer *_prev;
52 timer *_next;
53 timer_callback cb;
54 void *userdata;
55 uint64_t deadline;
56};
57
58static timer *timer_main_queue;
59static timer *timer_us_queue; /* hi-speed queue */
60
61inline static void timer_dequeue(timer *t, timer **queue)
62{
63 if (t->state == STATE_INACTIVE) return; /* not in a queue */
64
65 if (t->_prev) {
66 t->_prev->_next = t->_next;
67 } else {
68 *queue = t->_next;
69 }
70
71 if (t->_next) t->_next->_prev = t->_prev;
72
73 t->state = STATE_INACTIVE;
74}
75
76static void timer_enqueue(timer *t, timer **queue, timer *prev)
77{
78 t->state = STATE_ACTIVE;
79
80 while (true) {
81 if (!*queue) {
82 t->_next = 0;
83 t->_prev = prev;
84 *queue = t;
85 return;
86 }
87
88 if ((*queue)->deadline > t->deadline) {
89 (*queue)->_prev = t;
90 t->_next = *queue;
91 t->_prev = prev;
92 *queue = t;
93 return;
94 }
95
96 prev = *queue;
97 queue = &((*queue)->_next);
98 }
99}
100
101/*** interface ***/
102
103void timer_init()
104{
105 /* Nothing needs to be done... yet. */
106}
107
108/* Do not depend on fields being zeroed */
109static timer *timer_pool; /* timer_pool is SINGLY LINKED!! */
110
111timer *new_timer(void)
112{
113 timer *ret;
114
115 if (timer_pool) {
116 ret = timer_pool;
117 timer_pool = timer_pool->_next;
118 } else {
119 ret = calloc(1, sizeof(struct timer));
120 }
121
122 ret->state = STATE_INACTIVE;
123 return ret;
124}
125
126void delete_timer(timer *t)
127{
128 timer_dequeue(t, &timer_main_queue);
129 t->_next = timer_pool;
130 t->state = STATE_INACTIVE;
131 timer_pool = t;
132}
133
134void timer_setup(timer *t, timer_callback cb, void *userarg)
135{
136 t->cb = cb;
137 t->userdata = userarg;
138}
139
140void *timer_get_userdata(timer *t)
141{
142 return t->userdata;
143}
144
145static void timer_delay_us(timer *t, int us)
146{
147 t->deadline += us;
148 timer **queue = t->_prev ? &(t->_prev->_next) : &timer_main_queue;
149 timer_dequeue(t, &timer_main_queue);
150 timer_enqueue(t, queue, t->_prev);
151}
152
153/* Starts the timer so that it's called in sec seconds in the future.
154 * A non-positive value of sec results in the callback being called immediately.
155 * This function may be called again after a timer has been started to adjust
156 * the expiry time. */
157void timer_start(timer *t, int sec)
158{
159 uint64_t newdeadline = current_time() + sec * US_PER_SECOND;
160
161 if (timer_is_active(t)) {
162 if (t->deadline < newdeadline) {
163 timer_delay_us(t, newdeadline - t->deadline);
164 return;
165 }
166
167 timer_dequeue(t, &timer_main_queue);
168 }
169
170 t->deadline = newdeadline;
171 timer_enqueue(t, &timer_main_queue, 0);
172}
173
174/* Stops the timer. Returns -1 if the timer was not active. */
175int timer_stop(timer *t)
176{
177 int ret = timer_is_active(t) ? -1 : 0;
178 timer_dequeue(t, &timer_main_queue);
179 return ret;
180}
181
182/* Adds additionalsec seconds to the timer.
183 * Returns -1 and does nothing if the timer was not active. */
184int timer_delay(timer *t, int additonalsec)
185{
186 if (!timer_is_active(t)) return -1;
187
188 timer_delay_us(t, additonalsec * US_PER_SECOND);
189 return 0;
190}
191
192static uint64_t timer_diff(timer *t, uint64_t time)
193{
194 if (t->deadline <= time) return 0;
195
196 return time - t->deadline;
197}
198
199/* Returns the time remaining on a timer in seconds.
200 * Returns -1 if the timer is not active.
201 * Returns 0 if the timer has expired and will be called upon the next call to timer_poll. */
202int timer_time_remaining(timer *t)
203{
204 if (!timer_is_active(t)) return -1;
205
206 return timer_diff(t, current_time()) / US_PER_SECOND;
207}
208
209bool timer_is_active(timer *t)
210{
211 return t->state != STATE_INACTIVE;
212}
213
214/* Single-use timer.
215 * Creates a new timer, preforms setup and starts it. */
216void timer_single(timer_callback cb, void *userarg, int sec)
217{
218 timer *t = new_timer();
219 timer_setup(t, cb, userarg);
220 timer_start(t, sec);
221}
222
223/* Single-use microsecond timer. */
224void timer_us(timer_callback cb, void *userarg, int us)
225{
226 timer *t = new_timer();
227 timer_setup(t, cb, userarg);
228 t->deadline = current_time() + us;
229 t->state = STATE_ACTIVE;
230 timer_enqueue(t, &timer_us_queue, 0);
231}
232
233uint64_t prevtime = 0;
234void timer_poll(void)
235{
236 uint64_t time = current_time();
237
238 /* Handle millisecond timers */
239 while (timer_us_queue) {
240 if (timer_diff(timer_us_queue, time) != 0) break;
241
242 timer *t = timer_us_queue;
243 timer_dequeue(t, &timer_us_queue);
244 t->cb(0, t->userdata);
245 delete_timer(t);
246 }
247
248 if (time - prevtime > US_PER_SECOND || prevtime == 0 || prevtime > time) {
249 /* time moving backwards is just a sanity check */
250 prevtime = time;
251
252 while (timer_main_queue) {
253 if (timer_diff(timer_main_queue, time) != 0) break;
254
255 timer *t = timer_main_queue;
256 t->state = STATE_CALLBACK;
257 int rv = t->cb(t, t->userdata);
258
259 if (rv != 0) {
260 timer_dequeue(t, &timer_main_queue);
261 delete_timer(t);
262 continue;
263 }
264
265 if (t->state != STATE_ACTIVE) {
266 timer_dequeue(t, &timer_main_queue);
267 }
268 }
269 }
270}
271
272/*** Internal Testing ***/
273
274/* I do not want to expose internals to the public,
275 * which is why internals testing is done this way. */
276void timer_internal_tests(bool (*assert)(bool, char *))
277{
278
279}
280
281void timer_debug_print()
282{
283 timer *t = timer_main_queue;
284 printf("Queue:\n");
285
286 while (t) {
287 printf("%" PRIu64 " (%" PRIu64 ") : %s\n", t->deadline, t->deadline / US_PER_SECOND, (char *)t->userdata);
288 t = t->_next;
289 }
290}
diff --git a/other/unused/timer.h b/other/unused/timer.h
new file mode 100644
index 00000000..15491326
--- /dev/null
+++ b/other/unused/timer.h
@@ -0,0 +1,104 @@
1/* timer.h
2 *
3 * Timing subsystem. Provides deadline timers.
4 * All times are aliased to a second for efficiency.
5 *
6 * Timer Guarantees:
7 * - The callback will not be called before the timer expires.
8 * - The callback will be called sometime after the timer expires,
9 * on a best effort basis.
10 * - If timer_poll is called at least once a second, the callback
11 * will be called at most one second after it expires.
12 *
13 * Copyright (C) 2013 Tox project All Rights Reserved.
14 *
15 * This file is part of Tox.
16 *
17 * Tox is free software: you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License as published by
19 * the Free Software Foundation, either version 3 of the License, or
20 * (at your option) any later version.
21 *
22 * Tox is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 *
27 * You should have received a copy of the GNU General Public License
28 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
29 *
30 */
31
32#ifndef TIMER_H
33#define TIMER_H
34
35#include <stdint.h>
36#include <stdbool.h>
37
38#define US_PER_SECOND 1000000 /* 1 s = 10^6 us */
39
40struct timer;
41typedef struct timer timer;
42
43/* If time_callback returns a non-zero value, timer t is deleted.
44 * You may call any of the timer functions within the callback:
45 * For example, you may call timer_start to restart the timer from
46 * within a callback. */
47typedef int (*timer_callback)(timer *t, void *userarg);
48
49/* Initisalise timer subsystem */
50void timer_init(void);
51
52/* Poll. (I will eventually replace all polling in Tox with an async system.) */
53void timer_poll(void);
54
55/* Creates a new timer. Does not enqueue/start it. */
56timer *new_timer(void);
57
58/* Destroys a timer instance. */
59void delete_timer(timer *t);
60
61/* Sets up the timer callback. */
62void timer_setup(timer *t, timer_callback cb, void *userarg);
63
64/* Accessor Function. */
65void *timer_get_userdata(timer *t);
66
67/* Starts the timer so that it's called in sec seconds in the future from now.
68 * A non-positive value of sec results in the callback being called immediately.
69 * This function may be called again after a timer has been started to adjust
70 * the expiry time. */
71void timer_start(timer *t, int sec);
72
73/* Stops the timer. Returns -1 if the timer was not active. */
74int timer_stop(timer *t);
75
76/* Adds additionalsec seconds to the timer.
77 * Returns -1 and does nothing if the timer was not active. */
78int timer_delay(timer *t, int additonalsec);
79
80/* Returns the time remaining on a timer in seconds.
81 * Returns -1 if the timer is not active.
82 * Returns 0 if the timer has expired and the callback hasn't been called yet. */
83int timer_time_remaining(timer *t);
84
85/* Determines if timer is active. Returns TRUE if it is active */
86bool timer_is_active(timer *t);
87
88/* Single-use timer.
89 * Creates a new timer, preforms setup and starts it.
90 * Callback must return a non-zero value to prevent memory leak. */
91void timer_single(timer_callback cb, void *userarg, int sec);
92
93/* Single-use microsecond timer.
94 * Creates a new timer, preforms setup and starts it.
95 * Please do not use this when accuracy is not absolutely required.
96 * Use when one needs to time a period < 1 s.
97 * Use the more coarse timers above for periods > 5 s.
98 * WARNING: the callback will be called with NULL as the first argument */
99void timer_us(timer_callback cb, void *userarg, int us);
100
101/* Internal Testing */
102void timer_internal_tests(bool( *)(bool, char *));
103
104#endif