2011-05-04 10 views
14

Tengo dos MVars (bueno, un MVar y un Chan). Necesito sacar cosas del Chan y procesarlas hasta que el otro MVar ya no esté vacío. Mi solución ideal sería algo así como la función UNIX select donde paso una lista de MVars (presumiblemente vacíos) y los bloques de subprocesos hasta que uno de ellos esté lleno, luego devuelve el MVar completo. Por más que lo intente, no puedo pensar en ninguna forma de hacerlo más allá de interrogar repetidamente cada MVar con isEmptyMVar hasta que obtengo un resultado falso. Esto parece ineficiente.Una forma de formar un 'seleccionar' en MVars sin sondeo

Una idea diferente fue usar throwTo, pero interrumpe lo que está sucediendo en el hilo y tengo que completar el procesamiento de un Chan el atómico.

Una última idea, mientras escribo, es crear una nueva forkIO para cada MVar que intente leer su MVar y luego llenar una MVar recién creada con su propia instancia. El hilo original puede bloquearse en ese MVar. ¿Los hilos Haskell son lo suficientemente baratos como para que funcionen tantos?

+0

Ni siquiera lo pensaría dos veces antes de tener 1k hilos de ejecución. 10k Podría empezar a pensar en medir los gastos generales. 100k, definitivamente. –

Respuesta

16

Los hilos de Haskell son muy baratos, por lo que podría resolverlo de esa manera, pero parece que STM sería una mejor opción para su problema. Con STM se puede hacer

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

Debido al comportamiento de retry y orElse, el código intenta a, entonces si eso no funciona, entra b. Si ambos fallan, se bloquea hasta que cualquiera de ellos se actualice e intente de nuevo.

Incluso se puede usar esto para hacer su propia versión rudimentaria de select:

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

¿Cómo sobre el uso de versiones MCI, TChan y TVar, con el comportamiento y retryorElse?

La selección de implementación es una de las capacidades agradables de STM. De "Transacciones de memoria Composable":

Más allá de esto, también proporcionamos OrElse, lo que les permite estar compuestos como alternativas, por lo que el segundo se ejecuta si los primeros reintentos (Sección 3.4). Esta capacidad permite que los hilos esperen muchas cosas a la vez, como la llamada al sistema de selección Unix - excepto que orElEl se compone bien, mientras que la selección no.


Cuestiones relacionadas