事件循环如何解除自身对网络I / O的阻止?

时间:2019-10-08 17:47:56

标签: events libuv

libuv具有中央事件循环,并允许围绕它的异步网络I / O,计时器等。

文档中介绍的高级架构师是:

enter image description here

当事件循环为“就绪”套接字阻塞时(使用epoll等),如果没有一个套接字就绪,它将如何解除阻塞呢?它可能会错过一些可能在此期间用完的计时器。

如果如果没有一个套接字为空,并且没有计时器可触发而立即解除阻塞,那么事件循环是否会退化为“忙于等待”套接字准备就绪?

1 个答案:

答案 0 :(得分:0)

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;
}

仅当没有可用的计时器时,循环才会阻塞,直到准备好使用套接字/ IO完成端口为止,否则循环将最多阻塞直到下一次超时触发。 heap_min确保始终返回下一个计时器,不会错过任何计时器。