-
Notifications
You must be signed in to change notification settings - Fork 587
/
Timeout.c
127 lines (111 loc) · 4.18 KB
/
Timeout.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#include <stdint.h>
#include <sys/time.h>
#include <event2/event.h>
#include "memory/MemAllocator.h"
#include "util/Timeout.h"
struct Timeout
{
void (* callback)(void* callbackContext);
void* callbackContext;
struct event* event;
};
/**
* The callback to be called by libevent.
*
* @param socket unused since this is a pure timeout event.
* @param eventType unused since we know what type of event this will be.
* @param vcontext the Timeout structure.
*/
static void handleEvent(evutil_socket_t socket,
short eventType,
void* vcontext)
{
// unused
socket = socket;
eventType = eventType;
struct Timeout* timeout = (struct Timeout*) vcontext;
timeout->callback(timeout->callbackContext);
}
/**
* A callback to be called by a memory allocator on free.
*
* @param vcontext the Timeout structure.
*/
static void deleteEvent(void* vcontext)
{
event_del(((struct Timeout*) vcontext)->event);
}
/**
* @param numberOfMilliseconds that
* @return numberOfMilliseconds as a timeval struct.
*/
static struct timeval timeForMilliseconds(const uint64_t numberOfMilliseconds)
{
return (struct timeval) {
.tv_sec = numberOfMilliseconds / 1000,
.tv_usec = (numberOfMilliseconds % 1000) * 1000
};
}
/**
* Create a timeout event.
* The timeout event will be triggered after the given number of milliseconds.
*
* @param callback the functiont to call.
* @param callbackContext a pointer to pass to the called function.
* @param milliseconds the number of milliseconds to wait before the event happens.
* @param interval if non-zero, this event will repeat instead of triggering once.
* @param eventBase the libevent event base.
* @param allocator the memory allocator to use for allocating the event.
* if this is freed, the event will be safely deleted.
* @return a timeout struct which can be used to clear the timeout.
*/
static struct Timeout* setTimeout(void (* const callback)(void* callbackContext),
void* const callbackContext,
const uint64_t milliseconds,
const uint32_t interval,
struct event_base* eventBase,
const struct MemAllocator* allocator)
{
struct Timeout* timeout =
allocator->malloc(sizeof(struct Timeout) + event_get_struct_event_size(), allocator);
timeout->callback = callback;
timeout->callbackContext = callbackContext;
// Skip to after the end of the timeout and make that the event.
timeout->event = (struct event*) &timeout[1];
allocator->onFree(deleteEvent, timeout, allocator);
event_assign(timeout->event, eventBase, -1, ((interval) ? EV_PERSIST : 0), handleEvent, timeout);
struct timeval time = timeForMilliseconds(milliseconds);
event_add(timeout->event, &time);
return timeout;
}
/** See: Timeout.h */
struct Timeout* Timeout_setTimeout(void (* const callback)(void* callbackContext),
void* const callbackContext,
const uint64_t milliseconds,
struct event_base* eventBase,
const struct MemAllocator* allocator)
{
return setTimeout(callback, callbackContext, milliseconds, 0, eventBase, allocator);
}
/** See: Timeout.h */
struct Timeout* Timeout_setInterval(void (* const callback)(void* callbackContext),
void* const callbackContext,
const uint64_t milliseconds,
struct event_base* eventBase,
const struct MemAllocator* allocator)
{
return setTimeout(callback, callbackContext, milliseconds, 1, eventBase, allocator);
}
/** See: Timeout.h */
void Timeout_resetTimeout(struct Timeout* timeout,
const uint64_t milliseconds)
{
event_del(timeout->event);
struct timeval time = timeForMilliseconds(milliseconds);
event_add(timeout->event, &time);
}
/** See: Timeout.h */
void Timeout_clearTimeout(struct Timeout* timeout)
{
event_del(timeout->event);
}