This is basically a rehash of a useful Simon Marlow post to haskell-cafe, but with a few tweaks. It’s a useful way of wrapping an STM action with a timeout. In my case, I want to wait until some mutable state satisfies a predicate, and I want a timeout to fire if it takes too long. I hate thinking in microseconds, so there’s a helper type to improve that. And where Simon used a nested Maybe, I created some explicitly named constructors.
import Control.Concurrent.STM import Control.Concurrent import Control.Monad data TimeLimited a = Timeout | Result a deriving Show data Timeout = TimeoutSecs Int | TimeoutMs Int waitUntil :: TVar a -> (a -> Bool) -> Timeout -> IO (TimeLimited a) waitUntil var pred timeout = do timer < - registerDelay $ case timeout of TimeoutSecs n -> 1000000 * n TimeoutMs n -> 1000 * n let check_timeout = do b < - readTVar timer if b then return Timeout else retry check_t = do m <- readTVar var when (not $ pred m) retry return $ Result m atomically $ check_timeout `orElse` check_t main = do tvar <- atomically $ newTVar 44 -- tvar <- atomically $ newTVar 41 waitUntil tvar (>43) (TimeoutSecs 1) >>= print