diff --git a/src/win/core.c b/src/win/core.c index ca566c03..497fa883 100644 --- a/src/win/core.c +++ b/src/win/core.c @@ -269,11 +269,8 @@ int uv_run(uv_loop_t *loop, uv_run_mode mode) { if (!uv__loop_alive(loop)) return 0; - do { - if (loop->stop_flag) { - loop->stop_flag = 0; - return uv__loop_alive(loop); - } + r = uv__loop_alive(loop); + while (r != 0 && loop->stop_flag == 0) { uv_update_time(loop); uv_process_timers(loop); @@ -298,7 +295,15 @@ int uv_run(uv_loop_t *loop, uv_run_mode mode) { uv_check_invoke(loop); r = uv__loop_alive(loop); - } while (r && !(mode & (UV_RUN_ONCE | UV_RUN_NOWAIT))); + if (mode & (UV_RUN_ONCE | UV_RUN_NOWAIT)) + break; + } + + /* The if statement lets the compiler compile it to a conditional store. + * Avoids dirtying a cache line. + */ + if (loop->stop_flag != 0) + loop->stop_flag = 0; return r; } diff --git a/test/test-loop-stop.c b/test/test-loop-stop.c index 75ff9153..db52a094 100644 --- a/test/test-loop-stop.c +++ b/test/test-loop-stop.c @@ -22,11 +22,22 @@ #include "uv.h" #include "task.h" +static uv_prepare_t prepare_handle; static uv_timer_t timer_handle; +static int prepare_called = 0; static int timer_called = 0; static int num_ticks = 10; +static void prepare_cb(uv_prepare_t* handle, int status) { + ASSERT(handle == &prepare_handle); + ASSERT(status == 0); + prepare_called++; + if (prepare_called == num_ticks) + uv_prepare_stop(handle); +} + + static void timer_cb(uv_timer_t* handle, int status) { ASSERT(handle == &timer_handle); ASSERT(status == 0); @@ -40,6 +51,8 @@ static void timer_cb(uv_timer_t* handle, int status) { TEST_IMPL(loop_stop) { int r; + uv_prepare_init(uv_default_loop(), &prepare_handle); + uv_prepare_start(&prepare_handle, prepare_cb); uv_timer_init(uv_default_loop(), &timer_handle); uv_timer_start(&timer_handle, timer_cb, 100, 100); @@ -47,9 +60,14 @@ TEST_IMPL(loop_stop) { ASSERT(r != 0); ASSERT(timer_called == 1); + r = uv_run(uv_default_loop(), UV_RUN_NOWAIT); + ASSERT(r != 0); + ASSERT(prepare_called == 3); + r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); ASSERT(r == 0); ASSERT(timer_called == 10); + ASSERT(prepare_called == 10); return 0; }