Skip to content

Commit 3fbf000

Browse files
Fishrock123ulrikstrid
authored andcommitted
unix,win: add uv_timer_get_timeout()
Refs: nodejs/node-report#73
1 parent e44781a commit 3fbf000

5 files changed

Lines changed: 217 additions & 0 deletions

File tree

docs/src/timer.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,4 +78,10 @@ API
7878
7979
Get the timer repeat value.
8080
81+
.. c:function:: uint64_t uv_timer_get_timeout(const uv_timer_t* handle)
82+
83+
Get the timer timeout value.
84+
85+
.. versionadded:: 1.12.0
86+
8187
.. seealso:: The :c:type:`uv_handle_t` API functions also apply.

include/uv.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -865,6 +865,7 @@ UV_EXTERN int uv_timer_stop(uv_timer_t* handle);
865865
UV_EXTERN int uv_timer_again(uv_timer_t* handle);
866866
UV_EXTERN void uv_timer_set_repeat(uv_timer_t* handle, uint64_t repeat);
867867
UV_EXTERN uint64_t uv_timer_get_repeat(const uv_timer_t* handle);
868+
UV_EXTERN uint64_t uv_timer_get_timeout(const uv_timer_t* handle);
868869

869870

870871
/*

src/timer.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,11 @@ uint64_t uv_timer_get_repeat(const uv_timer_t* handle) {
130130
}
131131

132132

133+
uint64_t uv_timer_get_timeout(const uv_timer_t* handle) {
134+
return handle->timeout;
135+
}
136+
137+
133138
int uv__next_timeout(const uv_loop_t* loop) {
134139
const struct heap_node* heap_node;
135140
const uv_timer_t* handle;

src/win/timer.c

Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
2+
*
3+
* Permission is hereby granted, free of charge, to any person obtaining a copy
4+
* of this software and associated documentation files (the "Software"), to
5+
* deal in the Software without restriction, including without limitation the
6+
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7+
* sell copies of the Software, and to permit persons to whom the Software is
8+
* furnished to do so, subject to the following conditions:
9+
*
10+
* The above copyright notice and this permission notice shall be included in
11+
* all copies or substantial portions of the Software.
12+
*
13+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18+
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19+
* IN THE SOFTWARE.
20+
*/
21+
22+
#include <assert.h>
23+
#include <limits.h>
24+
25+
#include "uv.h"
26+
#include "internal.h"
27+
#include "tree.h"
28+
#include "handle-inl.h"
29+
30+
31+
/* The number of milliseconds in one second. */
32+
#define UV__MILLISEC 1000
33+
34+
35+
void uv_update_time(uv_loop_t* loop) {
36+
uint64_t new_time = uv__hrtime(UV__MILLISEC);
37+
assert(new_time >= loop->time);
38+
loop->time = new_time;
39+
}
40+
41+
42+
static int uv_timer_compare(uv_timer_t* a, uv_timer_t* b) {
43+
if (a->due < b->due)
44+
return -1;
45+
if (a->due > b->due)
46+
return 1;
47+
/*
48+
* compare start_id when both has the same due. start_id is
49+
* allocated with loop->timer_counter in uv_timer_start().
50+
*/
51+
if (a->start_id < b->start_id)
52+
return -1;
53+
if (a->start_id > b->start_id)
54+
return 1;
55+
return 0;
56+
}
57+
58+
59+
RB_GENERATE_STATIC(uv_timer_tree_s, uv_timer_s, tree_entry, uv_timer_compare);
60+
61+
62+
int uv_timer_init(uv_loop_t* loop, uv_timer_t* handle) {
63+
uv__handle_init(loop, (uv_handle_t*) handle, UV_TIMER);
64+
handle->timer_cb = NULL;
65+
handle->repeat = 0;
66+
67+
return 0;
68+
}
69+
70+
71+
void uv_timer_endgame(uv_loop_t* loop, uv_timer_t* handle) {
72+
if (handle->flags & UV__HANDLE_CLOSING) {
73+
assert(!(handle->flags & UV_HANDLE_CLOSED));
74+
uv__handle_close(handle);
75+
}
76+
}
77+
78+
79+
static uint64_t get_clamped_due_time(uint64_t loop_time, uint64_t timeout) {
80+
uint64_t clamped_timeout;
81+
82+
clamped_timeout = loop_time + timeout;
83+
if (clamped_timeout < timeout)
84+
clamped_timeout = (uint64_t) -1;
85+
86+
return clamped_timeout;
87+
}
88+
89+
90+
int uv_timer_start(uv_timer_t* handle, uv_timer_cb timer_cb, uint64_t timeout,
91+
uint64_t repeat) {
92+
uv_loop_t* loop = handle->loop;
93+
uv_timer_t* old;
94+
95+
if (timer_cb == NULL)
96+
return UV_EINVAL;
97+
98+
if (uv__is_active(handle))
99+
uv_timer_stop(handle);
100+
101+
handle->timer_cb = timer_cb;
102+
handle->due = get_clamped_due_time(loop->time, timeout);
103+
handle->repeat = repeat;
104+
uv__handle_start(handle);
105+
106+
/* start_id is the second index to be compared in uv__timer_cmp() */
107+
handle->start_id = handle->loop->timer_counter++;
108+
109+
old = RB_INSERT(uv_timer_tree_s, &loop->timers, handle);
110+
assert(old == NULL);
111+
112+
return 0;
113+
}
114+
115+
116+
int uv_timer_stop(uv_timer_t* handle) {
117+
uv_loop_t* loop = handle->loop;
118+
119+
if (!uv__is_active(handle))
120+
return 0;
121+
122+
RB_REMOVE(uv_timer_tree_s, &loop->timers, handle);
123+
uv__handle_stop(handle);
124+
125+
return 0;
126+
}
127+
128+
129+
int uv_timer_again(uv_timer_t* handle) {
130+
/* If timer_cb is NULL that means that the timer was never started. */
131+
if (!handle->timer_cb) {
132+
return UV_EINVAL;
133+
}
134+
135+
if (handle->repeat) {
136+
uv_timer_stop(handle);
137+
uv_timer_start(handle, handle->timer_cb, handle->repeat, handle->repeat);
138+
}
139+
140+
return 0;
141+
}
142+
143+
144+
void uv_timer_set_repeat(uv_timer_t* handle, uint64_t repeat) {
145+
assert(handle->type == UV_TIMER);
146+
handle->repeat = repeat;
147+
}
148+
149+
150+
uint64_t uv_timer_get_repeat(const uv_timer_t* handle) {
151+
assert(handle->type == UV_TIMER);
152+
return handle->repeat;
153+
}
154+
155+
156+
uint64_t uv_timer_get_timeout(const uv_timer_t* handle) {
157+
assert(handle->type == UV_TIMER);
158+
return handle->due;
159+
}
160+
161+
162+
DWORD uv__next_timeout(const uv_loop_t* loop) {
163+
uv_timer_t* timer;
164+
int64_t delta;
165+
166+
/* Check if there are any running timers
167+
* Need to cast away const first, since RB_MIN doesn't know what we are
168+
* going to do with this return value, it can't be marked const
169+
*/
170+
timer = RB_MIN(uv_timer_tree_s, &((uv_loop_t*)loop)->timers);
171+
if (timer) {
172+
delta = timer->due - loop->time;
173+
if (delta >= UINT_MAX - 1) {
174+
/* A timeout value of UINT_MAX means infinite, so that's no good. */
175+
return UINT_MAX - 1;
176+
} else if (delta < 0) {
177+
/* Negative timeout values are not allowed */
178+
return 0;
179+
} else {
180+
return (DWORD)delta;
181+
}
182+
} else {
183+
/* No timers */
184+
return INFINITE;
185+
}
186+
}
187+
188+
189+
void uv_process_timers(uv_loop_t* loop) {
190+
uv_timer_t* timer;
191+
192+
/* Call timer callbacks */
193+
for (timer = RB_MIN(uv_timer_tree_s, &loop->timers);
194+
timer != NULL && timer->due <= loop->time;
195+
timer = RB_MIN(uv_timer_tree_s, &loop->timers)) {
196+
197+
uv_timer_stop(timer);
198+
uv_timer_again(timer);
199+
timer->timer_cb((uv_timer_t*) timer);
200+
}
201+
}

