9
votes

En attente de deux entrées dans HASKELLL, simultanément

Le titre peut être un peu vague. C'est ce que je veux dire:

Disons que j'ai deux façons d'entrer à mon programme. Le premier est via le clavier, en utilisant la fonction getline qui bloque jusqu'à la lecture d'une ligne. L'autre est, disons, via un tchan , où utiliser readtchan chan entraînera également un bloc jusqu'à présent dans le canal, après quoi il sera lu. < / p>

Ce que je veux accomplir, c'est être capable d'attendre les valeurs , en utilisant un seul fil et ne permettant pas à mon CPU de sauter à 100%. Le moment où une des deux valeurs est disponible, il est extrait et le programme reprend. (Disons, en utilisant pour notifier lequel des deux valeurs a été reçue.)

est-ce possible?

Merci beaucoup!


3 commentaires

Que diriez-vous d'avoir une gaine d'appel io-thread et mettre son résultat dans le TCHAN aussi? Cela me semble comme ça devrait marcher ..


Pourquoi voulez-vous utiliser un seul fil? Et, par exemple, vous ne pouvez pas attendre 3 intrants? Ou 5? Ou 10? Pourquoi les restrictions arbitraires?


Je suppose que vous avez du code où plusieurs threads étaient utilisés et que vous aviez 100% de processeur? Vous voudrez peut-être publier le code afin que d'autres puissent voir pourquoi: la solution correcte est des threads et il peut simplement s'agir d'un problème de mise en œuvre.


3 Réponses :


12
votes

Je ne pense pas que "utiliser un seul fil" a du sens ici. Vous devez déjà utiliser plusieurs threads HASKELL de toute façon pour écrire sur tchan code>. Vous devez utiliser deux threads Haskell pour le faire et utiliser un mvar code> ou similaire pour communiquer le premier résultat pour arriver. Par exemple:

module Main where

import System.IO
import Control.Concurrent
import Control.Concurrent.MVar
import Control.Concurrent.STM
import Control.Concurrent.STM.TChan

main = do
   chan <- newTChanIO
   forkIO (threadTChanWrite chan)
   threadMultiplexedRead chan

threadTChanWrite chan = do
   threadDelay 5000000
   atomically $ writeTChan chan 3

threadMultiplexedRead chan = do
   mvar <- newEmptyMVar
   forkIO (threadKeyboardRead mvar)
   forkIO (threadTChanRead mvar chan)
   v <- readMVar mvar
   print v

threadKeyboardRead mvar = do
   str <- getLine
   putMVar mvar (Right str)

threadTChanRead mvar chan = do
   v <- atomically (readTChan chan)
   putMVar mvar (Left v)


0 commentaires

5
votes

J'ai deux façons d'entrer entrée à mon programme

Vous devez être capable d'utiliser 2 threads, une par source d'entrée, qui attendent sur leurs entrées respectives, écrivant le résultat à un canal partagé ou à un MVAR régi par un troisième thread.


3 commentaires

@Chals vous manquez le point. Il est plutôt inutile de ne pas utiliser plus d'un fil, et le gars ne parvient même pas à dire pourquoi.


Il n'a pas besoin de dire pourquoi, et je ne vois pas comment nous savons que le souhait est inutile.


Je suppose que l'OP est en attente de threads OS, pas de threads de haskell (continuations). Depuis que les threads de Haskell ne sont que deux continuations, c'est vraiment une meilleure solution ... En fait, toutes nos solutions utilisent plusieurs threads de haskell pour interlaisser IO, comme la réponse acceptée fait ...



3
votes

Il y a le race :: io a -> io b -> io (soit a b) fonction d'assistance dans le paquet "ASYNC" sur Hackage.

exécute simultanément deux actions de l'IO, alors on pourrait être votre getline et l'autre blocage sur un mvar ou autre. Renvoie un soit indiquant lequel l'on est retourné en premier (l'autre est annulée).

https: // Hackage.hakell.org/package/async-2.0.2/docs/control-concurrent-async.html#vher


1 commentaires

Imo c'est la bonne réponse. La réponse acceptée est trop compliquée et cette réponse effectue le dossier que la réponse acceptée est requise. Vous devez avoir une bonne raison d'utiliser forkio au lieu de async .