Как цикл событий разблокирует себя от сетевого ввода-вывода? - PullRequest
0 голосов
/ 08 октября 2019

libuv имеет центральный цикл обработки событий и допускает асинхронный сетевой ввод-вывод, таймеры и т. Д. Вокруг него.

Architecutre высокого уровня, представленный в документах:

enter image description here

Когда цикл событий блокируется для «готовых» сокетов (используяepoll и т. д.), как разблокировать себя, если ни один из сокетов не готов? Это может пропустить некоторые таймеры, которые могут закончиться тем временем.

Если он немедленно разблокируется, если ни один из сокетов не пуст, и нет таймеров для запуска, разве цикл обработки событий не вырождается в "ожидание занятости" для сокетов, чтобы подготовиться?

1 Ответ

0 голосов
/ 22 октября 2019

uv_run гарантирует, что ожидание не занято, путем передачи дополнительного параметра времени ожидания в функцию опроса. В Windows реализация для расчета времени ожидания для вызова опроса в основном выглядит следующим образом:

int uv__next_timeout(const uv_loop_t* loop) {
  const struct heap_node* heap_node;
  const uv_timer_t* handle;
  uint64_t diff;

  /* If not timer block indefinitely */
  heap_node = heap_min(timer_heap(loop));
  if (heap_node == NULL)
    return -1;

  /* Timer should have fired already */
  handle = container_of(heap_node, uv_timer_t, heap_node);
  if (handle->timeout <= loop->time)
    return 0;

  /* Timer fires in the future, compute the timeout until the 
     next timer should fire */
  diff = handle->timeout - loop->time;
  if (diff > INT_MAX)
    diff = INT_MAX;

  return (int) diff;
}

Только если таймеры недоступны, цикл будет блокироваться до тех пор, пока порт завершения сокета / ввода-вывода не будет готов к использованию, иначебудет блокироваться не более времени до следующего тайм-аута. heap_min всегда возвращает следующий таймер, чтобы не пропустить ни одного.

...