2017-09-29 16 views
0

j'ai un système multi-tâches dans lequel un fil conducteur doit attendre dans l'état de blocage pour l'un des suivants 4 événements de se produire:Comment bloquer un seul thread pour 3 événements différents (sémaphore, condition de pthread et blocage du socket recv)?

  1. sémaphore inter-processus (sem_wait())
  2. condition de pthread (pthread_cond_wait())
  3. recv() de la douille
  4. délai d'attente expire

Idéalement, je voudrais un mécanisme pour débloquer le fil conducteur lorsque l'un des ci-dessus se produit, quelque chose comme un ppoll() avec un paramètre de timeout approprié. Non-bloquant et polling est hors de l'image en raison de l'impact sur l'utilisation du processeur, alors que le blocage de threads distincts sur différents événements n'est pas idéal en raison de la latence accrue (un déblocage de thread d'un des événements devrait éventuellement réveiller un).

Le code sera presque exclusivement compilé sous Linux avec la chaîne d'outils gcc, si cela peut aider, mais une certaine portabilité serait bonne, si possible.

Merci à l'avance pour toute suggestion

+0

Êtes-vous capable de modifier le code pour les threads d'arrière-plan? Autrement dit, pouvez-vous ajouter plus de code autour de l'endroit où les variables de sémaphore et de condition sont modifiées dans les threads d'arrière-plan? – bnaecker

+0

@bnaecker J'ai accès au code de synchronisation intra-thread (essentiellement, les threads qui notifient la variable conditionnelle pthread) mais pas le sémaphore inter-processus, car le processus que sem_post() sur ce sémaphore attend est 3ème partie et en dehors de mon contrôle. – Bob

Répondre

1

Les mécanismes d'attente sur plusieurs types d'objets sur les systèmes Unix ne sont pas exceptionnelles. En général, l'idée est, dans la mesure du possible, d'utiliser des descripteurs de fichiers pour IPC plutôt que de multiples mécanismes IPC différents. De votre commentaire, il semble que vous pouvez modifier ou modifier la variable de condition, mais pas le code qui signale le sémaphore. Donc, ce que je recommande est quelque chose comme ce qui suit.

Remplacez la variable de condition par un canal (pour plus de portabilité) ou un objet eventfd(2) (spécifique à Linux). Le thread notifiant écrit dans le tuyau chaque fois qu'il veut signaler le thread principal. Cela vous permettra de select(2) ou poll(2) ou quoi que ce soit dans le fil principal à la fois ce tuyau et le socket.

Parce que vous êtes coincé avec le sémaphores, je pense que la meilleure option serait de créer un autre thread, dont le seul but est d'attendre que le sémaphores en utilisant sem_wait(), puis écrire à un autre tuyau ou eventfd(2) objet lorsqu'il est informé par tout ce que fait le processus sem_post(). Dans le thread principal, ajoutez simplement cet autre descripteur de fichier à votre ensemble select(2). Donc, vous aurez trois descripteurs: un pour le socket, un pour la variable de condition, et un qui est écrit quand le sémaphore est incrémenté. Vous pouvez ensuite attendre les trois en utilisant votre méthode de multiplexage E/S préférée et inclure directement le délai d'attente que vous souhaitez.

+0

Merci. Le remplacement de la condition pthread par un tuyau est simple. Nous utilisons la condition pour signaler la fin d'un travail au thread principal, donc un tuyau peut facilement le faire. Cependant, je me demande, devrais-je m'attendre à une pénalité de performance (signifiant la latence) en passant de pthread cond_wait à bloquer recv sur un tuyau? – Bob

+0

Peu importe, trouvé cette analyse très approfondie ici: https://stackoverflow.com/questions/7979164/lowest-latency-notification-method-between-process-under-linux – Bob