Как работает режим UV_RUN_NOWAIT в libuv?

При запуске цикла событий в libuv с использованием функции uv_run есть параметр «режим», который используется со следующими значениями:

UV_RUN_DEFAULT
UV_RUN_ONCE
UV_RUN_NOWAIT

Первые два очевидны. UV_RUN_DEFAULT запускает цикл событий до тех пор, пока не закончатся события, и UV_RUN_ONCE обрабатывает одно событие из цикла. Тем не менее, UV_RUN_NOWAIT не является отдельным режимом, а скорее флагом, который можно объединить с одним из двух других значений.

По умолчанию эта функция блокируется до завершения обработки событий, а UV_RUN_NOWAIT делает ее неблокирующей, но любая документация, которую я могу найти по ней, на этом заканчивается. Мой вопрос: если вы запускаете неблокирующий цикл событий, как обрабатываются обратные вызовы?

Модель событий libuv является однопоточной (шаблон реактора), поэтому я предполагаю, что она должна быть заблокирована, чтобы иметь возможность вызывать обратные вызовы, но если основной поток занят, что происходит с событием после его обработки? Будет ли обратный вызов «поставлен в очередь» до тех пор, пока libuv снова не получит контроль над основным потоком? Или обратные вызовы будут отправлены в другой поток?


person Alexis King    schedule 14.06.2013    source источник


Ответы (1)


Обратные вызовы обрабатываются таким же образом. Они будут выполняться в потоке, который находится в uv_run().

Согласно документации:

  • UV_RUN_DEFAULT: Запускает цикл обработки событий до тех пор, пока счетчик ссылок не упадет до нуля. Всегда возвращает ноль.
  • UV_RUN_ONCE: Опросить новые события один раз. Обратите внимание, что эта функция блокируется, если нет ожидающих событий. Возвращает ноль, когда выполнено (не осталось активных дескрипторов или запросов), или ненулевое значение, если ожидается больше событий (это означает, что вы должны снова запустить цикл обработки событий когда-нибудь в будущем).
  • UV_RUN_NOWAIT: Запрашивать новые события один раз, но не блокировать, если нет ожидающих событий.

Рассмотрим случай, когда в программе есть один наблюдатель, прослушивающий сокет. В этом случае событие будет создано, когда сокет получит данные.

  • UV_RUN_DEFAULT will block the caller even if the socket does not have data. The caller will return from uv_run(), when either:
    • The loop has been explicitly stopped, via uv_stop()
    • В цикле больше нет наблюдателей. Например, единственный наблюдатель был остановлен.
  • UV_RUN_ONCE will block the caller even if the socket does not have data. The caller will return from uv_run(), when any of the following occur:
    • The loop has been explicitly stopped, via uv_stop()
    • В цикле больше нет наблюдателей. Например, единственный наблюдатель был остановлен.
    • Он обработал максимум одно событие. Например, сокет получил данные, и был вызван обратный вызов пользователя. Дополнительные события могут быть готовы к обработке, но не будут обрабатываться в текущем вызове uv_run().
  • UV_RUN_NOWAIT вернется, если в сокете нет данных.

Часто запуск цикла событий неблокирующим образом выполняется для интеграции с другими циклами событий. Рассмотрим приложение с двумя циклами обработки событий: libuv для серверной работы и пользовательским интерфейсом Qt (который управляется собственным циклом обработки событий). Возможность запуска цикла событий неблокирующим образом позволяет одному потоку отправлять события в оба цикла событий. Вот упрощенный обзор, показывающий, что два цикла libuv обрабатываются одним потоком:

uv_loop_t *loop1 = uv_loop_new();
uv_loop_t *loop2 = uv_loop_new();

// create, initialize, and start a watcher for each loop.
...

// Handle two event loops with a single thread.
while (uv_run(loop1, UV_RUN_NOWAIT) || uv_run(loop2, UV_RUN_NOWAIT));

Без использования UV_RUN_NOWAIT loop2 будет запускаться только после того, как loop1 или loop1 будут остановлены наблюдатели.

Для получения дополнительной информации прочитайте расширенные циклы обработки событий и Процессы раздела Введение в libuv.

person Tanner Sansbury    schedule 26.06.2013
comment
Эта документация (та, что в uv.h) устарела и иногда неточна. Новая документация находится на docs.libuv.org: docs.libuv .org/en/v1.x/loop.html#c.uv_run - person saghul; 03.03.2015