test/test-timer.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ TEST_IMPL(timer_init) {
161161

162162
ASSERT(0 == uv_timer_init(uv_default_loop(), &handle));
163163
ASSERT(0 == uv_timer_get_repeat(&handle));
164+
ASSERT(0 == uv_timer_get_timeout(&handle));
164165
ASSERT(0 == uv_is_active((uv_handle_t*) &handle));
165166

166167
MAKE_VALGRIND_HAPPY();
@@ -232,6 +233,9 @@ TEST_IMPL(timer_huge_timeout) {
232233
ASSERT(0 == uv_timer_start(&tiny_timer, tiny_timer_cb, 1, 0));
233234
ASSERT(0 == uv_timer_start(&huge_timer1, tiny_timer_cb, 0xffffffffffffLL, 0));
234235
ASSERT(0 == uv_timer_start(&huge_timer2, tiny_timer_cb, (uint64_t) -1, 0));
236+
ASSERT(1 == uv_timer_get_timeout(&tiny_timer));
237+
ASSERT(0xffffffffffffLL == uv_timer_get_timeout(&huge_timer1));
238+
ASSERT((uint64_t) -1 == uv_timer_get_timeout(&huge_timer2));
235239
ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT));
236240
MAKE_VALGRIND_HAPPY();
237241
return 0;

0 commit comments

Comments
 (0)