base-4.20.2.0: Core data structures and operations

Copyright | (c) The University of Glasgow 2007
License | BSD-style (see the file libraries/base/LICENSE)
Maintainer | libraries@haskell.org
Stability | stable
Portability | non-portable
Safe Haskell | Safe
Language | Haskell2010

System.Timeout

Description

Attach a timeout event to arbitrary `IO` computations.

Synopsis

- data Timeout
- timeout :: Int -> IO a -> IO (Maybe a)

# Documentation

data Timeout Source #

An exception thrown to a thread by `timeout` to interrupt a timed-out computation.

Since: base-4.0

#### Instances

Instances details

Exception Timeout Source # | Since: base-4.7.0.0
Instance details Defined in System.Timeout Methods toException :: Timeout -> SomeException Source # fromException :: SomeException -> Maybe Timeout Source # displayException :: Timeout -> String Source # backtraceDesired :: Timeout -> Bool Source #
Show Timeout Source # | Since: base-4.0
Instance details Defined in System.Timeout Methods showsPrec :: Int -> Timeout -> ShowS Source # show :: Timeout -> String Source # showList :: [Timeout] -> ShowS Source #
Eq Timeout Source # |
Instance details Defined in System.Timeout Methods (==) :: Timeout -> Timeout -> Bool Source # (/=) :: Timeout -> Timeout -> Bool Source #

timeout :: Int -> IO a -> IO (Maybe a) Source #

Wrap an `IO` computation to time out and return `Nothing` in case no result is available within `n` microseconds (`1/10^6` seconds). In case a result is available before the timeout expires, `Just a` is returned. A negative timeout interval means "wait indefinitely". When specifying long timeouts, be careful not to exceed `maxBound :: Int`, which on 32-bit machines is only 2147483647 μs, less than 36 minutes. Consider using `Control.Concurrent.Timeout.timeout` from `unbounded-delays` package.

    >>> timeout 1000000 (threadDelay 1000 *> pure "finished on time")
    Just "finished on time"

    >>> timeout 10000 (threadDelay 100000 *> pure "finished on time")
    Nothing

The design of this combinator was guided by the objective that `timeout n f` should behave exactly the same as `f` as long as `f` doesn't time out. This means that `f` has the same `myThreadId` it would have without the timeout wrapper. Any exceptions `f` might throw cancel the timeout and propagate further up. It also possible for `f` to receive exceptions thrown to it by another thread.

A tricky implementation detail is the question of how to abort an `IO` computation. This combinator relies on asynchronous exceptions internally (namely throwing the computation the `Timeout` exception). The technique works very well for computations executing inside of the Haskell runtime system, but it doesn't work at all for non-Haskell code. Foreign function calls, for example, cannot be timed out with this combinator simply because an arbitrary C function cannot receive asynchronous exceptions. When `timeout` is used to wrap an FFI call that blocks, no timeout event can be delivered until the FFI call returns, which pretty much negates the purpose of the combinator. In practice, however, this limitation is less severe than it may sound. Standard I/O functions like `hGetBuf`, `hPutBuf`, Network.Socket.accept, or `hWaitForInput` appear to be blocking, but they really don't because the runtime system uses scheduling mechanisms like `select(2)` to perform asynchronous I/O, so it is possible to interrupt standard socket I/O or file I/O using this combinator.