
I'd like a function that blocks until data is available on one of two channels and then returns that data wrapped in an Either. Here is my naive implementation: readEitherChan::Chan a -> Chan b -> Either a b readEitherChan a b = do var <- newEmptyMVar forkIO (readChan a >>= putMVar var . Left) forkIO (readChan b >>= putMVar var . Right) val <- readMVar return val eitherChan a b left right = readEitherChan a b >>= either left right But creating an MVar and starting two threads feels like a lot of overhead for a simple operation. Is there a better way or is forkIO so efficient that I shouldn't care? -Alex- _________________________________________________________________ S. Alexander Jacobson mailto:me@alexjacobson.com tel:917-770-6565 http://alexjacobson.com

On Tue, Jun 15, 2004 at 06:29:59PM -0400, S. Alexander Jacobson wrote:
I'd like a function that blocks until data is available on one of two channels and then returns that data wrapped in an Either. Here is my naive implementation:
readEitherChan::Chan a -> Chan b -> Either a b readEitherChan a b = do var <- newEmptyMVar forkIO (readChan a >>= putMVar var . Left) forkIO (readChan b >>= putMVar var . Right) val <- readMVar return val
eitherChan a b left right = readEitherChan a b >>= either left right
But creating an MVar and starting two threads feels like a lot of overhead for a simple operation.
You can also loose some elements from both channels. I think it would be safer to create once new Chan (Either a b), and then read from it. createEitherChan :: Chan a -> Chan b -> IO (Chan (Either a b)) createEitherChan a b = do ab <- newChan forkIO (sequence_ (repeat (readChan a >>= writeChan ab . Left))) forkIO (sequence_ (repeat (readChan b >>= writeChan ab . Right))) return ab Best regards, Tom -- .signature: Too many levels of symbolic links

Tomasz Zielonka wrote:
On Tue, Jun 15, 2004 at 06:29:59PM -0400, S. Alexander Jacobson wrote:
readEitherChan::Chan a -> Chan b -> Either a b
eitherChan a b left right = readEitherChan a b >>= either left right
... I think it would be safer to create once new Chan (Either a b), and then read from it.
createEitherChan :: Chan a -> Chan b -> IO (Chan (Either a b))
Although createEitherChan might be the best solution for some application, it would be interesting to know what the recommended way to implement the function eitherChan above is, if that is what you really need? The eitherChan function corresponds to guarded nondeterministic choice, usually written (a?P)+(b?Q) process calculi, i.e., a rather fundamental concurrency operator. Section 5 of [1] enumerates some reasons why guarded nondeterministic choice is not available as a primitive in Concurrent Haskell. Section 5.2 describes a function select for nondeterministic choice, but I don't see how to use that to implement readEitherChan (or takeEitherMVar)... I got interested in this the other day when I was contemplating reviving Gadget Gofer [2], by porting it to Concurrent Haskell. Gadget Gofer has a non-deterministic choice operator, though, so the port would probably require more work than I expected... -- Thomas H [1] Concurrent Haskell http://www.haskell.org/ghc/docs/papers/concurrent-haskell.ps.gz [2] Lazy Functional Components for Graphical User Interfaces, Rob Noble, PhD thesis, York, 1996
participants (3)
-
S. Alexander Jacobson
-
Thomas Hallgren
-
Tomasz Zielonka