libuv-svace-build
200 строк · 5.1 Кб
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
29static struct heap *timer_heap(const uv_loop_t* loop) {30#ifdef _WIN3231return (struct heap*) loop->timer_heap;32#else33return (struct heap*) &loop->timer_heap;34#endif35}
36
37
38static int timer_less_than(const struct heap_node* ha,39const struct heap_node* hb) {40const uv_timer_t* a;41const uv_timer_t* b;42
43a = container_of(ha, uv_timer_t, node.heap);44b = container_of(hb, uv_timer_t, node.heap);45
46if (a->timeout < b->timeout)47return 1;48if (b->timeout < a->timeout)49return 0;50
51/* Compare start_id when both have the same timeout. start_id is52* allocated with loop->timer_counter in uv_timer_start().
53*/
54return a->start_id < b->start_id;55}
56
57
58int uv_timer_init(uv_loop_t* loop, uv_timer_t* handle) {59uv__handle_init(loop, (uv_handle_t*)handle, UV_TIMER);60handle->timer_cb = NULL;61handle->timeout = 0;62handle->repeat = 0;63uv__queue_init(&handle->node.queue);64return 0;65}
66
67
68int uv_timer_start(uv_timer_t* handle,69uv_timer_cb cb,70uint64_t timeout,71uint64_t repeat) {72uint64_t clamped_timeout;73
74if (uv__is_closing(handle) || cb == NULL)75return UV_EINVAL;76
77uv_timer_stop(handle);78
79clamped_timeout = handle->loop->time + timeout;80if (clamped_timeout < timeout)81clamped_timeout = (uint64_t) -1;82
83handle->timer_cb = cb;84handle->timeout = clamped_timeout;85handle->repeat = repeat;86/* start_id is the second index to be compared in timer_less_than() */87handle->start_id = handle->loop->timer_counter++;88
89heap_insert(timer_heap(handle->loop),90(struct heap_node*) &handle->node.heap,91timer_less_than);92uv__handle_start(handle);93
94return 0;95}
96
97
98int uv_timer_stop(uv_timer_t* handle) {99if (uv__is_active(handle)) {100heap_remove(timer_heap(handle->loop),101(struct heap_node*) &handle->node.heap,102timer_less_than);103uv__handle_stop(handle);104} else {105uv__queue_remove(&handle->node.queue);106}107
108uv__queue_init(&handle->node.queue);109return 0;110}
111
112
113int uv_timer_again(uv_timer_t* handle) {114if (handle->timer_cb == NULL)115return UV_EINVAL;116
117if (handle->repeat) {118uv_timer_stop(handle);119uv_timer_start(handle, handle->timer_cb, handle->repeat, handle->repeat);120}121
122return 0;123}
124
125
126void uv_timer_set_repeat(uv_timer_t* handle, uint64_t repeat) {127handle->repeat = repeat;128}
129
130
131uint64_t uv_timer_get_repeat(const uv_timer_t* handle) {132return handle->repeat;133}
134
135
136uint64_t uv_timer_get_due_in(const uv_timer_t* handle) {137if (handle->loop->time >= handle->timeout)138return 0;139
140return handle->timeout - handle->loop->time;141}
142
143
144int uv__next_timeout(const uv_loop_t* loop) {145const struct heap_node* heap_node;146const uv_timer_t* handle;147uint64_t diff;148
149heap_node = heap_min(timer_heap(loop));150if (heap_node == NULL)151return -1; /* block indefinitely */152
153handle = container_of(heap_node, uv_timer_t, node.heap);154if (handle->timeout <= loop->time)155return 0;156
157diff = handle->timeout - loop->time;158if (diff > INT_MAX)159diff = INT_MAX;160
161return (int) diff;162}
163
164
165void uv__run_timers(uv_loop_t* loop) {166struct heap_node* heap_node;167uv_timer_t* handle;168struct uv__queue* queue_node;169struct uv__queue ready_queue;170
171uv__queue_init(&ready_queue);172
173for (;;) {174heap_node = heap_min(timer_heap(loop));175if (heap_node == NULL)176break;177
178handle = container_of(heap_node, uv_timer_t, node.heap);179if (handle->timeout > loop->time)180break;181
182uv_timer_stop(handle);183uv__queue_insert_tail(&ready_queue, &handle->node.queue);184}185
186while (!uv__queue_empty(&ready_queue)) {187queue_node = uv__queue_head(&ready_queue);188uv__queue_remove(queue_node);189uv__queue_init(queue_node);190handle = container_of(queue_node, uv_timer_t, node.queue);191
192uv_timer_again(handle);193handle->timer_cb(handle);194}195}
196
197
198void uv__timer_close(uv_timer_t* handle) {199uv_timer_stop(handle);200}
201