aboutsummaryrefslogtreecommitdiff
path: root/src/lib/common/timeout.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/common/timeout.c')
-rw-r--r--src/lib/common/timeout.c131
1 files changed, 131 insertions, 0 deletions
diff --git a/src/lib/common/timeout.c b/src/lib/common/timeout.c
new file mode 100644
index 0000000..b12780b
--- /dev/null
+++ b/src/lib/common/timeout.c
@@ -0,0 +1,131 @@
1#include "timeout.h"
2
3#include <stdbool.h>
4
5#define LOG(kind, ...) GNUNET_log_from (kind, "dbus-timeout", __VA_ARGS__)
6
7struct Timeout
8{
9 /* doubly-linked list */
10 struct Timeout *next;
11 struct Timeout *prev;
12
13 DBusTimeout *timeout;
14
15 bool scheduled;
16
17 struct GNUNET_SCHEDULER_Task *task;
18
19 unsigned ref_count;
20};
21
22struct Timeout *
23timeout_create (
24 DBusTimeout *timeout)
25{
26 struct Timeout *t = GNUNET_new (struct Timeout);
27
28 t->timeout = timeout;
29 t->scheduled = false;
30 t->ref_count = 1;
31
32 return t;
33}
34
35void
36timeout_ref (
37 struct Timeout *t)
38{
39 t->ref_count++;
40}
41
42void
43timeout_unref (
44 struct Timeout *t)
45{
46 if (0 == t->ref_count)
47 {
48 LOG (GNUNET_ERROR_TYPE_ERROR, "Tried to unref timeout with ref_count == 0\n");
49 GNUNET_abort_ ();
50 };
51
52 if (0 == --t->ref_count)
53 {
54 GNUNET_free (t);
55 }
56}
57
58static void
59handle_timeout (
60 void *cls,
61 const struct GNUNET_SCHEDULER_TaskContext *tc)
62{
63 struct Timeout *t = (struct Timeout *)cls;
64
65 t->scheduled = false;
66
67 if (tc->reason & GNUNET_SCHEDULER_REASON_TIMEOUT)
68 dbus_timeout_handle (t->timeout);
69
70 if (t->ref_count > 1 && ! (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
71 timeout_schedule (t);
72 timeout_unref (t);
73};
74
75void
76timeout_schedule (
77 struct Timeout *t)
78{
79 if (! dbus_timeout_get_enabled (t->timeout))
80 {
81 LOG (GNUNET_ERROR_TYPE_WARNING, "Tried to schedule timeout that is disabled!\n");
82 return;
83 };
84
85 if (t->scheduled)
86 return;
87
88 int interval = dbus_timeout_get_interval (t->timeout);
89 struct GNUNET_TIME_Relative delay;
90 delay.rel_value_us = interval * 1000;
91 t->task = GNUNET_SCHEDULER_add_delayed (
92 delay,
93 handle_timeout,
94 t);
95 t->scheduled = true;
96 timeout_ref (t);
97}
98
99void
100do_timeout_unschedule (
101 void *cls,
102 const struct GNUNET_SCHEDULER_TaskContext *tc)
103{
104 (void)tc;
105 struct Timeout *t = (struct Timeout *)cls;
106
107 if (! t->scheduled)
108 return;
109
110 void *ret = GNUNET_SCHEDULER_cancel (t->task);
111 if ((struct Timeout *)ret != t)
112 LOG (GNUNET_ERROR_TYPE_WARNING, "Weird result unscheduling task. t == %p, GNUNET_SCHEDULER_cancel returned %p\n", t, ret);
113
114 timeout_unref (t);
115}
116
117void
118timeout_unschedule (
119 struct Timeout *t)
120{
121 GNUNET_SCHEDULER_add_now (do_timeout_unschedule, t);
122}
123
124struct TimeoutIter *
125timeout_find (struct TimeoutIter *ti, DBusTimeout *timeout)
126{
127 while (ti && ti->t->timeout != timeout)
128 ti = ti->next;
129 return ti;
130}
131