Question

J'ai deux MVars (enfin un MVar et un Chan).J'ai besoin de retirer des choses du Chan et de les traiter jusqu'à ce que l'autre MVar ne soit plus vide.Ma solution idéale serait quelque chose comme la fonction select UNIX où je passe dans une liste de MVars (vraisemblablement vides) et les blocs de thread jusqu'à ce que l'un d'eux soit plein, puis il renvoie le MVar complet.Essayez comme je pourrais, je ne peux penser à aucun moyen de faire cela au-delà d'interroger à plusieurs reprises chaque MVar avec isEmptyMVar jusqu'à ce que j'obtienne faux.Cela semble inefficace.

Une autre pensée était d'utiliser throwTo, mais cela interrompt tout ce qui se passe dans le thread et je dois terminer le traitement d'un travail sur le Chan de manière atomique.

Une dernière pensée pendant que je tape est de créer un nouveau forkIO pour chaque MVar qui essaie de lire son MVar puis de remplir un MVar nouvellement créé avec sa propre instance.Le thread d'origine peut alors bloquer sur ce MVar.Les threads Haskell sont-ils assez bon marché pour en exécuter autant?

Était-ce utile?

La solution

Les threads Haskell sont très bon marché, vous pouvez donc le résoudre de cette façon, mais il semble que STM conviendrait mieux à votre problème.Avec la STM, vous pouvez faire

do var <- atomically (takeTMVar a `orElse` takeTMVar b)
   ... do stuff with var

En raison du comportement de retry et orElse, ce code essaie d'obtenir a, puis si cela échoue, obtenez b.Si les deux échouent, il se bloque jusqu'à ce que l'un d'eux soit mis à jour et réessaye.

Vous pouvez même l'utiliser pour créer votre propre version rudimentaire de select:

select :: [TMVar a] -> STM a
select = foldr1 orElse . map takeTMVar

Autres conseils

Que diriez-vous d'utiliser les versions STM, TChan et TVar, avec le comportement retry et orElse?

La mise en œuvre de select est l'une des fonctionnalités intéressantes de STM. À partir de "Transactions de mémoire composables":

Au-delà de cela, nous proposons également orElse, ce qui leur permet d'être composés comme des alternatives, de sorte que la seconde est exécutée si les premières tentatives (Section 3.4). Cette capacité permet aux threads d'attendre plusieurs choses à la fois, comme le Appel système Unix select - sauf que orElse se compose bien, contrairement à select.


Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top