{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# OPTIONS_GHC -Wno-redundant-constraints #-}
module Network.Mux.Timeout
( TimeoutFn
, withTimeoutSerial
, withTimeoutSerialNative
, withTimeoutSerialAlternative
) where
import Control.Exception (asyncExceptionFromException,
asyncExceptionToException)
import Control.Monad
import Control.Monad.Class.MonadAsync
import Control.Monad.Class.MonadFork
import Control.Monad.Class.MonadSTM
import Control.Monad.Class.MonadThrow
import Control.Monad.Class.MonadTime
import Control.Monad.Class.MonadTimer (MonadTimer, registerDelay)
import qualified Control.Monad.Class.MonadTimer as MonadTimer
type TimeoutFn m = forall a. DiffTime -> m a -> m (Maybe a)
withTimeoutSerial, withTimeoutSerialNative
:: forall m b. (MonadAsync m, MonadFork m,
MonadMonotonicTime m, MonadTimer m,
MonadMask m, MonadThrow (STM m))
=> (TimeoutFn m -> m b) -> m b
#if defined(mingw32_HOST_OS)
withTimeoutSerial = withTimeoutSerialAlternative
#else
withTimeoutSerial :: (TimeoutFn m -> m b) -> m b
withTimeoutSerial = (TimeoutFn m -> m b) -> m b
forall (m :: * -> *) b.
(MonadAsync m, MonadFork m, MonadMonotonicTime m, MonadTimer m,
MonadMask m, MonadThrow (STM m)) =>
(TimeoutFn m -> m b) -> m b
withTimeoutSerialNative
#endif
withTimeoutSerialNative :: (TimeoutFn m -> m b) -> m b
withTimeoutSerialNative TimeoutFn m -> m b
body = TimeoutFn m -> m b
body TimeoutFn m
forall (m :: * -> *) a.
MonadTimer m =>
DiffTime -> m a -> m (Maybe a)
MonadTimer.timeout
withTimeoutSerialAlternative
:: forall m b. (MonadAsync m, MonadFork m,
MonadMonotonicTime m, MonadTimer m,
MonadMask m, MonadThrow (STM m))
=> (TimeoutFn m -> m b) -> m b
withTimeoutSerialAlternative :: (TimeoutFn m -> m b) -> m b
withTimeoutSerialAlternative TimeoutFn m -> m b
body = do
MonitorState m
monitorState <- m (MonitorState m)
forall (m :: * -> *). MonadSTM m => m (MonitorState m)
newMonitorState
m () -> (Async m () -> m b) -> m b
forall (m :: * -> *) a b.
MonadAsync m =>
m a -> (Async m a -> m b) -> m b
withAsync (MonitorState m -> m ()
forall (m :: * -> *).
(MonadFork m, MonadSTM m, MonadMonotonicTime m, MonadTimer m,
MonadThrow (STM m)) =>
MonitorState m -> m ()
monitoringThread MonitorState m
monitorState) ((Async m () -> m b) -> m b) -> (Async m () -> m b) -> m b
forall a b. (a -> b) -> a -> b
$ \Async m ()
_ ->
TimeoutFn m -> m b
body (MonitorState m -> DiffTime -> m a -> m (Maybe a)
forall (m :: * -> *) a.
(MonadFork m, MonadMonotonicTime m, MonadTimer m, MonadMask m,
MonadThrow (STM m)) =>
MonitorState m -> DiffTime -> m a -> m (Maybe a)
timeout MonitorState m
monitorState)
data MonitorState m =
MonitorState {
MonitorState m -> TVar m (NextTimeout m)
nextTimeoutVar :: !(TVar m (NextTimeout m)),
MonitorState m -> TVar m Time
curDeadlineVar :: !(TVar m Time),
MonitorState m -> TVar m Bool
deadlineResetVar :: !(TVar m Bool)
}
data NextTimeout m = NoNextTimeout
| NextTimeout
!(ThreadId m)
!Time
!(TVar m TimeoutState)
newMonitorState :: MonadSTM m => m (MonitorState m)
newMonitorState :: m (MonitorState m)
newMonitorState = do
TVar m (NextTimeout m)
nextTimeoutVar <- NextTimeout m -> m (TVar m (NextTimeout m))
forall (m :: * -> *) a. MonadSTM m => a -> m (TVar m a)
newTVarIO NextTimeout m
forall (m :: * -> *). NextTimeout m
NoNextTimeout
TVar m Time
curDeadlineVar <- Time -> m (TVar m Time)
forall (m :: * -> *) a. MonadSTM m => a -> m (TVar m a)
newTVarIO (DiffTime -> Time
Time DiffTime
0)
TVar m Bool
deadlineResetVar <- Bool -> m (TVar m Bool)
forall (m :: * -> *) a. MonadSTM m => a -> m (TVar m a)
newTVarIO Bool
False
MonitorState m -> m (MonitorState m)
forall (m :: * -> *) a. Monad m => a -> m a
return MonitorState :: forall (m :: * -> *).
TVar m (NextTimeout m)
-> TVar m Time -> TVar m Bool -> MonitorState m
MonitorState{TVar m Bool
TVar m Time
TVar m (NextTimeout m)
deadlineResetVar :: TVar m Bool
curDeadlineVar :: TVar m Time
nextTimeoutVar :: TVar m (NextTimeout m)
deadlineResetVar :: TVar m Bool
curDeadlineVar :: TVar m Time
nextTimeoutVar :: TVar m (NextTimeout m)
..}
setNewTimer :: MonadSTM m
=> MonitorState m
-> ThreadId m
-> Time
-> TVar m TimeoutState
-> m ()
setNewTimer :: MonitorState m -> ThreadId m -> Time -> TVar m TimeoutState -> m ()
setNewTimer MonitorState{TVar m (NextTimeout m)
nextTimeoutVar :: TVar m (NextTimeout m)
nextTimeoutVar :: forall (m :: * -> *). MonitorState m -> TVar m (NextTimeout m)
nextTimeoutVar, TVar m Time
curDeadlineVar :: TVar m Time
curDeadlineVar :: forall (m :: * -> *). MonitorState m -> TVar m Time
curDeadlineVar, TVar m Bool
deadlineResetVar :: TVar m Bool
deadlineResetVar :: forall (m :: * -> *). MonitorState m -> TVar m Bool
deadlineResetVar}
!ThreadId m
tid !Time
deadline !TVar m TimeoutState
stateVar =
STM m () -> m ()
forall (m :: * -> *) a.
(MonadSTM m, HasCallStack) =>
STM m a -> m a
atomically (STM m () -> m ()) -> STM m () -> m ()
forall a b. (a -> b) -> a -> b
$ do
TVar m (NextTimeout m) -> NextTimeout m -> STM m ()
forall (m :: * -> *) a. MonadSTM m => TVar m a -> a -> STM m ()
writeTVar TVar m (NextTimeout m)
nextTimeoutVar (ThreadId m -> Time -> TVar m TimeoutState -> NextTimeout m
forall (m :: * -> *).
ThreadId m -> Time -> TVar m TimeoutState -> NextTimeout m
NextTimeout ThreadId m
tid Time
deadline TVar m TimeoutState
stateVar)
Time
curDeadline <- TVar m Time -> STM m Time
forall (m :: * -> *) a. MonadSTM m => TVar m a -> STM m a
readTVar TVar m Time
curDeadlineVar
Bool -> STM m () -> STM m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Time
deadline Time -> Time -> Bool
forall a. Ord a => a -> a -> Bool
< Time
curDeadline) (STM m () -> STM m ()) -> STM m () -> STM m ()
forall a b. (a -> b) -> a -> b
$
TVar m Bool -> Bool -> STM m ()
forall (m :: * -> *) a. MonadSTM m => TVar m a -> a -> STM m ()
writeTVar TVar m Bool
deadlineResetVar Bool
True
readNextTimeout :: MonadSTM m
=> MonitorState m
-> m (ThreadId m, Time, TVar m TimeoutState)
readNextTimeout :: MonitorState m -> m (ThreadId m, Time, TVar m TimeoutState)
readNextTimeout MonitorState{TVar m (NextTimeout m)
nextTimeoutVar :: TVar m (NextTimeout m)
nextTimeoutVar :: forall (m :: * -> *). MonitorState m -> TVar m (NextTimeout m)
nextTimeoutVar, TVar m Time
curDeadlineVar :: TVar m Time
curDeadlineVar :: forall (m :: * -> *). MonitorState m -> TVar m Time
curDeadlineVar, TVar m Bool
deadlineResetVar :: TVar m Bool
deadlineResetVar :: forall (m :: * -> *). MonitorState m -> TVar m Bool
deadlineResetVar} = do
STM m (ThreadId m, Time, TVar m TimeoutState)
-> m (ThreadId m, Time, TVar m TimeoutState)
forall (m :: * -> *) a.
(MonadSTM m, HasCallStack) =>
STM m a -> m a
atomically (STM m (ThreadId m, Time, TVar m TimeoutState)
-> m (ThreadId m, Time, TVar m TimeoutState))
-> STM m (ThreadId m, Time, TVar m TimeoutState)
-> m (ThreadId m, Time, TVar m TimeoutState)
forall a b. (a -> b) -> a -> b
$ do
NextTimeout m
nextTimeout <- TVar m (NextTimeout m) -> STM m (NextTimeout m)
forall (m :: * -> *) a. MonadSTM m => TVar m a -> STM m a
readTVar TVar m (NextTimeout m)
nextTimeoutVar
case NextTimeout m
nextTimeout of
NextTimeout m
NoNextTimeout -> STM m (ThreadId m, Time, TVar m TimeoutState)
forall (m :: * -> *) a. MonadSTM m => STM m a
retry
NextTimeout ThreadId m
tid Time
deadline TVar m TimeoutState
stateVar -> do
TVar m (NextTimeout m) -> NextTimeout m -> STM m ()
forall (m :: * -> *) a. MonadSTM m => TVar m a -> a -> STM m ()
writeTVar TVar m (NextTimeout m)
nextTimeoutVar NextTimeout m
forall (m :: * -> *). NextTimeout m
NoNextTimeout
TVar m Time -> Time -> STM m ()
forall (m :: * -> *) a. MonadSTM m => TVar m a -> a -> STM m ()
writeTVar TVar m Time
curDeadlineVar Time
deadline
TVar m Bool -> Bool -> STM m ()
forall (m :: * -> *) a. MonadSTM m => TVar m a -> a -> STM m ()
writeTVar TVar m Bool
deadlineResetVar Bool
False
(ThreadId m, Time, TVar m TimeoutState)
-> STM m (ThreadId m, Time, TVar m TimeoutState)
forall (m :: * -> *) a. Monad m => a -> m a
return (ThreadId m
tid, Time
deadline, TVar m TimeoutState
stateVar)
data TimeoutState = TimeoutPending
| TimeoutCancelled
| TimeoutFired
| TimeoutTerminated
data TimeoutException = TimeoutException deriving Int -> TimeoutException -> ShowS
[TimeoutException] -> ShowS
TimeoutException -> String
(Int -> TimeoutException -> ShowS)
-> (TimeoutException -> String)
-> ([TimeoutException] -> ShowS)
-> Show TimeoutException
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [TimeoutException] -> ShowS
$cshowList :: [TimeoutException] -> ShowS
show :: TimeoutException -> String
$cshow :: TimeoutException -> String
showsPrec :: Int -> TimeoutException -> ShowS
$cshowsPrec :: Int -> TimeoutException -> ShowS
Show
instance Exception TimeoutException where
toException :: TimeoutException -> SomeException
toException = TimeoutException -> SomeException
forall e. Exception e => e -> SomeException
asyncExceptionToException
fromException :: SomeException -> Maybe TimeoutException
fromException = SomeException -> Maybe TimeoutException
forall e. Exception e => SomeException -> Maybe e
asyncExceptionFromException
timeout :: forall m a.
(MonadFork m, MonadMonotonicTime m, MonadTimer m,
MonadMask m, MonadThrow (STM m))
=> MonitorState m
-> DiffTime -> m a -> m (Maybe a)
timeout :: MonitorState m -> DiffTime -> m a -> m (Maybe a)
timeout MonitorState m
_ DiffTime
delay m a
action | DiffTime
delay DiffTime -> DiffTime -> Bool
forall a. Ord a => a -> a -> Bool
< DiffTime
0 = a -> Maybe a
forall a. a -> Maybe a
Just (a -> Maybe a) -> m a -> m (Maybe a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m a
action
timeout MonitorState m
_ DiffTime
delay m a
_ | DiffTime
delay DiffTime -> DiffTime -> Bool
forall a. Eq a => a -> a -> Bool
== DiffTime
0 = Maybe a -> m (Maybe a)
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe a
forall a. Maybe a
Nothing
timeout MonitorState m
monitorState DiffTime
delay m a
action =
((forall a. m a -> m a) -> m (Maybe a)) -> m (Maybe a)
forall (m :: * -> *) b.
MonadMask m =>
((forall a. m a -> m a) -> m b) -> m b
mask (((forall a. m a -> m a) -> m (Maybe a)) -> m (Maybe a))
-> ((forall a. m a -> m a) -> m (Maybe a)) -> m (Maybe a)
forall a b. (a -> b) -> a -> b
$ \forall a. m a -> m a
restore -> do
ThreadId m
tid <- m (ThreadId m)
forall (m :: * -> *). MonadThread m => m (ThreadId m)
myThreadId
TVar m TimeoutState
timeoutStateVar <- TimeoutState -> m (TVar m TimeoutState)
forall (m :: * -> *) a. MonadSTM m => a -> m (TVar m a)
newTVarIO TimeoutState
TimeoutPending
Time
now <- m Time
forall (m :: * -> *). MonadMonotonicTime m => m Time
getMonotonicTime
let deadline :: Time
deadline = DiffTime -> Time -> Time
addTime DiffTime
delay Time
now
MonitorState m -> ThreadId m -> Time -> TVar m TimeoutState -> m ()
forall (m :: * -> *).
MonadSTM m =>
MonitorState m -> ThreadId m -> Time -> TVar m TimeoutState -> m ()
setNewTimer MonitorState m
monitorState ThreadId m
tid Time
deadline TVar m TimeoutState
timeoutStateVar
a
result <- m a -> m a
forall a. m a -> m a
restore m a
action
Bool
timeoutFired <- STM m Bool -> m Bool
forall (m :: * -> *) a.
(MonadSTM m, HasCallStack) =>
STM m a -> m a
atomically (STM m Bool -> m Bool) -> STM m Bool -> m Bool
forall a b. (a -> b) -> a -> b
$ do
TimeoutState
st <- TVar m TimeoutState -> STM m TimeoutState
forall (m :: * -> *) a. MonadSTM m => TVar m a -> STM m a
readTVar TVar m TimeoutState
timeoutStateVar
case TimeoutState
st of
TimeoutState
TimeoutFired -> Bool -> STM m Bool
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
True
TimeoutState
TimeoutPending -> TVar m TimeoutState -> TimeoutState -> STM m ()
forall (m :: * -> *) a. MonadSTM m => TVar m a -> a -> STM m ()
writeTVar TVar m TimeoutState
timeoutStateVar TimeoutState
TimeoutCancelled
STM m () -> STM m Bool -> STM m Bool
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Bool -> STM m Bool
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
TimeoutState
_ -> TimeoutAssertion -> STM m Bool
forall (m :: * -> *) e a.
(MonadSTM m, MonadThrow (STM m), Exception e) =>
e -> STM m a
throwSTM TimeoutAssertion
TimeoutImpossibleTimeoutState
if Bool -> Bool
not Bool
timeoutFired
then Maybe a -> m (Maybe a)
forall (m :: * -> *) a. Monad m => a -> m a
return (a -> Maybe a
forall a. a -> Maybe a
Just a
result)
else STM m (Maybe a) -> m (Maybe a)
forall (m :: * -> *) a.
(MonadSTM m, HasCallStack) =>
STM m a -> m a
atomically (STM m (Maybe a) -> m (Maybe a)) -> STM m (Maybe a) -> m (Maybe a)
forall a b. (a -> b) -> a -> b
$ do
TimeoutState
st <- TVar m TimeoutState -> STM m TimeoutState
forall (m :: * -> *) a. MonadSTM m => TVar m a -> STM m a
readTVar TVar m TimeoutState
timeoutStateVar
case TimeoutState
st of
TimeoutState
TimeoutFired -> STM m (Maybe a)
forall (m :: * -> *) a. MonadSTM m => STM m a
retry
TimeoutState
TimeoutTerminated -> TimeoutAssertion -> STM m (Maybe a)
forall (m :: * -> *) e a.
(MonadSTM m, MonadThrow (STM m), Exception e) =>
e -> STM m a
throwSTM TimeoutAssertion
TimeoutImpossibleReachedTerminated
TimeoutState
_ -> TimeoutAssertion -> STM m (Maybe a)
forall (m :: * -> *) e a.
(MonadSTM m, MonadThrow (STM m), Exception e) =>
e -> STM m a
throwSTM TimeoutAssertion
TimeoutImpossibleTimeoutState
m (Maybe a) -> (TimeoutException -> m (Maybe a)) -> m (Maybe a)
forall (m :: * -> *) e a.
(MonadCatch m, Exception e) =>
m a -> (e -> m a) -> m a
`catch` \TimeoutException
TimeoutException -> Maybe a -> m (Maybe a)
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe a
forall a. Maybe a
Nothing
monitoringThread :: (MonadFork m, MonadSTM m,
MonadMonotonicTime m, MonadTimer m,
MonadThrow (STM m))
=> MonitorState m -> m ()
monitoringThread :: MonitorState m -> m ()
monitoringThread monitorState :: MonitorState m
monitorState@MonitorState{TVar m Bool
deadlineResetVar :: TVar m Bool
deadlineResetVar :: forall (m :: * -> *). MonitorState m -> TVar m Bool
deadlineResetVar} = do
ThreadId m
threadId <- m (ThreadId m)
forall (m :: * -> *). MonadThread m => m (ThreadId m)
myThreadId
ThreadId m -> String -> m ()
forall (m :: * -> *). MonadThread m => ThreadId m -> String -> m ()
labelThread ThreadId m
threadId String
"timeout-monitoring-thread"
m () -> m ()
forall (f :: * -> *) a b. Applicative f => f a -> f b
forever (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$ do
(ThreadId m
tid, Time
deadline, TVar m TimeoutState
timeoutStateVar) <- MonitorState m -> m (ThreadId m, Time, TVar m TimeoutState)
forall (m :: * -> *).
MonadSTM m =>
MonitorState m -> m (ThreadId m, Time, TVar m TimeoutState)
readNextTimeout MonitorState m
monitorState
Time
now <- m Time
forall (m :: * -> *). MonadMonotonicTime m => m Time
getMonotonicTime
let delay :: DiffTime
delay = Time -> Time -> DiffTime
diffTime Time
deadline Time
now
Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (DiffTime
delay DiffTime -> DiffTime -> Bool
forall a. Ord a => a -> a -> Bool
> DiffTime
0) (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$ do
TVar m Bool
timerExpired <- DiffTime -> m (TVar m Bool)
forall (m :: * -> *). MonadTimer m => DiffTime -> m (TVar m Bool)
registerDelay DiffTime
delay
STM m () -> m ()
forall (m :: * -> *) a.
(MonadSTM m, HasCallStack) =>
STM m a -> m a
atomically (STM m () -> m ()) -> STM m () -> m ()
forall a b. (a -> b) -> a -> b
$
(TVar m Bool -> STM m Bool
forall (m :: * -> *) a. MonadSTM m => TVar m a -> STM m a
readTVar TVar m Bool
timerExpired STM m Bool -> (Bool -> STM m ()) -> STM m ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Bool -> STM m ()
forall (m :: * -> *). MonadSTM m => Bool -> STM m ()
check)
STM m () -> STM m () -> STM m ()
forall (m :: * -> *) a. MonadSTM m => STM m a -> STM m a -> STM m a
`orElse`
(TVar m Bool -> STM m Bool
forall (m :: * -> *) a. MonadSTM m => TVar m a -> STM m a
readTVar TVar m Bool
deadlineResetVar STM m Bool -> (Bool -> STM m ()) -> STM m ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Bool -> STM m ()
forall (m :: * -> *). MonadSTM m => Bool -> STM m ()
check)
Bool
cancelled <- STM m Bool -> m Bool
forall (m :: * -> *) a.
(MonadSTM m, HasCallStack) =>
STM m a -> m a
atomically (STM m Bool -> m Bool) -> STM m Bool -> m Bool
forall a b. (a -> b) -> a -> b
$ do
TimeoutState
st <- TVar m TimeoutState -> STM m TimeoutState
forall (m :: * -> *) a. MonadSTM m => TVar m a -> STM m a
readTVar TVar m TimeoutState
timeoutStateVar
case TimeoutState
st of
TimeoutState
TimeoutPending -> TVar m TimeoutState -> TimeoutState -> STM m ()
forall (m :: * -> *) a. MonadSTM m => TVar m a -> a -> STM m ()
writeTVar TVar m TimeoutState
timeoutStateVar TimeoutState
TimeoutFired
STM m () -> STM m Bool -> STM m Bool
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Bool -> STM m Bool
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
TimeoutState
TimeoutCancelled -> Bool -> STM m Bool
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
True
TimeoutState
_ -> TimeoutAssertion -> STM m Bool
forall (m :: * -> *) e a.
(MonadSTM m, MonadThrow (STM m), Exception e) =>
e -> STM m a
throwSTM TimeoutAssertion
TimeoutImpossibleMonitorState
Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless Bool
cancelled (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$ do
ThreadId m -> TimeoutException -> m ()
forall (m :: * -> *) e.
(MonadFork m, Exception e) =>
ThreadId m -> e -> m ()
throwTo ThreadId m
tid TimeoutException
TimeoutException
STM m () -> m ()
forall (m :: * -> *) a.
(MonadSTM m, HasCallStack) =>
STM m a -> m a
atomically (STM m () -> m ()) -> STM m () -> m ()
forall a b. (a -> b) -> a -> b
$ TVar m TimeoutState -> TimeoutState -> STM m ()
forall (m :: * -> *) a. MonadSTM m => TVar m a -> a -> STM m ()
writeTVar TVar m TimeoutState
timeoutStateVar TimeoutState
TimeoutTerminated
data TimeoutAssertion = TimeoutImpossibleReachedTerminated
| TimeoutImpossibleTimeoutState
| TimeoutImpossibleMonitorState
deriving Int -> TimeoutAssertion -> ShowS
[TimeoutAssertion] -> ShowS
TimeoutAssertion -> String
(Int -> TimeoutAssertion -> ShowS)
-> (TimeoutAssertion -> String)
-> ([TimeoutAssertion] -> ShowS)
-> Show TimeoutAssertion
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [TimeoutAssertion] -> ShowS
$cshowList :: [TimeoutAssertion] -> ShowS
show :: TimeoutAssertion -> String
$cshow :: TimeoutAssertion -> String
showsPrec :: Int -> TimeoutAssertion -> ShowS
$cshowsPrec :: Int -> TimeoutAssertion -> ShowS
Show
instance Exception TimeoutAssertion