Implemented uv_run2
Allows for running the event loop in 3 modes:
* default: loop runs until the refcount drops to zero
* once: poll for events only once and block until one is handled
* nowait: poll for events only once but don't block if there are
no pending events
This commit is contained in:
parent
dc559a5ce6
commit
0820be7008
23
include/uv.h
23
include/uv.h
@ -221,6 +221,13 @@ typedef struct uv_cpu_info_s uv_cpu_info_t;
|
|||||||
typedef struct uv_interface_address_s uv_interface_address_t;
|
typedef struct uv_interface_address_s uv_interface_address_t;
|
||||||
|
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
UV_RUN_DEFAULT = 0,
|
||||||
|
UV_RUN_ONCE,
|
||||||
|
UV_RUN_NOWAIT
|
||||||
|
} uv_run_mode;
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This function must be called before any other functions in libuv.
|
* This function must be called before any other functions in libuv.
|
||||||
*
|
*
|
||||||
@ -244,12 +251,18 @@ UV_EXTERN uv_loop_t* uv_default_loop(void);
|
|||||||
UV_EXTERN int uv_run(uv_loop_t*);
|
UV_EXTERN int uv_run(uv_loop_t*);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Poll for new events once. Note that this function blocks if there are no
|
* This function runs the event loop. It will act differently depending on the
|
||||||
* pending events. Returns zero when done (no active handles or requests left),
|
* specified mode:
|
||||||
* or non-zero if more events are expected (meaning you should call
|
* - UV_RUN_DEFAULT: Runs the event loop until the reference count drops to
|
||||||
* uv_run_once() again sometime in the future).
|
* zero. Always returns zero.
|
||||||
|
* - UV_RUN_ONCE: Poll for new events once. Note that this function blocks if
|
||||||
|
* there are no pending events. Returns zero when done (no active handles
|
||||||
|
* or requests left), or non-zero if more events are expected (meaning you
|
||||||
|
* should run the event loop again sometime in the future).
|
||||||
|
* - UV_RUN_NOWAIT: Poll for new events once but don't block if there are no
|
||||||
|
* pending events.
|
||||||
*/
|
*/
|
||||||
UV_EXTERN int uv_run_once(uv_loop_t*);
|
UV_EXTERN int uv_run2(uv_loop_t*, uv_run_mode mode);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Manually modify the event loop's reference count. Useful if the user wants
|
* Manually modify the event loop's reference count. Useful if the user wants
|
||||||
|
|||||||
@ -267,27 +267,25 @@ int uv_backend_timeout(const uv_loop_t* loop) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int uv__run(uv_loop_t* loop) {
|
int uv_run2(uv_loop_t* loop, uv_run_mode mode) {
|
||||||
uv_update_time(loop);
|
int r;
|
||||||
uv__run_timers(loop);
|
do {
|
||||||
uv__run_idle(loop);
|
uv_update_time(loop);
|
||||||
uv__run_prepare(loop);
|
uv__run_timers(loop);
|
||||||
uv__run_pending(loop);
|
uv__run_idle(loop);
|
||||||
uv__io_poll(loop, uv_backend_timeout(loop));
|
uv__run_prepare(loop);
|
||||||
uv__run_check(loop);
|
uv__run_pending(loop);
|
||||||
uv__run_closing_handles(loop);
|
uv__io_poll(loop, (mode & UV_RUN_NOWAIT ? 0 : uv_backend_timeout(loop)));
|
||||||
return uv__has_active_handles(loop) || uv__has_active_reqs(loop);
|
uv__run_check(loop);
|
||||||
|
uv__run_closing_handles(loop);
|
||||||
|
r = uv__has_active_handles(loop) || uv__has_active_reqs(loop);
|
||||||
|
} while (r && !(mode & (UV_RUN_ONCE | UV_RUN_NOWAIT)));
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int uv_run(uv_loop_t* loop) {
|
int uv_run(uv_loop_t* loop) {
|
||||||
while (uv__run(loop));
|
return uv_run2(loop, UV_RUN_DEFAULT);
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int uv_run_once(uv_loop_t* loop) {
|
|
||||||
return uv__run(loop);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -252,57 +252,47 @@ static void uv_poll_ex(uv_loop_t* loop, int block) {
|
|||||||
!ngx_queue_empty(&(loop)->active_reqs) || \
|
!ngx_queue_empty(&(loop)->active_reqs) || \
|
||||||
(loop)->endgame_handles != NULL)
|
(loop)->endgame_handles != NULL)
|
||||||
|
|
||||||
#define UV_LOOP_ONCE(loop, poll) \
|
int uv_run2(uv_loop_t *loop, uv_run_mode mode) {
|
||||||
do { \
|
int r;
|
||||||
uv_update_time((loop)); \
|
void (*poll)(uv_loop_t* loop, int block);
|
||||||
uv_process_timers((loop)); \
|
|
||||||
\
|
|
||||||
/* Call idle callbacks if nothing to do. */ \
|
|
||||||
if ((loop)->pending_reqs_tail == NULL && \
|
|
||||||
(loop)->endgame_handles == NULL) { \
|
|
||||||
uv_idle_invoke((loop)); \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
uv_process_reqs((loop)); \
|
|
||||||
uv_process_endgames((loop)); \
|
|
||||||
\
|
|
||||||
if (!UV_LOOP_ALIVE((loop))) { \
|
|
||||||
break; \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
uv_prepare_invoke((loop)); \
|
|
||||||
\
|
|
||||||
poll((loop), (loop)->idle_handles == NULL && \
|
|
||||||
(loop)->pending_reqs_tail == NULL && \
|
|
||||||
(loop)->endgame_handles == NULL && \
|
|
||||||
UV_LOOP_ALIVE((loop))); \
|
|
||||||
\
|
|
||||||
uv_check_invoke((loop)); \
|
|
||||||
} while (0);
|
|
||||||
|
|
||||||
#define UV_LOOP(loop, poll) \
|
if (pGetQueuedCompletionStatusEx)
|
||||||
while (UV_LOOP_ALIVE((loop))) { \
|
poll = &uv_poll_ex;
|
||||||
UV_LOOP_ONCE(loop, poll) \
|
else
|
||||||
|
poll = &uv_poll;
|
||||||
|
|
||||||
|
r = UV_LOOP_ALIVE(loop);
|
||||||
|
while (r) {
|
||||||
|
uv_update_time(loop);
|
||||||
|
uv_process_timers(loop);
|
||||||
|
|
||||||
|
/* Call idle callbacks if nothing to do. */
|
||||||
|
if (loop->pending_reqs_tail == NULL &&
|
||||||
|
loop->endgame_handles == NULL) {
|
||||||
|
uv_idle_invoke(loop);
|
||||||
|
}
|
||||||
|
|
||||||
|
uv_process_reqs(loop);
|
||||||
|
uv_process_endgames(loop);
|
||||||
|
|
||||||
|
uv_prepare_invoke(loop);
|
||||||
|
|
||||||
|
(*poll)(loop, loop->idle_handles == NULL &&
|
||||||
|
loop->pending_reqs_tail == NULL &&
|
||||||
|
loop->endgame_handles == NULL &&
|
||||||
|
UV_LOOP_ALIVE(loop) &&
|
||||||
|
!(mode & UV_RUN_NOWAIT));
|
||||||
|
|
||||||
|
uv_check_invoke(loop);
|
||||||
|
r = UV_LOOP_ALIVE(loop);
|
||||||
|
|
||||||
|
if (mode & (UV_RUN_ONCE | UV_RUN_NOWAIT))
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
return r;
|
||||||
|
|
||||||
int uv_run_once(uv_loop_t* loop) {
|
|
||||||
if (pGetQueuedCompletionStatusEx) {
|
|
||||||
UV_LOOP_ONCE(loop, uv_poll_ex);
|
|
||||||
} else {
|
|
||||||
UV_LOOP_ONCE(loop, uv_poll);
|
|
||||||
}
|
|
||||||
return UV_LOOP_ALIVE(loop);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int uv_run(uv_loop_t* loop) {
|
int uv_run(uv_loop_t* loop) {
|
||||||
if (pGetQueuedCompletionStatusEx) {
|
return uv_run2(loop, UV_RUN_DEFAULT);
|
||||||
UV_LOOP(loop, uv_poll_ex);
|
|
||||||
} else {
|
|
||||||
UV_LOOP(loop, uv_poll);
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(!UV_LOOP_ALIVE((loop)));
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -84,7 +84,7 @@ static void embed_thread_runner(void* arg) {
|
|||||||
|
|
||||||
|
|
||||||
static void embed_cb(uv_async_t* async, int status) {
|
static void embed_cb(uv_async_t* async, int status) {
|
||||||
uv_run_once(uv_default_loop());
|
uv_run2(uv_default_loop(), UV_RUN_ONCE);
|
||||||
|
|
||||||
uv_sem_post(&embed_sem);
|
uv_sem_post(&embed_sem);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -22,6 +22,7 @@
|
|||||||
TEST_DECLARE (platform_output)
|
TEST_DECLARE (platform_output)
|
||||||
TEST_DECLARE (callback_order)
|
TEST_DECLARE (callback_order)
|
||||||
TEST_DECLARE (run_once)
|
TEST_DECLARE (run_once)
|
||||||
|
TEST_DECLARE (run_nowait)
|
||||||
TEST_DECLARE (barrier_1)
|
TEST_DECLARE (barrier_1)
|
||||||
TEST_DECLARE (barrier_2)
|
TEST_DECLARE (barrier_2)
|
||||||
TEST_DECLARE (barrier_3)
|
TEST_DECLARE (barrier_3)
|
||||||
@ -227,6 +228,7 @@ TASK_LIST_START
|
|||||||
TEST_ENTRY (callback_order)
|
TEST_ENTRY (callback_order)
|
||||||
#endif
|
#endif
|
||||||
TEST_ENTRY (run_once)
|
TEST_ENTRY (run_once)
|
||||||
|
TEST_ENTRY (run_nowait)
|
||||||
TEST_ENTRY (barrier_1)
|
TEST_ENTRY (barrier_1)
|
||||||
TEST_ENTRY (barrier_2)
|
TEST_ENTRY (barrier_2)
|
||||||
TEST_ENTRY (barrier_3)
|
TEST_ENTRY (barrier_3)
|
||||||
|
|||||||
46
test/test-run-nowait.c
Normal file
46
test/test-run-nowait.c
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to
|
||||||
|
* deal in the Software without restriction, including without limitation the
|
||||||
|
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||||
|
* sell copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||||
|
* IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "uv.h"
|
||||||
|
#include "task.h"
|
||||||
|
|
||||||
|
static uv_timer_t timer_handle;
|
||||||
|
static int timer_called = 0;
|
||||||
|
|
||||||
|
|
||||||
|
static void timer_cb(uv_timer_t* handle, int status) {
|
||||||
|
ASSERT(handle == &timer_handle);
|
||||||
|
ASSERT(status == 0);
|
||||||
|
timer_called = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST_IMPL(run_nowait) {
|
||||||
|
int r;
|
||||||
|
uv_timer_init(uv_default_loop(), &timer_handle);
|
||||||
|
uv_timer_start(&timer_handle, timer_cb, 100, 100);
|
||||||
|
|
||||||
|
r = uv_run2(uv_default_loop(), UV_RUN_NOWAIT);
|
||||||
|
ASSERT(r != 0);
|
||||||
|
ASSERT(timer_called == 0);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@ -41,7 +41,7 @@ TEST_IMPL(run_once) {
|
|||||||
uv_idle_init(uv_default_loop(), &idle_handle);
|
uv_idle_init(uv_default_loop(), &idle_handle);
|
||||||
uv_idle_start(&idle_handle, idle_cb);
|
uv_idle_start(&idle_handle, idle_cb);
|
||||||
|
|
||||||
while (uv_run_once(uv_default_loop()));
|
while (uv_run2(uv_default_loop(), UV_RUN_ONCE));
|
||||||
ASSERT(idle_counter == NUM_TICKS);
|
ASSERT(idle_counter == NUM_TICKS);
|
||||||
|
|
||||||
MAKE_VALGRIND_HAPPY();
|
MAKE_VALGRIND_HAPPY();
|
||||||
|
|||||||
1
uv.gyp
1
uv.gyp
@ -275,6 +275,7 @@
|
|||||||
'test/test-poll-close.c',
|
'test/test-poll-close.c',
|
||||||
'test/test-process-title.c',
|
'test/test-process-title.c',
|
||||||
'test/test-ref.c',
|
'test/test-ref.c',
|
||||||
|
'test/test-run-nowait.c',
|
||||||
'test/test-run-once.c',
|
'test/test-run-once.c',
|
||||||
'test/test-semaphore.c',
|
'test/test-semaphore.c',
|
||||||
'test/test-shutdown-close.c',
|
'test/test-shutdown-close.c',
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user