Faster timeout but is it correct?
Bas van Dijk
v.dijk.bas at gmail.com
Wed Feb 16 09:39:46 CET 2011
Dear all,
I wrote a faster implementation for System.Timeout.timeout but wonder
whether it's correct. It would be great if someone can review the
code.
The implementation comes with a tiny Criterion benchmark:
darcs get http://bifunctor.homelinux.net/~bas/bench_timeouts/
On ghc-7.0.1 with -O2 the following benchmark, which always times out,
doesn't show a difference with the current timeout:
timeout 1 (threadDelay 1000000)
However the following benchmark, which never times out, shows nice
speedups for both a non-threaded and a threaded version:
timeout 1000000 (return ())
non-threaded: 3.6 faster
threaded: 10.8 faster
I suspect the reason why my timeout is faster is that I use only one
'catch' while the original uses two: handleJust and bracket. I have to
admit that my implementation is more complex and more fragile than the
original. That's why I'm not sure of it's correctness yet:
newtype Timeout = Timeout Unique deriving (Eq, Typeable)
instance Show Timeout where
show _ = "<<timeout>>"
instance Exception Timeout
timeout :: Int -> IO a -> IO (Maybe a)
timeout n f
| n < 0 = fmap Just f
| n == 0 = return Nothing
| otherwise = do
myTid <- myThreadId
timeoutEx <- fmap Timeout newUnique
uninterruptibleMask $ \restore -> do
tid <- restore $ forkIO $ threadDelay n >> throwTo myTid timeoutEx
let handle e = case fromException (e :: SomeException) of
Just timeoutEx' | timeoutEx' == timeoutEx
-> return Nothing
_ -> killThread tid >> throwIO e
mb <- restore (fmap Just f) `catch` handle
killThread tid
return mb
If nobody proves it incorrect I will make a patch for the base library.
Regards,
Bas
More information about the Libraries
mailing list