|
160
|
1 /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
|
|
2 * Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
3 * of this software and associated documentation files (the "Software"), to
|
|
|
4 * deal in the Software without restriction, including without limitation the
|
|
|
5 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
|
6 * sell copies of the Software, and to permit persons to whom the Software is
|
|
|
7 * furnished to do so, subject to the following conditions:
|
|
|
8 *
|
|
|
9 * The above copyright notice and this permission notice shall be included in
|
|
|
10 * all copies or substantial portions of the Software.
|
|
|
11 *
|
|
|
12 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
13 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
14 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
15 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
16 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
|
17 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
|
18 * IN THE SOFTWARE.
|
|
|
19 */
|
|
|
20
|
|
|
21 #include "uv.h"
|
|
|
22 #include "uv-common.h"
|
|
|
23 #include "heap-inl.h"
|
|
|
24
|
|
|
25 #include <assert.h>
|
|
|
26 #include <limits.h>
|
|
|
27
|
|
|
28
|
|
|
29 static struct heap *timer_heap(const uv_loop_t* loop) {
|
|
|
30 #ifdef _WIN32
|
|
|
31 return (struct heap*) loop->timer_heap;
|
|
|
32 #else
|
|
|
33 return (struct heap*) &loop->timer_heap;
|
|
|
34 #endif
|
|
|
35 }
|
|
|
36
|
|
|
37
|
|
|
38 static int timer_less_than(const struct heap_node* ha,
|
|
|
39 const struct heap_node* hb) {
|
|
|
40 const uv_timer_t* a;
|
|
|
41 const uv_timer_t* b;
|
|
|
42
|
|
|
43 a = container_of(ha, uv_timer_t, node.heap);
|
|
|
44 b = container_of(hb, uv_timer_t, node.heap);
|
|
|
45
|
|
|
46 if (a->timeout < b->timeout)
|
|
|
47 return 1;
|
|
|
48 if (b->timeout < a->timeout)
|
|
|
49 return 0;
|
|
|
50
|
|
|
51 /* Compare start_id when both have the same timeout. start_id is
|
|
|
52 * allocated with loop->timer_counter in uv_timer_start().
|
|
|
53 */
|
|
|
54 return a->start_id < b->start_id;
|
|
|
55 }
|
|
|
56
|
|
|
57
|
|
|
58 int uv_timer_init(uv_loop_t* loop, uv_timer_t* handle) {
|
|
|
59 uv__handle_init(loop, (uv_handle_t*)handle, UV_TIMER);
|
|
|
60 handle->timer_cb = NULL;
|
|
|
61 handle->timeout = 0;
|
|
|
62 handle->repeat = 0;
|
|
|
63 uv__queue_init(&handle->node.queue);
|
|
|
64 return 0;
|
|
|
65 }
|
|
|
66
|
|
|
67
|
|
|
68 int uv_timer_start(uv_timer_t* handle,
|
|
|
69 uv_timer_cb cb,
|
|
|
70 uint64_t timeout,
|
|
|
71 uint64_t repeat) {
|
|
|
72 uint64_t clamped_timeout;
|
|
|
73
|
|
|
74 if (uv__is_closing(handle) || cb == NULL)
|
|
|
75 return UV_EINVAL;
|
|
|
76
|
|
|
77 uv_timer_stop(handle);
|
|
|
78
|
|
|
79 clamped_timeout = handle->loop->time + timeout;
|
|
|
80 if (clamped_timeout < timeout)
|
|
|
81 clamped_timeout = (uint64_t) -1;
|
|
|
82
|
|
|
83 handle->timer_cb = cb;
|
|
|
84 handle->timeout = clamped_timeout;
|
|
|
85 handle->repeat = repeat;
|
|
|
86 /* start_id is the second index to be compared in timer_less_than() */
|
|
|
87 handle->start_id = handle->loop->timer_counter++;
|
|
|
88
|
|
|
89 heap_insert(timer_heap(handle->loop),
|
|
|
90 (struct heap_node*) &handle->node.heap,
|
|
|
91 timer_less_than);
|
|
|
92 uv__handle_start(handle);
|
|
|
93
|
|
|
94 return 0;
|
|
|
95 }
|
|
|
96
|
|
|
97
|
|
|
98 int uv_timer_stop(uv_timer_t* handle) {
|
|
|
99 if (uv__is_active(handle)) {
|
|
|
100 heap_remove(timer_heap(handle->loop),
|
|
|
101 (struct heap_node*) &handle->node.heap,
|
|
|
102 timer_less_than);
|
|
|
103 uv__handle_stop(handle);
|
|
|
104 } else {
|
|
|
105 uv__queue_remove(&handle->node.queue);
|
|
|
106 }
|
|
|
107
|
|
|
108 uv__queue_init(&handle->node.queue);
|
|
|
109 return 0;
|
|
|
110 }
|
|
|
111
|
|
|
112
|
|
|
113 int uv_timer_again(uv_timer_t* handle) {
|
|
|
114 if (handle->timer_cb == NULL)
|
|
|
115 return UV_EINVAL;
|
|
|
116
|
|
|
117 if (handle->repeat) {
|
|
|
118 uv_timer_stop(handle);
|
|
|
119 uv_timer_start(handle, handle->timer_cb, handle->repeat, handle->repeat);
|
|
|
120 }
|
|
|
121
|
|
|
122 return 0;
|
|
|
123 }
|
|
|
124
|
|
|
125
|
|
|
126 void uv_timer_set_repeat(uv_timer_t* handle, uint64_t repeat) {
|
|
|
127 handle->repeat = repeat;
|
|
|
128 }
|
|
|
129
|
|
|
130
|
|
|
131 uint64_t uv_timer_get_repeat(const uv_timer_t* handle) {
|
|
|
132 return handle->repeat;
|
|
|
133 }
|
|
|
134
|
|
|
135
|
|
|
136 uint64_t uv_timer_get_due_in(const uv_timer_t* handle) {
|
|
|
137 if (handle->loop->time >= handle->timeout)
|
|
|
138 return 0;
|
|
|
139
|
|
|
140 return handle->timeout - handle->loop->time;
|
|
|
141 }
|
|
|
142
|
|
|
143
|
|
|
144 int uv__next_timeout(const uv_loop_t* loop) {
|
|
|
145 const struct heap_node* heap_node;
|
|
|
146 const uv_timer_t* handle;
|
|
|
147 uint64_t diff;
|
|
|
148
|
|
|
149 heap_node = heap_min(timer_heap(loop));
|
|
|
150 if (heap_node == NULL)
|
|
|
151 return -1; /* block indefinitely */
|
|
|
152
|
|
|
153 handle = container_of(heap_node, uv_timer_t, node.heap);
|
|
|
154 if (handle->timeout <= loop->time)
|
|
|
155 return 0;
|
|
|
156
|
|
|
157 diff = handle->timeout - loop->time;
|
|
|
158 if (diff > INT_MAX)
|
|
|
159 diff = INT_MAX;
|
|
|
160
|
|
|
161 return (int) diff;
|
|
|
162 }
|
|
|
163
|
|
|
164
|
|
|
165 void uv__run_timers(uv_loop_t* loop) {
|
|
|
166 struct heap_node* heap_node;
|
|
|
167 uv_timer_t* handle;
|
|
|
168 struct uv__queue* queue_node;
|
|
|
169 struct uv__queue ready_queue;
|
|
|
170
|
|
|
171 uv__queue_init(&ready_queue);
|
|
|
172
|
|
|
173 for (;;) {
|
|
|
174 heap_node = heap_min(timer_heap(loop));
|
|
|
175 if (heap_node == NULL)
|
|
|
176 break;
|
|
|
177
|
|
|
178 handle = container_of(heap_node, uv_timer_t, node.heap);
|
|
|
179 if (handle->timeout > loop->time)
|
|
|
180 break;
|
|
|
181
|
|
|
182 uv_timer_stop(handle);
|
|
|
183 uv__queue_insert_tail(&ready_queue, &handle->node.queue);
|
|
|
184 }
|
|
|
185
|
|
|
186 while (!uv__queue_empty(&ready_queue)) {
|
|
|
187 queue_node = uv__queue_head(&ready_queue);
|
|
|
188 uv__queue_remove(queue_node);
|
|
|
189 uv__queue_init(queue_node);
|
|
|
190 handle = container_of(queue_node, uv_timer_t, node.queue);
|
|
|
191
|
|
|
192 uv_timer_again(handle);
|
|
|
193 handle->timer_cb(handle);
|
|
|
194 }
|
|
|
195 }
|
|
|
196
|
|
|
197
|
|
|
198 void uv__timer_close(uv_timer_t* handle) {
|
|
|
199 uv_timer_stop(handle);
|
|
|
200 }
|