Если вы загляните в сам libuv, вы обнаружите, что оперативная часть запуска таймеров в событии l oop является функцией uv_run_timers()
.
void uv__run_timers(uv_loop_t* loop) {
struct heap_node* heap_node;
uv_timer_t* handle;
for (;;) {
heap_node = heap_min(timer_heap(loop));
if (heap_node == NULL)
break;
handle = container_of(heap_node, uv_timer_t, heap_node);
if (handle->timeout > loop->time)
break;
uv_timer_stop(handle);
uv_timer_again(handle);
handle->timer_cb(handle);
}
}
То, как оно работает, это событие l oop устанавливает отметку времени в текущем времени, а затем обрабатывает все таймеры, которые должны быть к этому времени по порядку, без обновления l oop время. Таким образом, это запустит все таймеры, которые уже истекли, но не запустит новые таймеры, которые должны быть выполнены, пока он обрабатывает те, которые уже должны были быть выполнены.
Это приводит к более справедливому планированию, так как он запускает все таймеры, которые должны, затем идет и запускает остальные типы событий в событии l oop, а затем возвращается, чтобы сделать больше таймеров, которые должны быть снова. Это НЕ будет обрабатывать любые таймеры, которые не должны быть запущены в начале цикла этого события l oop, но наступают во время обработки других таймеров. Таким образом, вы видите поведение, о котором вы спрашивали.
Вышеуказанная функция вызывается из основной части события l oop с этим кодом:
int uv_run(uv_loop_t *loop, uv_run_mode mode) {
DWORD timeout;
int r;
int ran_pending;
r = uv__loop_alive(loop);
if (!r)
uv_update_time(loop);
while (r != 0 && loop->stop_flag == 0) {
uv_update_time(loop); <== establish loop time
uv__run_timers(loop); <== process only timers due by that loop time
ran_pending = uv_process_reqs(loop);
uv_idle_invoke(loop);
uv_prepare_invoke(loop);
.... more code here
}
Запишите вызов uv_update_time(loop)
прямо перед вызовом uv__run_timers()
. Это устанавливает таймер, на который ссылается uv__run_timers()
. Вот код для uv_update_time()
:
void uv_update_time(uv_loop_t* loop) {
uint64_t new_time = uv__hrtime(1000);
assert(new_time >= loop->time);
loop->time = new_time;
}