Подтвердить что ты не робот

Является ли libuv потоком безопасным?

Я создал новый поток, посвященный циклу запуска libuv. Функция потока выглядит примерно так:

void thread_function()
{
  uv_loop_t *loop = uv_loop_new();
  uv_ref( loop );
  uv_run( loop );
}

Приращение счетчика ref сохраняет поток в реальном времени и в состоянии обрабатывать события libuv. Я надеюсь, что вы сможете завершить цикл выполнения, заставив поток выйти из него, выполнив uv_unref в основном потоке.

Однако при проверке исходного кода uv_ref я не видел никакой гарантии, что доступ к переменной контрольного счетчика будет синхронизирован при одновременном доступе. Кроме того, я не видел никаких вызовов доходности, чтобы отказаться от управления операционной системой во время цикла цикла, то есть программа не будет хорошо взаимодействовать с другими процессами.

Это заставляет меня поверить, что я не правильно использую libuv. Если кто-то может объяснить, что я делаю неправильно, это было бы здорово!

4b9b3361

Ответ 1

Нет, libuv не является потокобезопасным таким образом. Вы должны использовать uv_async, чтобы сигнализировать о выходе цикла. uv_async - единственное средство, защищенное потоками, которое имеет libuv.

Он будет выглядеть примерно так:

uv_async_t exit_handle;

void exit_async_cb(uv_async_t* handle, int status) {
  /* After closing the async handle, it will no longer keep the loop alive. */
  uv_close((uv_handle_t*) &exit_handle, NULL);
}

void thread_function() {
  uv_loop_t *loop = uv_loop_new();
  /* The existence of the async handle will keep the loop alive. */
  uv_async_init(loop, &exit_handle, exit_async_cb);
  uv_run(loop);
}

Теперь из другого потока вы можете вывести этот цикл для выхода, вызывая

uv_async_send(&exit_handle);

Вам нужно позаботиться о том, чтобы не вызывать uv_async_send(), пока другой поток не завершил настройку цикла и ручку uv_async. Последняя версия libuv включает примитивы синхронизации uv_barrier, которые вы могли бы использовать; но версия libuv, которая поставляется с Node.js 0.8, пока не поддерживает это, поэтому вам, вероятно, понадобится использовать средства pthread для выполнения этой работы.

На боковой ноте вы, кажется, вызываете uv_ref и uv_unref с ссылкой на цикл в качестве аргумента. В последних версиях libuv это изменилось, теперь вы должны использовать uv_ref и uv_unref определенный дескриптор. Подробнее см. uv.h.