thread-utils-context-0.2.0.0: Garbage-collected thread local storage
Safe HaskellNone
LanguageHaskell2010

Control.Concurrent.Thread.Storage

Description

A perilous implementation of thread-local storage for Haskell. This module uses a fair amount of GHC internals to enable performing lookups of context for any threads that are alive. Caution should be taken for consumers of this module to not retain ThreadId references indefinitely, as that could delay cleanup of thread-local state.

Thread-local contexts have the following semantics:

  • A value attached to a ThreadId will remain alive at least as long as the ThreadId.
  • A value may be detached from a ThreadId via detach by the library consumer without detriment.
  • No guarantees are made about when a value will be garbage-collected once all references to ThreadId have been dropped. However, this simply means in practice that any unused contexts will cleaned up upon the next garbage collection and may not be actively freed when the program exits.

Note: This library assumes that ThreadIds aren't reused before a finalizer runs to clean up the ThreadStorageMap, so quick thread churn of this nature.

Also note: This implementation of context sharing is mildly expensive (~40ns to attach a value) relative to using pure code / idiomatic things like MonadReader, hard to reason about without deep knowledge of threading in the code you are using, and has limited guarantees of behavior across GHC versions due to internals usage.

Synopsis

Create a ThreadStorageMap

data ThreadStorageMap a Source #

A storage mechanism for values of a type. This structure retains items on per-(green)thread basis, which can be useful in rare cases.

newThreadStorageMap :: MonadIO m => m (ThreadStorageMap a) Source #

Create a new thread storage map. The map is striped by thread into 32 sections in order to reduce contention.

Retrieve values from a ThreadStorageMap

lookup :: MonadIO m => ThreadStorageMap a -> m (Maybe a) Source #

Retrieve a value if it exists for the current thread

lookupOnThread :: MonadIO m => ThreadStorageMap a -> ThreadId -> m (Maybe a) Source #

Retrieve a value if it exists for the specified thread

Associate values with a thread in a ThreadStorageMap

attach :: MonadIO m => ThreadStorageMap a -> a -> m (Maybe a) Source #

Associate the provided value with the current thread

attachOnThread :: MonadIO m => ThreadStorageMap a -> ThreadId -> a -> m (Maybe a) Source #

Associate the provided value with the specified thread

Remove values from a thread in a ThreadStorageMap

detach :: MonadIO m => ThreadStorageMap a -> m (Maybe a) Source #

Disassociate the associated value from the current thread, returning it if it exists.

detachFromThread :: MonadIO m => ThreadStorageMap a -> ThreadId -> m (Maybe a) Source #

Disassociate the associated value from the specified thread, returning it if it exists.

Update values for a thread in a ThreadStorageMap

adjust :: MonadIO m => ThreadStorageMap a -> (a -> a) -> m () Source #

Update the associated value for the current thread if it is attached.

adjustOnThread :: MonadIO m => ThreadStorageMap a -> ThreadId -> (a -> a) -> m () Source #

Update the associated value for the specified thread if it is attached.

Monitoring utilities

storedItems :: ThreadStorageMap a -> IO [(Int, a)] Source #

List thread ids with live entries in the ThreadStorageMap.

This is useful for monitoring purposes to verify that there are no memory leaks retaining threads and thus preventing items from being freed from a ThreadStorageMap