9.5. Select: Synchronous I/O multiplexing

The Select interface provides a Haskell wrapper for the select() OS call supplied by many modern UNIX variants. Select exports the following:

type TimeOut = Maybe Int
  -- Nothing => wait indefinitely.
  -- Just x | x >= 0    => block waiting for 'x' micro seconds.
  --        | otherwise => block waiting for '-x' micro seconds.

hSelect :: [Handle]
        -> [Handle]
        -> [Handle]
        -> TimeOut
        -> IO SelectResult

type SelectResult
 = ( [Handle]  -- input  handles ready
   , [Handle]  -- output handles ready
   , [Handle]  -- exc.   handles ready
   )

Here's an example of how it could be used:

module Main(main) where

import Select
import IO

main :: IO ()
main = do
  hSetBuffering stdin NoBuffering
  putStrLn "waiting for input to appear"
  hSelect [stdin] [] [] Nothing
  putStrLn "input ready, let's try reading"
  x <- getChar
  print x

where the call to hSelect makes the process go to sleep until there's input available on stdin.

9.5.1. Using hSelect with Concurrent Haskell

In brief: don't. For two reasons:

  • hSelect will cause all your Haskell threads to block until the hSelect returns, much like any call to a foreign function.

  • You don't need to. Concurrent Haskell will let you do I/O on multiple file handles concurrently by forking threads, and if you need to assign a timeout, then this can be done using a combination of threadDelay and asynchronous exceptions.