
On 19 June 2004 03:06, Thomas Hallgren wrote:
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)...
It's a hard problem. Trying to code up takeEitherMVar by hand always seems to lead to solutions with race conditions - I can't see a way to do it. Perhaps takeEitherMVar should be provided as a primitive, but I'm concerned that the same problems will crop up if we tried to implement takeEitherMVar in a multi-threaded runtime (GHC doesn't currently have a true multi-threaded runtime, but we'd like to do it someday). So I think in order to do this you have to build another abstraction around MVars. I've attached some code I just hacked up to do just that; it's untested (but compiles), and has a couple of known deficiencies, but it might be along the right lines. Cheers, Simon