2013-06-14 6 views
7

Wenn eine Ereignisschleife in libuv Ausführen des uv_run Funktion verwenden, gibt es einen „Modus“ Parameter, der mit den folgenden Werten verwendet wird:Wie funktioniert der UV_RUN_NOWAIT Modus in libuv?

UV_RUN_DEFAULT 
UV_RUN_ONCE 
UV_RUN_NOWAIT 

Die ersten beiden sind offensichtlich. UV_RUN_DEFAULT führt die Ereignisschleife aus, bis keine weiteren Ereignisse mehr auftreten, und UV_RUN_ONCE verarbeitet ein einzelnes Ereignis aus der Schleife. UV_RUN_NOWAIT scheint jedoch kein separater Modus zu sein, sondern ein Flag, das mit einem der anderen beiden Werte verknüpft werden kann.

Standardmäßig blockiert diese Funktion, bis die Ereignisse verarbeitet werden, und UV_RUN_NOWAIT macht es nonblocking, aber jede Dokumentation, die ich dort finde, endet dort. Meine Frage ist, wie werden Callbacks behandelt, wenn Sie die Ereignisschleife nonblocking ausführen? Das Libuv-Ereignismodell ist ein single-threaded (reactor pattern), also würde ich annehmen, dass es blockieren muss, um die Callbacks aufrufen zu können, aber wenn der Hauptthread belegt ist, was passiert mit einem Event, nachdem es verarbeitet wurde ? Wird der Callback "in die Warteschlange gestellt", bis libuv wieder die Kontrolle über den Haupt-Thread hat? Oder werden die Rückrufe auf einem anderen Thread ausgelöst?

Antwort

9

Rückrufe werden auf die gleiche Weise behandelt. Sie werden innerhalb des Threads ausgeführt, der sich in uv_run() befindet.

Per den documentation:

  • UV_RUN_DEFAULT: Führt die Ereignisschleife, bis der Referenzzähler auf Null abfällt. Gibt immer Null zurück.
  • UV_RUN_ONCE: Poll für neue Ereignisse einmal. Beachten Sie, dass diese Funktion blockiert, wenn keine ausstehenden Ereignisse vorliegen. Gibt null zurück, wenn es fertig ist (keine aktiven Griffe oder Anfragen übrig), oder nicht Null, wenn mehr Ereignisse erwartet werden (was bedeutet, dass Sie die Ereignisschleife irgendwann in der Zukunft erneut ausführen sollten).
  • UV_RUN_NOWAIT: Einmalige Abfrage nach neuen Ereignissen, aber keine Blockierung, wenn keine ausstehenden Ereignisse vorliegen.

Betrachten wir den Fall, wo ein Programm einen einzigen Beobachter an eine Steckdose zu hören hat. In diesem Szenario wird ein Ereignis erstellt, wenn der Socket Daten empfangen hat.

  • UV_RUN_DEFAULT blockiert den Anrufer, auch wenn der Socket keine Daten enthält. Der Anrufer wird wieder von uv_run(), wenn entweder:
    • Die Schleife explizit gestoppt wurde, über uv_stop()
    • nicht mehr Beobachter in der Schleife ausgeführt werden. Zum Beispiel wurde der einzige Beobachter gestoppt.
    • UV_RUN_ONCE blockiert den Anrufer auch wenn der Socket keine Daten hat. Der Anrufer wird wieder von uv_run(), wenn eine der folgenden Voraussetzungen erfüllt sind:
      • Die Schleife gestoppt wurde explizit über uv_stop()
      • nicht mehr Beobachter in der Schleife ausgeführt werden. Zum Beispiel wurde der einzige Beobachter gestoppt.
      • Es hat ein Maximum von einem Ereignis behandelt.Der Socket empfängt beispielsweise Daten, und der Benutzer-Callback wurde aufgerufen. Weitere Ereignisse können zur Bearbeitung bereit sein, werden jedoch im aktuellen uv_run()-Aufruf nicht behandelt.
    • UV_RUN_NOWAIT wird zurückgegeben, wenn der Socket keine Daten enthält.

    Oft eine Ereignis-Schleife in einer nicht blockierenden Weise ausgeführt wird, erfolgt mit anderen Ereignis-Schleifen zu integrieren. Betrachten Sie eine Anwendung mit zwei Ereignisschleifen: libuv für die Back-End-Arbeit und Qt UI (die von einer eigenen Ereignisschleife gesteuert wird). Da die Ereignisschleife nicht blockierend ausgeführt werden kann, kann ein einzelner Thread Ereignisse in beiden Ereignisschleifen senden. Hier ist eine einfache Übersicht zwei zeigt libuv von einem einzigen Thread behandelt Schleifen werden:

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

    Ohne UV_RUN_NOWAIT zu verwenden, würde loop2 nur einmal ausführen loop1 oder loop1 ‚s-Beobachter wurden gestoppt.

    Weitere Informationen finden Sie in den Abschnitten Advanced Event Loops und Processes von An Introduction to libuv.

  • +1

    Diese Dokumentation (die in uv.h) ist alt und manchmal inakzeptabel. Die neue Dokumentation befindet sich unter docs.libuv.org: http://docs.libuv.org/en/v1.x/loop.html#cuv_run – saghul

    Verwandte Themen