Disclaimer: cela peut facilement être effectué à l'aide d'un Je veux faire ce qui suit atomique: p>
Lire certaines variables. P> Li>
Décidez quel E / S à effectuer, en fonction de ce que je viens de lire. p> li>
Effectuez les E / S. P> LI>
enregistrer les résultats dans les variables. P> li>
ul>
Pour la concrétion, supposons que je souhaite garder une trace du nombre d'octets d'entrée que j'ai lus, et de prétendre que j'ai atteint EOF après qu'un certain nombre d'octets aient été consommés. (OK, laissez deux threads lire dans le même fichier simultanément est probablement une chose faux à faire en premier lieu, mais aller avec moi sur cette ...) p>
Clairement, cela ne peut pas être une seule transaction STM; Il y a des E / S au milieu. Clairement, il serait également faux de l'avoir comme deux transactions non connectées. (Deux threads pouvaient voir qu'il reste un octet de quota, et les deux décident de lire cet octet.) P>
Y a-t-il une belle solution à ce problème? Ou est-ce que STM est simplement le mauvais outil pour cette tâche? P> mvar () code> comme un simple mutex. Je suis juste des curiosités pour voir si cela peut être fait avec STM. P>
3 Réponses :
Je dirais que STM ne peut pas le faire, et c'est exprès. Un morceau de code STM peut être redémarré plusieurs fois à différents endroits si une transaction roule vers le dos. Que se passerait-il si vous exécutez votre transaction, il effectue l'action d'E / S, puis roule ensuite lors de l'enregistrement des résultats dans les variables? P>
Pour cette raison, les calculs STM doivent être purs, uniquement avec l'ajout de primitives STM telles que les variables et les tableaux MTM mutables. P>
Certes, il n'aurait pas de sens d'exécuter des E / S à l'intérieur d'une transaction; Vous ne pouvez pas annuler les E / S. Mais les transactions peuvent-elles être utilisées pour obtenir une exclusion mutuelle? Et est-ce raisonnable de le faire?
@Mathematicalorchid autant que je sache, l'exclusion mutuelle ne peut pas être faite dans STM. Il n'y a pas de garantie qu'un cadre STM attend quoi que ce soit - il peut aussi bien répéter une transaction échouée sur une boucle jusqu'à ce qu'elle réussisse. De The Docs < / a>: La mise en œuvre peut bloquer le fil jusqu'à ce que l'un des téléviseurs a été mis à jour a été mis à jour. i> La meilleure solution est probablement dans la réponse donnée par Comonad i> - Si je comprends bien, il exécute io code> actions sur un commit réussi.
@Mathematicalorchid juste une pensée, est-il même possible d'atteindre une exclusivité mutuelle et une composition sans risquer une impasse?
C'est s'il n'y a qu'une seule ressource verrouillée. Mais dans le cas général ... Non, il est peu probable que cela fonctionne.
@Mathematicalorchid hmm, semble en fait comme s'il y avait une solution monadique là-bas - créer une monade qui, avant d'exécuter, tente de saisir tous les mutiles des fonctions qui le composent à partir d'un bloc STM. De cette façon, vous obtenez une granularité fine-u-voulez-vous-voulez, mais prévenir l'impasse, tout libre simplement en mettant votre code dans un bloc code> code>. Semble raisonnable, mais il y a certainement une faille dans ma logique ou que quelqu'un aurait déjà fait cela.
@DAXFOHL Je dirais que vous ne serez pas en mesure d'énumérer les mutiles tant que vous n'avez pas exécuté la monade, car ils pourraient dépendre des valeurs (résultats) pendant le calcul. Mais il semble que ce soit réalisable avec un applicatif code> lorsque les effets sont fixes et ne dépendent pas des valeurs.
Utilisez un ceci garantit que ces actions ne voient qu'une vue constante des variables étant modifié et ne sera pas exécuté pendant que l'action IO est en cours. p> p> TVAR BOOL code> nommé
cohérent code> pour garder une trace de si votre action IO est en cours. Avant d'exécuter l'action IO, vous avez défini cohérent à
false code> et après avoir exécuté l'action IO, vous définissez
cohérent code> sur
true code>. Ensuite, toute action qui dépend des valeurs de ces variables STM que vous modifiez vient de mettre cette clause au début:
Cela a une saveur. Actuellement, le problème que je frappe est qu'une action mutex ne peut pas exécuter d'autres actions mutex, car le mutex est déjà pris. Je ne sais pas si l'approche ci-dessus résoudra ce problème ...
Pouvez-vous clarifier le problème du mutex?
Si vous utilisez mvar () code> comme mutex et commencez chaque fonction avec
takemvar code>, une seule fonction ne peut pas en appeler une autre car le mutex est déjà pris. Les fonctions deviennent non composacieuses.
@Mathematicalorchid Vous pouvez utiliser l'option TVAR entier code>, et ne procédez que si c'est
Aucun code> ou
Quelques [COURROSTHADID] CODE>
@GABRIELGONZALEZ J'essaie d'écrire un module de telle sorte que les clients ne soient pas obligés de se soucier de la sécurité thread-sécurité. Chaque fonction exportée prend le mutex, fait des choses, le libère. Mais parfois, une fonction exportée voudrait appeler une autre fonction exportée pour faire une partie de son travail ... qui entraîne une impasse instantanée. Ce n'est pas difficile de travailler, juste légèrement irritant.
@Mathematicalorchid en fait, vous devriez utiliser quelque chose comme TVAR (entier, compte) code>; Avec
TVAR Option integer code> Votre fonction la plus intérieure relâcherait avant que votre plus externe soit terminée. Mais tout ce qui dit, je pensais que c'est essentiellement ce que
mvar code> a fait.
@Mathematicalorchid C'est le problème général avec la programmation basée sur le verrou, qui est fondamentalement ce que cela revient. Je pense que vous étiez probablement plus sur la bonne voie lorsque vous avez parlé de l'envoi de toutes les actions io code> à une sorte de canal dans le style acteur. On dirait que cela pourrait mieux résoudre votre problème mieux.
Je pense que vous recherchez le package STM-IO-Hags . p>
Tout ce que vous voulez réellement faire - serait-il possible d'exprimer cela en termes de sémantique d'abandon / réessayer de STM? En d'autres termes: pouvez-vous faire une annuelle et répéter l'action de l'IO? Sinon, alors je me référerais à la réponse de Gabriel Gonzalez. P>
Eh bien, toutes les opérations d'E / S sont lire des opérations i>, donc la seule chose qu'ils modifient est l'état d'une poignée. Si vous pouviez garantir que pas deux opérations d'E / S ne se produisent en même temps, et tout le monde cherche toujours au bon endroit en premier ... il pourrait i> peut-être travailler ... mais je pense que garder I / O des transactions fonctionnerait mieux.
@Mathematicalorchid: Dans ce cas, j'utiliserais simplement différentes poignées. Si ce n'est pas une option, vous devez utiliser un mécanisme de verrouillage (la réponse de MVAR ou GABRIEL) pour chercher + lire.
@Mathematicalorchid: Je ne suis pas sûr de ce dont vous avez besoin de STM pour, mais peut-être que vous n'exprimez que de la concurrence. Vous n'avez pas besoin de mautexs comme dans les langues inférieures: dans HASKELLL, vous appliquez le mécanisme de verrouillage directement sur la ressource, comme MPAR code> au lieu de
(MVAR (), la poignée) code>. STM est une manière complètement différente de résoudre des problèmes de concurrence, il utilise des "transactions" pouvant être abandonnées / restaurées / répétées comme une transaction de monnaie entre les comptes bancaires. Je ne vois aucune utilisation dans cela pour la lecture de fichiers immuables.
Je comprends ça. J'utilise un mutex pour ne pas protéger la poignée, mais pour protéger les autres choses que je mette à jour chaque fois que la poignée est utilisée. Mais comme je le dis, cela finit par être plutôt non composable. Je peux le réparer, mais je me demandais simplement si STM offre une meilleure façon. Je soupçonnais pas, mais je voulais vérifier.
Cela vous donne-t-il ce que vous auriez besoin? Le "Barber" pourrait être votre pointeur de lecture. Stackoverflow.com/questions/16933678 / ...
@Daxfohl Eh bien, vous pourrait I> utiliser STM pour envoyer toutes les demandes d'E / S à un seul thread via un
Tchan code> ... qui devrait fonctionner.
Il semble que vous ayez un cas d'utilisation standard pour la solution de modèle de base de l'acteur de style Erlang, qui est ce que la coiffure est implémente via
STM code> et
tchan code>.