Implement uv_timer for windows
This commit is contained in:
parent
a730165312
commit
c28fe6e170
114
uv-win.c
114
uv-win.c
@ -141,9 +141,9 @@ static LPFN_TRANSMITFILE pTransmitFile;
|
|||||||
|
|
||||||
|
|
||||||
/* Binary tree used to keep the list of timers sorted. */
|
/* Binary tree used to keep the list of timers sorted. */
|
||||||
static int uv_timer_compare(uv_req_t* t1, uv_req_t* t2);
|
static int uv_timer_compare(uv_handle_t* handle1, uv_handle_t* handle2);
|
||||||
RB_HEAD(uv_timer_s, uv_req_s);
|
RB_HEAD(uv_timer_s, uv_handle_s);
|
||||||
RB_PROTOTYPE_STATIC(uv_timer_s, uv_req_s, tree_entry, uv_timer_compare);
|
RB_PROTOTYPE_STATIC(uv_timer_s, uv_handle_s, tree_entry, uv_timer_compare);
|
||||||
|
|
||||||
/* The head of the timers tree */
|
/* The head of the timers tree */
|
||||||
static struct uv_timer_s uv_timers_ = RB_INITIALIZER(uv_timers_);
|
static struct uv_timer_s uv_timers_ = RB_INITIALIZER(uv_timers_);
|
||||||
@ -538,6 +538,20 @@ static void uv_tcp_endgame(uv_handle_t* handle) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void uv_timer_endgame(uv_handle_t* handle) {
|
||||||
|
if (handle->flags & UV_HANDLE_CLOSING) {
|
||||||
|
assert(!(handle->flags & UV_HANDLE_CLOSED));
|
||||||
|
handle->flags |= UV_HANDLE_CLOSED;
|
||||||
|
|
||||||
|
if (handle->close_cb) {
|
||||||
|
handle->close_cb(handle, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
uv_refs_--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void uv_loop_endgame(uv_handle_t* handle) {
|
static void uv_loop_endgame(uv_handle_t* handle) {
|
||||||
if (handle->flags & UV_HANDLE_CLOSING) {
|
if (handle->flags & UV_HANDLE_CLOSING) {
|
||||||
assert(!(handle->flags & UV_HANDLE_CLOSED));
|
assert(!(handle->flags & UV_HANDLE_CLOSED));
|
||||||
@ -581,6 +595,10 @@ static void uv_call_endgames() {
|
|||||||
uv_tcp_endgame(handle);
|
uv_tcp_endgame(handle);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case UV_TIMER:
|
||||||
|
uv_timer_endgame(handle);
|
||||||
|
break;
|
||||||
|
|
||||||
case UV_PREPARE:
|
case UV_PREPARE:
|
||||||
case UV_CHECK:
|
case UV_CHECK:
|
||||||
case UV_IDLE:
|
case UV_IDLE:
|
||||||
@ -626,6 +644,11 @@ static int uv_close_error(uv_handle_t* handle, uv_err_t e) {
|
|||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
case UV_TIMER:
|
||||||
|
uv_timer_stop(handle);
|
||||||
|
uv_want_endgame(handle);
|
||||||
|
return 0;
|
||||||
|
|
||||||
case UV_PREPARE:
|
case UV_PREPARE:
|
||||||
uv_prepare_stop(handle);
|
uv_prepare_stop(handle);
|
||||||
uv_want_endgame(handle);
|
uv_want_endgame(handle);
|
||||||
@ -1167,7 +1190,7 @@ static void uv_tcp_return_req(uv_handle_t* handle, uv_req_t* req) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int uv_timer_compare(uv_req_t* a, uv_req_t* b) {
|
static int uv_timer_compare(uv_handle_t* a, uv_handle_t* b) {
|
||||||
if (a->due < b->due)
|
if (a->due < b->due)
|
||||||
return -1;
|
return -1;
|
||||||
if (a->due > b->due)
|
if (a->due > b->due)
|
||||||
@ -1180,22 +1203,48 @@ static int uv_timer_compare(uv_req_t* a, uv_req_t* b) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
RB_GENERATE_STATIC(uv_timer_s, uv_req_s, tree_entry, uv_timer_compare);
|
RB_GENERATE_STATIC(uv_timer_s, uv_handle_s, tree_entry, uv_timer_compare);
|
||||||
|
|
||||||
|
|
||||||
int uv_timeout(uv_req_t* req, int64_t timeout) {
|
int uv_timer_init(uv_handle_t* handle, uv_close_cb close_cb, void* data) {
|
||||||
assert(!(req->flags & UV_REQ_PENDING));
|
handle->type = UV_TIMER;
|
||||||
|
handle->close_cb = (void*) close_cb;
|
||||||
req->type = UV_TIMEOUT;
|
handle->data = data;
|
||||||
|
handle->flags = 0;
|
||||||
req->due = uv_now_ + timeout;
|
handle->error = uv_ok_;
|
||||||
if (RB_INSERT(uv_timer_s, &uv_timers_, req) != NULL) {
|
|
||||||
uv_set_sys_error(ERROR_INVALID_DATA);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
uv_refs_++;
|
uv_refs_++;
|
||||||
req->flags |= UV_REQ_PENDING;
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int uv_timer_start(uv_handle_t* handle, uv_loop_cb timer_cb, int64_t timeout, int64_t repeat) {
|
||||||
|
if (handle->flags & UV_HANDLE_ACTIVE) {
|
||||||
|
RB_REMOVE(uv_timer_s, &uv_timers_, handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
handle->timer_cb = (void*) timer_cb;
|
||||||
|
handle->due = uv_now_ + timeout;
|
||||||
|
handle->repeat = repeat;
|
||||||
|
handle->flags |= UV_HANDLE_ACTIVE;
|
||||||
|
|
||||||
|
if (RB_INSERT(uv_timer_s, &uv_timers_, handle) != NULL) {
|
||||||
|
uv_fatal_error(ERROR_INVALID_DATA, "RB_INSERT");
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int uv_timer_stop(uv_handle_t* handle) {
|
||||||
|
if (!(handle->flags & UV_HANDLE_ACTIVE))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
RB_REMOVE(uv_timer_s, &uv_timers_, handle);
|
||||||
|
|
||||||
|
handle->flags &= ~UV_HANDLE_ACTIVE;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1439,9 +1488,9 @@ static void uv_poll() {
|
|||||||
uv_update_time();
|
uv_update_time();
|
||||||
|
|
||||||
/* Check if there are any running timers */
|
/* Check if there are any running timers */
|
||||||
req = RB_MIN(uv_timer_s, &uv_timers_);
|
handle = RB_MIN(uv_timer_s, &uv_timers_);
|
||||||
if (req) {
|
if (handle) {
|
||||||
delta = req->due - uv_now_;
|
delta = handle->due - uv_now_;
|
||||||
if (delta >= UINT_MAX) {
|
if (delta >= UINT_MAX) {
|
||||||
/* Can't have a timeout greater than UINT_MAX, and a timeout value of */
|
/* Can't have a timeout greater than UINT_MAX, and a timeout value of */
|
||||||
/* UINT_MAX means infinite, so that's no good either. */
|
/* UINT_MAX means infinite, so that's no good either. */
|
||||||
@ -1469,13 +1518,26 @@ static void uv_poll() {
|
|||||||
uv_loop_invoke(uv_check_handles_);
|
uv_loop_invoke(uv_check_handles_);
|
||||||
|
|
||||||
/* Call timer callbacks */
|
/* Call timer callbacks */
|
||||||
for (req = RB_MIN(uv_timer_s, &uv_timers_);
|
for (handle = RB_MIN(uv_timer_s, &uv_timers_);
|
||||||
req != NULL && req->due <= uv_now_;
|
handle != NULL && handle->due <= uv_now_;
|
||||||
req = RB_MIN(uv_timer_s, &uv_timers_)) {
|
handle = RB_MIN(uv_timer_s, &uv_timers_)) {
|
||||||
RB_REMOVE(uv_timer_s, &uv_timers_, req);
|
RB_REMOVE(uv_timer_s, &uv_timers_, handle);
|
||||||
req->flags &= ~UV_REQ_PENDING;
|
|
||||||
uv_refs_--;
|
if (handle->repeat != 0) {
|
||||||
((uv_timer_cb)req->cb)(req, req->due - uv_now_, 0);
|
/* If it is a repeating timer, reschedule with repeat timeout. */
|
||||||
|
handle->due += handle->repeat;
|
||||||
|
if (handle->due < uv_now_) {
|
||||||
|
handle->due = uv_now_;
|
||||||
|
}
|
||||||
|
if (RB_INSERT(uv_timer_s, &uv_timers_, handle) != NULL) {
|
||||||
|
uv_fatal_error(ERROR_INVALID_DATA, "RB_INSERT");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* If non-repeating, mark the timer as inactive. */
|
||||||
|
handle->flags &= ~UV_HANDLE_ACTIVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
((uv_loop_cb) handle->timer_cb)(handle, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Only if a iocp package was dequeued... */
|
/* Only if a iocp package was dequeued... */
|
||||||
|
|||||||
12
uv-win.h
12
uv-win.h
@ -48,11 +48,6 @@ typedef struct uv_buf_t {
|
|||||||
OVERLAPPED overlapped; \
|
OVERLAPPED overlapped; \
|
||||||
size_t queued_bytes; \
|
size_t queued_bytes; \
|
||||||
}; \
|
}; \
|
||||||
/* Used by timers */ \
|
|
||||||
struct { \
|
|
||||||
RB_ENTRY(uv_req_s) tree_entry; \
|
|
||||||
int64_t due; \
|
|
||||||
}; \
|
|
||||||
}; \
|
}; \
|
||||||
int flags;
|
int flags;
|
||||||
|
|
||||||
@ -79,6 +74,12 @@ typedef struct uv_buf_t {
|
|||||||
struct { uv_tcp_server_fields }; \
|
struct { uv_tcp_server_fields }; \
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define uv_timer_fields \
|
||||||
|
RB_ENTRY(uv_handle_s) tree_entry; \
|
||||||
|
int64_t due; \
|
||||||
|
int64_t repeat; \
|
||||||
|
void* timer_cb;
|
||||||
|
|
||||||
#define uv_loop_fields \
|
#define uv_loop_fields \
|
||||||
uv_handle_t* loop_prev; \
|
uv_handle_t* loop_prev; \
|
||||||
uv_handle_t* loop_next; \
|
uv_handle_t* loop_next; \
|
||||||
@ -95,6 +96,7 @@ typedef struct uv_buf_t {
|
|||||||
uv_err_t error; \
|
uv_err_t error; \
|
||||||
union { \
|
union { \
|
||||||
struct { uv_tcp_fields }; \
|
struct { uv_tcp_fields }; \
|
||||||
|
struct { uv_timer_fields }; \
|
||||||
struct { uv_loop_fields }; \
|
struct { uv_loop_fields }; \
|
||||||
struct { uv_async_fields }; \
|
struct { uv_async_fields }; \
|
||||||
};
|
};
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user