Comment fonctionne le mode UV_RUN_NOWAIT dans libuv?

Lors de l’exécution d’une boucle d’événement dans libuv à l’aide de la fonction uv_run , un paramètre “mode” est utilisé avec les valeurs suivantes:

 UV_RUN_DEFAULT UV_RUN_ONCE UV_RUN_NOWAIT 

Les deux premiers sont évidents. UV_RUN_DEFAULT exécute la boucle d’événements jusqu’à ce qu’il n’y ait plus d’événements et UV_RUN_ONCE traite un seul événement de la boucle. Cependant, UV_RUN_NOWAIT ne semble pas être un mode séparé, mais plutôt un indicateur pouvant être associé à l’une des deux autres valeurs.

Par défaut, cette fonction bloque jusqu’au traitement des événements et UV_RUN_NOWAIT rend non bloquant, mais toute documentation que je peux trouver dessus se termine ici. Ma question est la suivante: si vous exécutez le non-blocage de la boucle d’événement, comment les rappels sont-ils gérés?

Le modèle d’événement libuv est mono-thread (pattern de réacteur), donc je suppose qu’il doit être bloqué pour pouvoir appeler les rappels, mais si le thread principal est occupé, qu’advient-il d’un événement après son traitement? Le rappel sera-t-il “mis en queue” jusqu’à ce que libuv reprenne le contrôle du thread principal? Ou les rappels seront-ils envoyés sur un autre thread?

Les rappels sont traités de la même manière. Ils fonctionneront dans le thread qui se trouve dans uv_run() .

Selon la documentation :

  • UV_RUN_DEFAULT : Exécute la boucle d’événements jusqu’à ce que le nombre de références tombe à zéro. Renvoie toujours zéro.
  • UV_RUN_ONCE : UV_RUN_ONCE une fois les nouveaux événements. Notez que cette fonction est bloquée s’il n’y a pas d’événements en attente. Renvoie zéro lorsque terminé (pas de descripteurs actifs ou de demandes restantes), ou différent de zéro si plusieurs événements sont attendus (ce qui signifie que vous devrez réexécuter la boucle d’événements ultérieurement).
  • UV_RUN_NOWAIT : UV_RUN_NOWAIT une fois les nouveaux événements, mais ne bloquez pas si aucun événement n’est en attente.

Prenons le cas où un programme a un seul observateur écoutant un socket. Dans ce scénario, un événement serait créé lorsque le socket a reçu des données.

  • UV_RUN_DEFAULT bloquera l’appelant même si le socket n’a pas de données. L’appelant reviendra de uv_run() lorsque:
    • La boucle a été explicitement arrêtée via uv_stop()
    • Plus aucun observateur ne court dans la boucle. Par exemple, le seul observateur a été arrêté.
  • UV_RUN_ONCE bloquera l’appelant même si le socket n’a pas de données. L’appelant reviendra de uv_run() lorsque l’un des uv_run() suivants se produit:
    • La boucle a été explicitement arrêtée via uv_stop()
    • Plus aucun observateur ne court dans la boucle. Par exemple, le seul observateur a été arrêté.
    • Il a géré un maximum d’un événement. Par exemple, le socket a reçu des données et le rappel de l’utilisateur a été appelé. D’autres événements peuvent être prêts à être traités, mais ne le seront pas dans l’ uv_run() cours de uv_run() .
  • UV_RUN_NOWAIT retournera si le socket n’a pas de données.

Souvent, l’exécution d’une boucle d’événements de manière non bloquante est effectuée pour s’intégrer à d’autres boucles d’événements. Prenons une application qui a deux boucles d’événements: libuv pour le travail d’arrière-plan et Qt UI (pilotée par sa propre boucle d’événements). La possibilité d’exécuter la boucle d’événements de manière non bloquante permet à un seul thread de dissortingbuer des événements sur les deux boucles d’événements. Voici un aperçu simpliste montrant deux boucles Libuv gérées par un seul thread:

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

Sans utiliser UV_RUN_NOWAIT , loop2 ne s’exécutera qu’une fois que les observateurs de loop1 ou loop1 auront été arrêtés.

Pour plus d’informations, reportez-vous aux sections relatives aux boucles d’événement avancées et aux processus de Introduction à libuv .