Waiting on two inputs in Haskell, simultaneously

concurrency, haskell, io

Solution

I don't think "using a single thread" makes sense here. You must already be using multiple Haskell threads anyway to write to the `TChan`. You should use two Haskell threads to do this, and use an `MVar` or similar to communicate the first result to arrive. For example:

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)

A proper implementation would probably clean up the threads left lying around afterwards, btw.

Problem

The title may be a bit vague. This is what I mean: Say I have two ways of getting input to my program. The first is via the keyboard, using the function `getLine` which blocks until a line is read. The other is, say, via a `TChan`, where using `readTChan chan` will also result in a block until a value is present in the channel, whereupon it will be read. What I want to accomplish is being able to wait for both values, using a single thread and not allowing my CPU to jump to 100%. The moment one of the two values is available, it is fetched and the program resumes. (Say, using `Either` to notify which of the two values was received.) Is this possible? Thank you very much!

Original source