module Clckwrks.IOThread where
import Control.Concurrent (ThreadId, forkIO, killThread)
import Control.Concurrent.Chan (Chan,newChan, readChan, writeChan)
import Control.Concurrent.MVar (MVar, newEmptyMVar, putMVar, readMVar)
import Control.Exception
import Control.Monad (forever)
data IOThread a b = IOThread { ioThreadId :: ThreadId
, ioThreadChan :: (Chan (a, MVar (Either SomeException b)))
}
startIOThread :: (a -> IO b)
-> IO (IOThread a b)
startIOThread f =
do c <- newChan
tid <- forkIO $ ioThread f c
return (IOThread tid c)
where
ioThread f c =
forever $ do (a, mvar) <- readChan c
b <- try $ f a
putMVar mvar b
killIOThread :: IOThread a b -> IO ()
killIOThread iot = killThread (ioThreadId iot)
ioRequest :: (IOThread a b)
-> a
-> IO b
ioRequest iot a =
do resp <- newEmptyMVar
writeChan (ioThreadChan iot) (a, resp)
e <- readMVar resp
case e of
(Right r) -> return r
(Left err) -> throwIO err