int uv_run(uv_loop_t *loop, uv_run_mode mode) { DWORD timeout; int r; int ran_pending; void (*poll)(uv_loop_t* loop, DWORD timeout); if (pGetQueuedCompletionStatusEx) poll = &uv_poll_ex; else poll = &uv_poll; r = uv__loop_alive(loop); if (!r) uv_update_time(loop); while (r != 0 && loop->stop_flag == 0) { uv_update_time(loop); uv_process_timers(loop); ran_pending = uv_process_reqs(loop); uv_idle_invoke(loop); uv_prepare_invoke(loop); timeout = 0; if ((mode == UV_RUN_ONCE && !ran_pending) || mode == UV_RUN_DEFAULT) timeout = uv_backend_timeout(loop); (*poll)(loop, timeout); uv_check_invoke(loop); uv_process_endgames(loop); if (mode == UV_RUN_ONCE) { /* UV_RUN_ONCE implies forward progress: 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_process_timers(loop); } r = uv__loop_alive(loop); if (mode == UV_RUN_ONCE || mode == 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; }
int uv_run_prework(uv_run_state* state) { BOOL block; uv_update_time(state->loop); uv_process_timers(state->loop); // Call idle callbacks if nothing to do. if (state->loop->pending_reqs_tail == NULL && state->loop->endgame_handles == NULL) { uv_idle_invoke(state->loop); } uv_process_reqs(state->loop); uv_process_endgames(state->loop); if (!UV_LOOP_ALIVE(state->loop)) return FALSE; uv_prepare_invoke(state->loop); block = (state->loop->idle_handles == NULL && state->loop->pending_reqs_tail == NULL && state->loop->endgame_handles == NULL && UV_LOOP_ALIVE(state->loop)); if (block) state->timeout = uv_get_poll_timeout(state->loop); else state->timeout = 0; state->count = 0; return TRUE; }
int uv_run(uv_loop_t *loop, uv_run_mode mode) { int r; void (*poll)(uv_loop_t* loop, int block); if (pGetQueuedCompletionStatusEx) poll = &uv_poll_ex; else poll = &uv_poll; if (!uv__loop_alive(loop)) return 0; r = uv__loop_alive(loop); while (r != 0 && loop->stop_flag == 0) { 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 && !loop->stop_flag && (loop->active_handles > 0 || !ngx_queue_empty(&loop->active_reqs)) && !(mode & UV_RUN_NOWAIT)); uv_check_invoke(loop); r = uv__loop_alive(loop); 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; }
int uv_run_jx(uv_loop_t* loop, uv_run_mode mode, void (*triggerSync)(const int), const int tid) { int r; void (*poll)(uv_loop_t * loop, int block); if (pGetQueuedCompletionStatusEx) poll = &uv_poll_ex; else poll = &uv_poll; if (tid != THREAD_ID_ALREADY_DEFINED) { if (tid != THREAD_ID_NOT_DEFINED) loop->loopId = tid; else loop->loopId = 63; } if (!uv__loop_alive(loop)) return 0; r = uv__loop_alive(loop); while (r != 0 && loop->stop_flag == 0) { 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); if (loop->loopId >= 0 && mode == UV_RUN_DEFAULT) { if (threadMessages[loop->loopId] != 0 && triggerSync != NULL) { triggerSync(loop->loopId); } } if (mode != UV_RUN_PAUSE) { (*poll)(loop, loop->idle_handles == NULL && threadMessages[loop->loopId] == 0 && loop->pending_reqs_tail == NULL && loop->endgame_handles == NULL && !loop->stop_flag && (loop->active_handles > loop->fakeHandle || !QUEUE_EMPTY(&loop->active_reqs)) && !(mode & UV_RUN_NOWAIT)); } uv_check_invoke(loop); r = uv__loop_alive(loop); if (mode & (UV_RUN_ONCE | UV_RUN_NOWAIT | UV_RUN_PAUSE)) break; } if (loop->loopId >= 0 && mode == UV_RUN_DEFAULT && triggerSync != NULL) { triggerSync(loop->loopId); } // if we force thread shutdown, there will be some remaining tasks etc. // It is highly possible they might leak, below impl. tries to workaround // this problem by looping the handles for 500 ms. at max. // TODO(obastemur) make it configurable per thread / timer sensitive if (loop->stop_flag != 0) { loop->stop_flag = 0; if (mode != UV_RUN_DEFAULT || r == 0) return r; int force_close = uv__loop_alive(loop); if (force_close) { uint64_t start_time = uv_hrtime(); int ret_val = 1; while (ret_val) { ret_val = uv_run_jx(loop, UV_RUN_NOWAIT, triggerSync, THREAD_ID_ALREADY_DEFINED); uint64_t end_time = uv_hrtime(); if(end_time - start_time > 500 * 1024 * 1024) { break; } } } } return r; }