about summary refs log tree commit diff
path: root/evloop/timer.c
diff options
context:
space:
mode:
authorRichard Nyberg <rnyberg@murmeldjur.se>2009-01-09 18:26:23 +0100
committerRichard Nyberg <rnyberg@murmeldjur.se>2009-01-11 15:26:46 +0100
commit59905999ce145a81e0003766d468945c2444a90e (patch)
treeb4b2f566942c2a4b90ab7a6d6111c73c49e4afc5 /evloop/timer.c
parent4457c1268a923d2a662ab23ca1b8d7920811ae51 (diff)
downloadbtpd-59905999ce145a81e0003766d468945c2444a90e.tar.gz
btpd-59905999ce145a81e0003766d468945c2444a90e.zip
Add evloop, btpd's new event loop. This will replace libevent.
Diffstat (limited to 'evloop/timer.c')
-rw-r--r--evloop/timer.c104
1 files changed, 104 insertions, 0 deletions
diff --git a/evloop/timer.c b/evloop/timer.c
new file mode 100644
index 0000000..3ef3091
--- /dev/null
+++ b/evloop/timer.c
@@ -0,0 +1,104 @@
+#include <time.h>
+
+#include "evloop.h"
+#include "timeheap.h"
+
+#if defined(CLOCK_MONOTONIC_FAST)
+#define TIMER_CLOCK CLOCK_MONOTONIC_FAST
+#elif defined(CLOCK_MONOTONIC)
+#define TIMER_CLOCK CLOCK_MONOTONIC
+#else
+#error CLOCK_MONOTONIC needed!
+#endif
+
+static struct timespec
+addtime(struct timespec a, struct timespec b)
+{
+    struct timespec ret;
+    ret.tv_sec = a.tv_sec + b.tv_sec;
+    ret.tv_nsec = a.tv_nsec + b.tv_nsec;
+    if (ret.tv_nsec >= 1000000000) {
+        ret.tv_sec  += 1;
+        ret.tv_nsec -= 1000000000;
+    }
+    return ret;
+}
+
+static struct timespec
+subtime(struct timespec a, struct timespec b)
+{
+    struct timespec ret;
+    ret.tv_sec = a.tv_sec - b.tv_sec;
+    ret.tv_nsec = a.tv_nsec - b.tv_nsec;
+    if (ret.tv_nsec < 0) {
+        ret.tv_sec  -= 1;
+        ret.tv_nsec += 1000000000;
+    }
+    return ret;
+}
+
+void
+timer_init(struct timeout *h, evloop_cb_t cb, void *arg)
+{
+    h->cb = cb;
+    h->arg = arg;
+    h->th.i = -1;
+    h->th.data = h;
+}
+
+int
+timer_add(struct timeout *h, struct timespec *t)
+{
+    struct timespec now, sum;
+    clock_gettime(TIMER_CLOCK, &now);
+    sum = addtime(now, *t);
+    if (h->th.i == -1)
+        return timeheap_insert(&h->th, &sum);
+    else {
+        timeheap_change(&h->th, &sum);
+        return 0;
+    }
+}
+
+void
+timer_del(struct timeout *h)
+{
+    if (h->th.i >= 0) {
+        timeheap_remove(&h->th);
+        h->th.i = -1;
+    }
+}
+
+void
+timers_run(void)
+{
+    struct timespec now;
+    clock_gettime(TIMER_CLOCK, &now);
+    while (timeheap_size() > 0) {
+        struct timespec diff = subtime(timeheap_top(), now);
+        if (diff.tv_sec < 0) {
+            struct timeout *t = timeheap_remove_top();
+            t->th.i = -1;
+            t->cb(-1, EV_TIMEOUT, t->arg);
+        } else
+            break;
+    }
+}
+
+struct timespec
+timer_delay(void)
+{
+    struct timespec now, diff;
+    if (timeheap_size() == 0) {
+        diff.tv_sec = -1;
+        diff.tv_nsec = 0;
+    } else {
+        clock_gettime(TIMER_CLOCK, &now);
+        diff = subtime(timeheap_top(), now);
+        if (diff.tv_sec < 0) {
+            diff.tv_sec = 0;
+            diff.tv_nsec = 0;
+        }
+    }
+    return diff;
+}