Skip to content
This repository has been archived by the owner on May 4, 2018. It is now read-only.

Commit

Permalink
unix, windows: run expired timers in UV_RUN_ONCE mode
Browse files Browse the repository at this point in the history
Before this commit, creating an event loop, starting a timer and
calling uv_run(UV_RUN_ONCE) blocked in uv_run() until the timer
expired - but didn't actually run the timer.
  • Loading branch information
bnoordhuis committed May 29, 2013
1 parent 081f701 commit c0a1206
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 1 deletion.
15 changes: 14 additions & 1 deletion src/unix/core.c
Expand Up @@ -317,8 +317,21 @@ int uv_run(uv_loop_t* loop, uv_run_mode mode) {
uv__io_poll(loop, timeout);
uv__run_check(loop);
uv__run_closing_handles(loop);
r = uv__loop_alive(loop);

if (mode == UV_RUN_ONCE) {
/* UV_RUN_ONCE implies forward progess: at least one callback must have
* been invoked when it returns. uv__io_poll() can return without doing
* I/O (meaning: no callbacks) when its timeout expires - which means we
* have pending timers that satisfy the forward progress constraint.
*
* UV_RUN_NOWAIT makes no guarantees about progress so it's omitted from
* the check.
*/
uv__update_time(loop);
uv__run_timers(loop);
}

r = uv__loop_alive(loop);
UV_TICK_STOP(loop, mode);

if (mode & (UV_RUN_ONCE | UV_RUN_NOWAIT))
Expand Down
14 changes: 14 additions & 0 deletions src/win/core.c
Expand Up @@ -291,6 +291,20 @@ int uv_run(uv_loop_t *loop, uv_run_mode mode) {
!(mode & UV_RUN_NOWAIT));

uv_check_invoke(loop);

if (mode == UV_RUN_ONCE) {
/* UV_RUN_ONCE implies forward progess: at least one callback must have
* been invoked when it returns. uv__io_poll() can return without doing
* I/O (meaning: no callbacks) when its timeout expires - which means we
* have pending timers that satisfy the forward progress constraint.
*
* UV_RUN_NOWAIT makes no guarantees about progress so it's omitted from
* the check.
*/
uv_update_time(loop);
uv_process_timers(loop);
}

r = uv__loop_alive(loop);
if (mode & (UV_RUN_ONCE | UV_RUN_NOWAIT))
break;
Expand Down
2 changes: 2 additions & 0 deletions test/test-list.h
Expand Up @@ -101,6 +101,7 @@ TEST_DECLARE (timer_start_twice)
TEST_DECLARE (timer_order)
TEST_DECLARE (timer_huge_timeout)
TEST_DECLARE (timer_huge_repeat)
TEST_DECLARE (timer_run_once)
TEST_DECLARE (idle_starvation)
TEST_DECLARE (loop_handles)
TEST_DECLARE (get_loadavg)
Expand Down Expand Up @@ -348,6 +349,7 @@ TASK_LIST_START
TEST_ENTRY (timer_order)
TEST_ENTRY (timer_huge_timeout)
TEST_ENTRY (timer_huge_repeat)
TEST_ENTRY (timer_run_once)

TEST_ENTRY (idle_starvation)

Expand Down
24 changes: 24 additions & 0 deletions test/test-timer.c
Expand Up @@ -264,3 +264,27 @@ TEST_IMPL(timer_huge_repeat) {
MAKE_VALGRIND_HAPPY();
return 0;
}


static unsigned int timer_run_once_timer_cb_called;


static void timer_run_once_timer_cb(uv_timer_t* handle, int status) {
timer_run_once_timer_cb_called++;
}


TEST_IMPL(timer_run_once) {
uv_timer_t timer_handle;

ASSERT(0 == uv_timer_init(uv_default_loop(), &timer_handle));
ASSERT(0 == uv_timer_start(&timer_handle, timer_run_once_timer_cb, 1, 0));
ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_ONCE));
ASSERT(1 == timer_run_once_timer_cb_called);

uv_close((uv_handle_t*) &timer_handle, NULL);
ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_ONCE));

MAKE_VALGRIND_HAPPY();
return 0;
}

0 comments on commit c0a1206

Please sign in to comment.