Safe Haskell | Safe |
---|---|
Language | Haskell2010 |
Synopsis
- data ConcurrentResourceMap m v
- class ResourceMap m where
- newResourceMap :: ResourceMap m => IO (ConcurrentResourceMap m r)
- withInitialisedResource :: ResourceMap m => ConcurrentResourceMap m r -> Key m -> (r -> IO ()) -> (Maybe r -> IO a) -> IO a
- withSharedResource :: ResourceMap m => ConcurrentResourceMap m r -> Key m -> IO r -> (r -> IO ()) -> (r -> IO a) -> IO a
Documentation
data ConcurrentResourceMap m v Source #
A map of shared resources r
keyed by k
.
class ResourceMap m where Source #
Resource maps should implement this small set of operations that we expect maps to have.
This allows you to use whatever fast underlying map type you'd like, depending on your resources.
newResourceMap :: ResourceMap m => IO (ConcurrentResourceMap m r) Source #
Create an empty resource map.
withInitialisedResource Source #
:: ResourceMap m | |
=> ConcurrentResourceMap m r | Resource map. Create with |
-> Key m | Key for the resource. This allows you to have many of the same type of resource but separated: for example, one group of threads could be holding onto a logging handle to syslog while another could be holding a handle to a file. |
-> (r -> IO ()) | Destroy the resource if it was initialised. Ran by last alive user when it's exiting. Unlike initialisation, this _is_ ran in masked context. If this action fails (by throwing an exception itself), the resource will be assumed to be uninitialised and the exception will be re-thrown. Therefore, if your cleanup can fail in a way that you have to
know about/recover from, you should catch exceptions coming out
out |
-> (Maybe r -> IO a) | Run an action with the resource. Note that the availability of
this resource only ensures that the user-given
initialisers/destructors have been ran appropriate number of
times: it of course makes no guarantees as to what the resource
represents. For example, if it's a |
-> IO a |
This is like withSharedResource
but will only execute the user
action if the resource already exists. This is useful if you create
your resources in one place but would like to use them
conditionally in another place if they are still alive.
Action is given Nothing if the resource does not exist or is not initialised.
:: ResourceMap m | |
=> ConcurrentResourceMap m r | Resource map. Create with |
-> Key m | Key for the resource. This allows you to have many of the same type of resource but separated: for example, one group of threads could be holding onto a logging handle to syslog while another could be holding a handle to a file. |
-> IO r | Initialise resource. Only ran if the resource is not yet
initialised. Does not run in masked context so if you need to
stop async exceptions, you should use |
-> (r -> IO ()) | Destroy the resource if it was initialised. Ran by last alive user when it's exiting. Unlike initialisation, this _is_ ran in masked context. If this action fails (by throwing an exception itself), the resource will be assumed to be uninitialised and the exception will be re-thrown. Therefore, if your cleanup can fail in a way that you have to
know about/recover from, you should catch exceptions coming out
out |
-> (r -> IO a) | Run an action with the initialised resource. Note that the
availability of this resource only ensures that the user-given
initialisers/destructors have been ran appropriate number of
times: it of course makes no guarantees as to what the resource
represents. For example, if it's a |
-> IO a |
Use a resource that can be accessed concurrently via multiple threads but is only initialised and destroyed on as-needed basis. If number of users falls to 0, the resource is destroyed. If a new user joins and resource is not available, it's created.
Calls to withSharedResource
can even be nested if you need access
to resources with different keys in the same map. Calling
withSharedResource
in a nested matter on same resource key should
have no real adverse effects either.