-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Thread-indexed, nested contexts -- -- Thread-indexed storage around arbitrary context values. The interface -- supports nesting context values per thread, and at any point, the -- calling thread may ask for their current context. @package context @version 0.2.0.0 module Context.Internal -- | Opaque type that manages thread-indexed storage of context values. data Store ctx Store :: IORef (State ctx) -> Unique -> Store ctx [$sel:ref:Store] :: Store ctx -> IORef (State ctx) [$sel:key:Store] :: Store ctx -> Unique data State ctx State :: Map ThreadId [ctx] -> Maybe ctx -> State ctx [$sel:stacks:State] :: State ctx -> Map ThreadId [ctx] [$sel:def:State] :: State ctx -> Maybe ctx -- | An exception which may be thrown when the calling thread does not have -- a registered context. data NotFoundException NotFoundException :: ThreadId -> NotFoundException [$sel:threadId:NotFoundException] :: NotFoundException -> ThreadId -- | Provides a new Store. This is a lower-level function and is -- provided mainly to give library authors more fine-grained control when -- using a Store as an implementation detail. -- -- withNonEmptyStore/withEmptyStore should generally be -- preferred over this function when acquiring a Store. withStore :: forall m ctx a. (MonadIO m, MonadMask m) => PropagationStrategy -> Maybe ctx -> (Store ctx -> m a) -> m a -- | Creates a new Store. This is a lower-level function and is -- provided only to support the use case of creating a -- Store as a global: -- --
-- store :: Store Int
-- store = unsafePerformIO $ Context.newStore Context.defaultPropagation Nothing
-- {-# NOINLINE store #-}
--
--
-- Outside of the global variable use case, withNonEmptyStore,
-- withEmptyStore, or even the lower-level withStore should
-- always be preferred over this function when acquiring a
-- Store.
newStore :: forall m ctx. MonadIO m => PropagationStrategy -> Maybe ctx -> m (Store ctx)
-- | Register a context in the specified Store on behalf of the
-- calling thread, for the duration of the specified action.
use :: forall m ctx a. (MonadIO m, MonadMask m) => Store ctx -> ctx -> m a -> m a
push :: Store ctx -> ctx -> IO ()
pop :: Store ctx -> IO ()
-- | Provide the calling thread its current context from the specified
-- Store, if present.
mineMay :: forall m ctx. MonadIO m => Store ctx -> m (Maybe ctx)
mineMayOnDefault :: forall m ctx. MonadIO m => (Maybe ctx -> Maybe ctx) -> Store ctx -> m (Maybe ctx)
-- | Set the default context value for a store. If the store was
-- initialized as an empty store, this function converts it to a
-- non-empty store. If the store was initialized as a non-empty store,
-- this overwrites the default context value.
--
-- One common use case for this function is to convert an empty store in
-- a global variable to a non-empty store while the application is
-- initializing/acquiring resources:
--
--
-- depsStore :: Store Dependencies
-- depsStore = unsafePerformIO $ Context.newStore Context.defaultPropagation Nothing
-- {-# NOINLINE depsStore #-}
--
-- main :: IO ()
-- main = do
-- let config = -- ...
-- withDependencies config \deps -> do
-- Context.setDefault depsStore deps
-- -- ...
--
setDefault :: forall m ctx. MonadIO m => Store ctx -> ctx -> m ()
throwContextNotFound :: forall m a. (MonadIO m, MonadThrow m) => m a
-- | A View provides a read-only view into a Store.
-- View trades the Store ability to register new context
-- for the ability to arbitrarily transform context values locally to the
-- View.
data View ctx
[MkView] :: (ctx' -> ctx) -> Store ctx' -> View ctx
-- | Provide the calling thread a view of its current context from the
-- specified View. Throws a NotFoundException when the
-- calling thread has no registered context.
view :: (MonadIO m, MonadThrow m) => View ctx -> m ctx
-- | Provide the calling thread a view of its current context from the
-- specified View, if present.
viewMay :: MonadIO m => View ctx -> m (Maybe ctx)
-- | Create a View from the provided Store.
toView :: Store ctx -> View ctx
-- | The PropagationStrategy controls the behavior used by
-- Context.Concurrent when propagating context from a "parent"
-- thread to a new thread.
data PropagationStrategy
NoPropagation :: PropagationStrategy
LatestPropagation :: PropagationStrategy
newtype Registry
Registry :: IORef (Map Unique AnyStore) -> Registry
[$sel:ref:Registry] :: Registry -> IORef (Map Unique AnyStore)
data AnyStore
[MkAnyStore] :: forall ctx. Store ctx -> AnyStore
registry :: Registry
emptyRegistry :: IO Registry
withPropagator :: ((IO a -> IO a) -> IO b) -> IO b
withRegisteredPropagator :: Registry -> ((IO a -> IO a) -> IO b) -> IO b
register :: Registry -> Store ctx -> IO ()
unregister :: Registry -> Store ctx -> IO ()
bug :: HasCallStack => String -> a
instance GHC.Exception.Type.Exception Context.Internal.NotFoundException
instance GHC.Show.Show Context.Internal.NotFoundException
instance GHC.Generics.Generic Context.Internal.NotFoundException
instance GHC.Classes.Eq Context.Internal.NotFoundException
instance GHC.Base.Functor Context.Internal.View
module Context.Concurrent
-- | See forkIO.
forkIO :: IO () -> IO ThreadId
-- | See forkFinally.
forkFinally :: IO a -> (Either SomeException a -> IO ()) -> IO ThreadId
-- | See forkIOWithUnmask.
forkIOWithUnmask :: ((forall a. IO a -> IO a) -> IO ()) -> IO ThreadId
-- | See forkOn.
forkOn :: Int -> IO () -> IO ThreadId
-- | See forkOnWithUnmask.
forkOnWithUnmask :: Int -> ((forall a. IO a -> IO a) -> IO ()) -> IO ThreadId
-- | See forkOS.
forkOS :: IO () -> IO ThreadId
-- | See forkOSWithUnmask.
forkOSWithUnmask :: ((forall a. IO a -> IO a) -> IO ()) -> IO ThreadId
-- | See runInBoundThread.
runInBoundThread :: IO a -> IO a
-- | See runInUnboundThread.
runInUnboundThread :: IO a -> IO a
-- | A ThreadId is an abstract type representing a handle to a
-- thread. ThreadId is an instance of Eq, Ord and
-- Show, where the Ord instance implements an arbitrary
-- total ordering over ThreadIds. The Show instance lets
-- you convert an arbitrary-valued ThreadId to string form;
-- showing a ThreadId value is occasionally useful when debugging
-- or diagnosing the behaviour of a concurrent program.
--
-- Note: in GHC, if you have a ThreadId, you essentially
-- have a pointer to the thread itself. This means the thread itself
-- can't be garbage collected until you drop the ThreadId. This
-- misfeature will hopefully be corrected at a later date.
data ThreadId
-- | Returns the ThreadId of the calling thread (GHC only).
myThreadId :: IO ThreadId
-- | killThread raises the ThreadKilled exception in the
-- given thread (GHC only).
--
-- -- killThread tid = throwTo tid ThreadKilled --killThread :: ThreadId -> IO () -- | throwTo raises an arbitrary exception in the target thread (GHC -- only). -- -- Exception delivery synchronizes between the source and target thread: -- throwTo does not return until the exception has been raised in -- the target thread. The calling thread can thus be certain that the -- target thread has received the exception. Exception delivery is also -- atomic with respect to other exceptions. Atomicity is a useful -- property to have when dealing with race conditions: e.g. if there are -- two threads that can kill each other, it is guaranteed that only one -- of the threads will get to kill the other. -- -- Whatever work the target thread was doing when the exception was -- raised is not lost: the computation is suspended until required by -- another thread. -- -- If the target thread is currently making a foreign call, then the -- exception will not be raised (and hence throwTo will not -- return) until the call has completed. This is the case regardless of -- whether the call is inside a mask or not. However, in GHC a -- foreign call can be annotated as interruptible, in which case -- a throwTo will cause the RTS to attempt to cause the call to -- return; see the GHC documentation for more details. -- -- Important note: the behaviour of throwTo differs from that -- described in the paper "Asynchronous exceptions in Haskell" -- (http://research.microsoft.com/~simonpj/Papers/asynch-exns.htm). -- In the paper, throwTo is non-blocking; but the library -- implementation adopts a more synchronous design in which -- throwTo does not return until the exception is received by the -- target thread. The trade-off is discussed in Section 9 of the paper. -- Like any blocking operation, throwTo is therefore interruptible -- (see Section 5.3 of the paper). Unlike other interruptible operations, -- however, throwTo is always interruptible, even if it -- does not actually block. -- -- There is no guarantee that the exception will be delivered promptly, -- although the runtime will endeavour to ensure that arbitrary delays -- don't occur. In GHC, an exception can only be raised when a thread -- reaches a safe point, where a safe point is where memory -- allocation occurs. Some loops do not perform any memory allocation -- inside the loop and therefore cannot be interrupted by a -- throwTo. -- -- If the target of throwTo is the calling thread, then the -- behaviour is the same as throwIO, except that the exception is -- thrown as an asynchronous exception. This means that if there is an -- enclosing pure computation, which would be the case if the current IO -- operation is inside unsafePerformIO or -- unsafeInterleaveIO, that computation is not permanently -- replaced by the exception, but is suspended as if it had received an -- asynchronous exception. -- -- Note that if throwTo is called with the current thread as the -- target, the exception will be thrown even if the thread is currently -- inside mask or uninterruptibleMask. throwTo :: Exception e => ThreadId -> e -> IO () -- | Returns the number of Haskell threads that can run truly -- simultaneously (on separate physical processors) at any given time. To -- change this value, use setNumCapabilities. getNumCapabilities :: IO Int -- | Set the number of Haskell threads that can run truly simultaneously -- (on separate physical processors) at any given time. The number passed -- to forkOn is interpreted modulo this value. The initial value -- is given by the +RTS -N runtime flag. -- -- This is also the number of threads that will participate in parallel -- garbage collection. It is strongly recommended that the number of -- capabilities is not set larger than the number of physical processor -- cores, and it may often be beneficial to leave one or more cores free -- to avoid contention with other processes in the machine. setNumCapabilities :: Int -> IO () -- | Returns the number of the capability on which the thread is currently -- running, and a boolean indicating whether the thread is locked to that -- capability or not. A thread is locked to a capability if it was -- created with forkOn. threadCapability :: ThreadId -> IO (Int, Bool) -- | The yield action allows (forces, in a co-operative multitasking -- implementation) a context-switch to any other currently runnable -- threads (if any), and is occasionally useful when implementing -- concurrency abstractions. yield :: IO () -- | Suspends the current thread for a given number of microseconds (GHC -- only). -- -- There is no guarantee that the thread will be rescheduled promptly -- when the delay has expired, but the thread will never continue to run -- earlier than specified. threadDelay :: Int -> IO () -- | Block the current thread until data is available to read on the given -- file descriptor (GHC only). -- -- This will throw an IOError if the file descriptor was closed -- while this thread was blocked. To safely close a file descriptor that -- has been used with threadWaitRead, use closeFdWith. threadWaitRead :: Fd -> IO () -- | Block the current thread until data can be written to the given file -- descriptor (GHC only). -- -- This will throw an IOError if the file descriptor was closed -- while this thread was blocked. To safely close a file descriptor that -- has been used with threadWaitWrite, use closeFdWith. threadWaitWrite :: Fd -> IO () -- | Returns an STM action that can be used to wait for data to read from a -- file descriptor. The second returned value is an IO action that can be -- used to deregister interest in the file descriptor. threadWaitReadSTM :: Fd -> IO (STM (), IO ()) -- | Returns an STM action that can be used to wait until data can be -- written to a file descriptor. The second returned value is an IO -- action that can be used to deregister interest in the file descriptor. threadWaitWriteSTM :: Fd -> IO (STM (), IO ()) -- | True if bound threads are supported. If -- rtsSupportsBoundThreads is False, -- isCurrentThreadBound will always return False and both -- forkOS and runInBoundThread will fail. rtsSupportsBoundThreads :: Bool -- | Returns True if the calling thread is bound, that is, if -- it is safe to use foreign libraries that rely on thread-local state -- from the calling thread. isCurrentThreadBound :: IO Bool -- | Make a weak pointer to a ThreadId. It can be important to do -- this if you want to hold a reference to a ThreadId while still -- allowing the thread to receive the BlockedIndefinitely family -- of exceptions (e.g. BlockedIndefinitelyOnMVar). Holding a -- normal ThreadId reference will prevent the delivery of -- BlockedIndefinitely exceptions because the reference could be -- used as the target of throwTo at any time, which would unblock -- the thread. -- -- Holding a Weak ThreadId, on the other hand, will not prevent -- the thread from receiving BlockedIndefinitely exceptions. It -- is still possible to throw an exception to a Weak ThreadId, -- but the caller must use deRefWeak first to determine whether -- the thread still exists. mkWeakThreadId :: ThreadId -> IO (Weak ThreadId) module Context.Storage -- | Provides a new Store. This is a lower-level function and is -- provided mainly to give library authors more fine-grained control when -- using a Store as an implementation detail. -- -- withNonEmptyStore/withEmptyStore should generally be -- preferred over this function when acquiring a Store. withStore :: forall m ctx a. (MonadIO m, MonadMask m) => PropagationStrategy -> Maybe ctx -> (Store ctx -> m a) -> m a -- | Creates a new Store. This is a lower-level function and is -- provided only to support the use case of creating a -- Store as a global: -- --
-- store :: Store Int
-- store = unsafePerformIO $ Context.newStore Context.defaultPropagation Nothing
-- {-# NOINLINE store #-}
--
--
-- Outside of the global variable use case, withNonEmptyStore,
-- withEmptyStore, or even the lower-level withStore should
-- always be preferred over this function when acquiring a
-- Store.
newStore :: forall m ctx. MonadIO m => PropagationStrategy -> Maybe ctx -> m (Store ctx)
-- | Set the default context value for a store. If the store was
-- initialized as an empty store, this function converts it to a
-- non-empty store. If the store was initialized as a non-empty store,
-- this overwrites the default context value.
--
-- One common use case for this function is to convert an empty store in
-- a global variable to a non-empty store while the application is
-- initializing/acquiring resources:
--
--
-- depsStore :: Store Dependencies
-- depsStore = unsafePerformIO $ Context.newStore Context.defaultPropagation Nothing
-- {-# NOINLINE depsStore #-}
--
-- main :: IO ()
-- main = do
-- let config = -- ...
-- withDependencies config \deps -> do
-- Context.setDefault depsStore deps
-- -- ...
--
setDefault :: forall m ctx. MonadIO m => Store ctx -> ctx -> m ()
-- | The PropagationStrategy controls the behavior used by
-- Context.Concurrent when propagating context from a "parent"
-- thread to a new thread.
data PropagationStrategy
-- | The default PropagationStrategy. For any Store
-- initialized with this PropagationStrategy,
-- Context.Concurrent will automatically propagate the "parent"
-- thread's latest context value from this Store so that that
-- context is accessible in a newly-created thread.
defaultPropagation :: PropagationStrategy
-- | This PropagationStrategy does no propagation whatsoever. For
-- any Store initialized with this PropagationStrategy,
-- Context.Concurrent will not propagate the "parent"
-- thread's context values from this Store in any way to the
-- newly-created thread.
noPropagation :: PropagationStrategy
module Context.View
-- | A View provides a read-only view into a Store.
-- View trades the Store ability to register new context
-- for the ability to arbitrarily transform context values locally to the
-- View.
data View ctx
-- | Provide the calling thread a view of its current context from the
-- specified View. Throws a NotFoundException when the
-- calling thread has no registered context.
view :: (MonadIO m, MonadThrow m) => View ctx -> m ctx
-- | Provide the calling thread a view of its current context from the
-- specified View, if present.
viewMay :: MonadIO m => View ctx -> m (Maybe ctx)
-- | Create a View from the provided Store.
toView :: Store ctx -> View ctx
module Context
-- | Opaque type that manages thread-indexed storage of context values.
data Store ctx
-- | Provides a new, non-empty Store that uses the specified context
-- value as a default when the calling thread has no registered context.
-- mine, mines, and adjust are guaranteed to never
-- throw NotFoundException when applied to a non-empty
-- Store.
withNonEmptyStore :: forall m ctx a. (MonadIO m, MonadMask m) => ctx -> (Store ctx -> m a) -> m a
-- | Provides a new, empty Store. mine, mines, and
-- adjust will throw NotFoundException when the calling
-- thread has no registered context. Useful when the Store will
-- contain context values that are always thread-specific.
withEmptyStore :: forall m ctx a. (MonadIO m, MonadMask m) => (Store ctx -> m a) -> m a
-- | Register a context in the specified Store on behalf of the
-- calling thread, for the duration of the specified action.
use :: forall m ctx a. (MonadIO m, MonadMask m) => Store ctx -> ctx -> m a -> m a
-- | Adjust the calling thread's context in the specified Store for
-- the duration of the specified action. Throws a
-- NotFoundException when the calling thread has no registered
-- context.
adjust :: forall m ctx a. (MonadIO m, MonadMask m) => Store ctx -> (ctx -> ctx) -> m a -> m a
-- | Convenience function to adjust the context then supply the
-- adjusted context to the inner action. This function is equivalent to
-- calling adjust and then immediately calling mine in the
-- inner action of adjust, e.g.:
--
-- -- doStuff :: Store Thing -> (Thing -> Thing) -> IO () -- doStuff store f = do -- adjust store f do -- adjustedThing <- mine store -- ... ---- -- Throws a NotFoundException when the calling thread has no -- registered context. withAdjusted :: forall m ctx a. (MonadIO m, MonadMask m) => Store ctx -> (ctx -> ctx) -> (ctx -> m a) -> m a -- | Provide the calling thread its current context from the specified -- Store. Throws a NotFoundException when the calling -- thread has no registered context. mine :: forall m ctx. (MonadIO m, MonadThrow m) => Store ctx -> m ctx -- | Provide the calling thread a selection from its current context in the -- specified Store. Throws a NotFoundException when the -- calling thread has no registered context. mines :: forall m ctx a. (MonadIO m, MonadThrow m) => Store ctx -> (ctx -> a) -> m a -- | Provide the calling thread its current context from the specified -- Store, if present. mineMay :: forall m ctx. MonadIO m => Store ctx -> m (Maybe ctx) -- | Provide the calling thread a selection from its current context in the -- specified Store, if present. minesMay :: forall m ctx a. MonadIO m => Store ctx -> (ctx -> a) -> m (Maybe a) -- | An exception which may be thrown when the calling thread does not have -- a registered context. data NotFoundException NotFoundException :: ThreadId -> NotFoundException [$sel:threadId:NotFoundException] :: NotFoundException -> ThreadId module Context.Implicit -- | Opaque type that manages thread-indexed storage of context values. data Store ctx -- | Provides a new, non-empty Store that uses the specified context -- value as a default when the calling thread has no registered context. -- mine, mines, and adjust are guaranteed to never -- throw NotFoundException when applied to a non-empty -- Store. withNonEmptyStore :: forall m ctx a. (MonadIO m, MonadMask m) => ctx -> (Store ctx -> m a) -> m a -- | Provides a new, empty Store. mine, mines, and -- adjust will throw NotFoundException when the calling -- thread has no registered context. Useful when the Store will -- contain context values that are always thread-specific. withEmptyStore :: forall m ctx a. (MonadIO m, MonadMask m) => (Store ctx -> m a) -> m a -- | Register a context in the implicit Store on behalf of the -- calling thread, for the duration of the specified action. use :: forall m ctx a. (MonadIO m, MonadMask m, ?contextStore :: Store ctx) => ctx -> m a -> m a -- | Adjust the calling thread's context in the implicit Store for -- the duration of the specified action. Throws a -- NotFoundException when the calling thread has no registered -- context. adjust :: forall m ctx a. (MonadIO m, MonadMask m, ?contextStore :: Store ctx) => (ctx -> ctx) -> m a -> m a -- | Convenience function to adjust the context then supply the -- adjusted context to the inner action. This function is equivalent to -- calling adjust and then immediately calling mine in the -- inner action of adjust, e.g.: -- --
-- doStuff :: Store Thing -> (Thing -> Thing) -> IO () -- doStuff store f = do -- adjust store f do -- adjustedThing <- mine store -- ... ---- -- Throws a NotFoundException when the calling thread has no -- registered context. withAdjusted :: forall m ctx a. (MonadIO m, MonadMask m, ?contextStore :: Store ctx) => (ctx -> ctx) -> (ctx -> m a) -> m a -- | Provide the calling thread its current context from the implicit -- Store. Throws a NotFoundException when the calling -- thread has no registered context. mine :: forall m ctx. (MonadIO m, MonadThrow m, ?contextStore :: Store ctx) => m ctx -- | Provide the calling thread a selection from its current context in the -- implicit Store. Throws a NotFoundException when the -- calling thread has no registered context. mines :: forall m ctx a. (MonadIO m, MonadThrow m, ?contextStore :: Store ctx) => (ctx -> a) -> m a -- | Provide the calling thread its current context from the implicit -- Store, if present. mineMay :: forall m ctx. (MonadIO m, ?contextStore :: Store ctx) => m (Maybe ctx) -- | Provide the calling thread a selection from its current context in the -- implicit Store, if present. minesMay :: forall m ctx a. (MonadIO m, ?contextStore :: Store ctx) => (ctx -> a) -> m (Maybe a) -- | An exception which may be thrown when the calling thread does not have -- a registered context. data NotFoundException NotFoundException :: ThreadId -> NotFoundException [$sel:threadId:NotFoundException] :: NotFoundException -> ThreadId