2013-06-14 11 views
7

Podczas działania pętli zdarzeń w libuv użyciu funkcji uv_run, jest parametr „Tryb”, który stosuje się z następującymi wartościami:W jaki sposób tryb UV_RUN_NOWAIT działa w libuv?

UV_RUN_DEFAULT 
UV_RUN_ONCE 
UV_RUN_NOWAIT 

Pierwsze dwa są widoczne. UV_RUN_DEFAULT uruchamia pętlę zdarzeń, dopóki nie będzie już żadnych zdarzeń, i UV_RUN_ONCE przetwarzanie pojedynczego zdarzenia z pętli. Jednakże, UV_RUN_NOWAIT nie wydaje się być oddzielnym trybem, ale raczej flagą, która może być OR z jedną z dwóch pozostałych wartości.

Domyślnie ta funkcja blokuje do momentu zakończenia przetwarzania zdarzeń, a UV_RUN_NOWAIT uniemożliwia odblokowanie, ale na tym kończy się każda dokumentacja, którą można znaleźć. Moje pytanie brzmi: jeśli uruchomisz pętlę zdarzeń bez blokowania, w jaki sposób obsługiwane są wywołania zwrotne?

Model zdarzeń libuv jest jednowątkowy (wzorzec reaktora), więc zakładam, że musi on blokować, aby móc wywoływać wywołania zwrotne, ale jeśli główny wątek jest zajęty, co dzieje się ze zdarzeniem po jego przetworzeniu ? Czy wywołanie zwrotne będzie "ustawione w kolejce", dopóki libuv ponownie nie zapanuje nad głównym wątkiem? Czy wywołania zwrotne będą wysyłane w innym wątku?

Odpowiedz

9

Oddzwonienia są obsługiwane w ten sam sposób. Będą działać w wątku, który jest w uv_run().

za tym documentation:

  • UV_RUN_DEFAULT Uruchamia pętli do momentu, kiedy liczba odniesienia spada do zera. Zawsze zwraca zero.
  • UV_RUN_ONCE: Jednorazowa ankieta dla nowych wydarzeń. Zauważ, że ta funkcja blokuje, jeśli nie ma żadnych oczekujących zdarzeń. Zwraca zero po zakończeniu (brak aktywnych uchwytów lub żądań) lub niezerowe, jeśli oczekiwane jest więcej zdarzeń (co oznacza, że ​​powinieneś ponownie uruchomić pętlę zdarzeń w przyszłości).
  • UV_RUN_NOWAIT: Sonduj nowe zdarzenia raz, ale nie blokuj, jeśli nie ma oczekujących zdarzeń.

Weź pod uwagę przypadek, w którym program ma jednego obserwatora słuchającego gniazda. W tym scenariuszu zdarzenie zostanie utworzone, gdy gniazdo otrzyma dane.

  • UV_RUN_DEFAULT zablokuje dzwoniącego, nawet jeśli gniazdo nie ma danych. Rozmówca powróci z uv_run(), gdy:
    • Pętla została wyraźnie zatrzymany, poprzez uv_stop()
    • Nie więcej Obserwowane są wyświetlane w pętli. Na przykład jedyny obserwator został zatrzymany.
  • UV_RUN_ONCE zablokuje dzwoniącego, nawet jeśli gniazdo nie ma danych. Rozmówca powróci z uv_run(), gdy którykolwiek z poniższych warunków:
    • Pętla została wyraźnie zatrzymany, poprzez uv_stop()
    • Nie więcej Obserwowane są wyświetlane w pętli. Na przykład jedyny obserwator został zatrzymany.
    • Obsługuje maksymalnie jedno zdarzenie.Na przykład gniazdo odebrało dane, a wywołanie zwrotne użytkownika zostało wywołane. Dodatkowe zdarzenia mogą być gotowe do obsłużenia, ale nie będą obsługiwane w bieżącej rozmowie uv_run().
  • UV_RUN_NOWAIT zwróci, jeśli gniazdo nie ma danych.

Często uruchomione wydarzenie pętli w non-blocking sposób odbywa się zintegrować z innymi zdarzeniami pętli. Rozważmy aplikację, która ma dwie pętle zdarzeń: libuv dla pracy backendu i Qt UI (która jest sterowana przez własną pętlę zdarzeń). Możliwość uruchomienia pętli zdarzeń w sposób nieblokujący pozwala pojedynczemu wątkowi wywoływać zdarzenia w obu pętlach zdarzeń. Oto uproszczony przegląd pokazano dwa libuv pętle są obsługiwane przez jednego wątku:

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

Bez użycia UV_RUN_NOWAIT, loop2 byłoby tylko raz loop1 lub loop1 „s obserwatorów zostały zatrzymane.

Aby uzyskać więcej informacji, należy zapoznać się z sekcją Advanced Event Loops i Processes pod numerem An Introduction to libuv.

+1

Ta dokumentacja (ta w uv.h) jest stara, a czasami nieścisła. Nowa dokumentacja znajduje się na docs.libuv.org: http://docs.libuv.org/en/v1.x/loop.html#c.uv_run – saghul

Powiązane problemy