Attendre sur de multiples variables de condition sur Linux sans inutiles dort-il?
Je suis en train d'écrire une latence sensible application qui, en effet, veut attendre sur de multiples variables de condition à la fois. Je l'ai lu avant de plusieurs moyens pour obtenir cette fonctionnalité sur Linux (apparemment c'est builtin sur Windows), mais aucune d'entre elles semblent convenir pour mon application. Les méthodes que je connais sont:
-
Ont un thread attente sur chacune des variables de condition, vous voulez attendre, qui, lorsqu'il sera réveillé signal d'une seule variable d'état qui vous attendent sur place.
-
Vélo à travers de multiples variables de condition, avec un temps d'attente.
-
Écrit mannequin octets de fichiers ou des tubes à la place, et l'interrogation sur ceux-ci.
#1 & #2 sont inadaptées, car elles entraînent inutile de couchage. Avec le n ° 1, vous avez à attendre pour le mannequin thread à se réveiller, alors le signal de véritable fil conducteur, puis pour le véritable fil conducteur de se réveiller, au lieu de la véritable fil conducteur juste de me réveiller pour commencer, l'extra planificateur de quantum passé sur ce qui importe réellement pour mon application, et je préfèrerais ne pas avoir à l'utiliser à part entière un RTOS. #2 est encore pire, vous passent potentiellement N * délai d'attente temps à dormir, ou votre délai d'attente sera 0 dans ce cas, vous ne dormez jamais (à l'infini la gravure du PROCESSEUR et de la faim d'autres threads est aussi mauvais).
Pour le #3, les tuyaux sont problématiques parce que si le thread " a " est occupé ou même se bloque (je suis en affaire avec processus distinct plutôt que de threads -- les mutex et les conditions devraient être stockées dans la mémoire partagée), alors le thread d'écriture sera coincé à cause de la canalisation de la mémoire tampon est pleine, comme tous les autres clients. Les fichiers sont problématiques parce que vous seriez la croissance sans cesse plus l'application a couru.
Est-il une meilleure façon de le faire? Curieux pour des réponses appropriées pour Solaris ainsi.
- Je rencontre cette limitation dans le C++0x primitives de thread qui semblent être fortement basé sur un pthreads moins-petit dénominateur commun.
- Ne pouvez-vous pas utiliser un seul sémaphore à la place? Une fois que le thread en attente obtient une unité, il peut interroger les différentes sources pour en trouver un qui a des "la flamme", (peut-être un tableau de la volatilité des booléens?).
Vous devez vous connecter pour publier un commentaire.
Si vous parlez des threads POSIX je vous recommande d'utiliser une seule variable d'état et le nombre de cas de drapeaux ou quelque chose de semblable. L'idée est d'utiliser le peer condvar mutex pour la garde des notifications d'événements. Toute façon, vous devez vérifier pour les événements d'après cond_wait() de sortie. Voici mon ancien assez de code pour illustrer ce de ma formation (oui, j'ai vérifié qu'il fonctionne, mais s'il vous plaît noter qu'il a été préparé il y a quelques temps et pressé pour les nouveaux arrivants).
pthread_mutex_lock(&mtx);
après le traitement, les événements reçus?Votre #3 option (écrit mannequin octets de fichiers ou des tubes à la place, et l'interrogation sur celles-ci) a une meilleure alternative sur Linux:
eventfd
.Au lieu d'une taille limitée de la mémoire tampon (comme dans un tuyau) ou une infinité de croissance tampon (comme dans un fichier), avec
eventfd
vous avez un noyau 64 bits non signé comptoir. Un octet de 8write
ajoute un numéro au compteur; un octet de 8read
soit efface le compteur et retourne sa valeur précédente (sansEFD_SEMAPHORE
), ou décrémente le compteur de 1 et renvoie 1 (avecEFD_SEMAPHORE
). Le descripteur de fichier est considéré comme lisible pour les bureaux de fonctions (select
,poll
,epoll
) lorsque le compteur est différent de zéro.Même si le compteur est à proximité de la 64 bits de la limite, de la
write
va échouer avecEAGAIN
si vous avez fait le descripteur de fichier non bloquant. La même chose arrive avecread
lorsque le compteur est à zéro.Si vous voulez un maximum de flexibilité en vertu de la POSIX variable d'état du modèle de synchronisation, vous devez éviter d'écrire des modules qui communiquent les événements à leurs utilisateurs que par le biais de l'exposition d'une variable de condition. (Vous avez alors essentiellement réinventé un sémaphore.)
Active les modules doivent être conçus de telle sorte que leurs interfaces fournissent des notifications de rappel d'événements, via enregistrés fonctions: et, si nécessaire, de telle sorte que plusieurs rappels peuvent être enregistrés.
Un client de plusieurs modules enregistre un rappel avec chacun d'eux. Toutes ces valeurs peuvent être acheminés dans un endroit commun où ils verrouillage de la même mutex, changement de l'état, déverrouiller, et frappé de la même variable de condition.
Cette conception offre également la possibilité que, si la quantité de travail effectué en réponse à un événement est raisonnablement petit, peut-être qu'il peut seulement être fait dans le contexte de la fonction de rappel.
Rappels ont aussi quelques avantages dans le débogage. Vous pouvez mettre un point d'arrêt sur un événement qui arrive sous la forme d'un rappel, et de voir la pile d'appels de la façon dont il a été généré. Si vous mettez un point d'arrêt sur un événement qui arrive comme un sémaphore de réveil, ou par l'intermédiaire de la transmission de message mécanisme, la trace d'appel de ne pas révéler l'origine de l'événement.
Cela étant dit, vous pouvez faire votre propre primitives de synchronisation avec les mutex et les variables de condition, de soutien en attente sur plusieurs objets. Ces primitives de synchronisation peut être en interne basé sur les rappels, d'une manière qui est invisible pour le reste de l'application.
L'essentiel, c'est que, pour chaque objet, qu'un thread souhaite attendre, l'attente fonctionnement des files d'attente d'une interface de rappel avec cet objet. Lorsqu'un objet est signalé, il appelle tous ses rappels enregistrés. L'réveillé fils résorption de toutes les interfaces de rappel, et coup d'oeil à certains indicateurs d'état dans chacun de voir quels sont les objets signalés.
Pour l'attente, sur de multiples variables de condition, il y a une application pour Solaris que vous pourriez port de Linux si vous êtes intéressé: WaitFor API