View Source Mutex (Mutex v2.0.0)
This is the main module in this application, it implements a mutex as a GenServer with a notification system to be able to await lock releases.
See README.md
for how to use.
Summary
Functions
Locks a key if it is available, or waits for the key to be freed before attempting again to lock it.
Awaits multiple keys at once. Returns once all the keys have been locked,
timeout is :infinity
.
Returns a specification to start this module under a supervisor.
Fetch the metadata of the mutex.
Tells the mutex to release all the keys owned by the calling process and
returns immediately with :ok
.
Callback implementation for GenServer.init/1
.
Attemps to lock a resource on the mutex and returns immediately with the
result, which is either a Mutex.Lock
structure or {:error, :busy}
.
Attemps to lock a resource on the mutex and returns immediately with the lock or raises an exception if the key is already locked.
Tells the mutex to free the given lock and immediately returns :ok
without
waiting for the actual release.
If the calling process is not the owner of the key(s), the key(s) is/are
not released and an error is logged.
Starts a mutex with no process linking. Given options are passed as options
for a GenServer
, it's a good place to set the name for registering the
process.
Starts a mutex with linking under a supervision tree. Given options are passed
as options for a GenServer
, it's a good place to set the name for
registering the process.
Awaits a lock for the given key, executes the given fun and releases the lock immediately.
Awaits a lock for the given keys, executes the given fun and releases the lock immediately.
Types
@type key() :: any()
A key can be any term.
@type name() :: atom()
The name of a mutex is an atom, registered with Process.register/2
Functions
@spec await(mutex :: name(), key :: key(), timeout :: timeout()) :: Mutex.Lock.t()
Locks a key if it is available, or waits for the key to be freed before attempting again to lock it.
Returns the lock or fails with a timeout.
Due to the notification system, multiple attempts can be made to lock if multiple processes are competing for the key.
So timeout will be at least for the passed amount of milliseconds, but may be slightly longer.
Default timeout is 5000
milliseconds. If the timeout is reached, the caller
process exists as in GenServer.call/3
.
More information in the timeouts
section.
@spec await_all(mutex :: name(), keys :: [key()]) :: Mutex.Lock.t()
Awaits multiple keys at once. Returns once all the keys have been locked,
timeout is :infinity
.
If two processes are trying to lock [:user_1, :user_2]
and
[:user_2, :user_3]
at the same time, this function ensures that no deadlock
can happen and that one process will eventually lock all the keys.
More information at the end of the deadlocks section.
Returns a specification to start this module under a supervisor.
See Supervisor
.
Fetch the metadata of the mutex.
@spec goodbye(mutex :: name()) :: :ok
Tells the mutex to release all the keys owned by the calling process and
returns immediately with :ok
.
Callback implementation for GenServer.init/1
.
@spec lock(name :: name(), key :: key()) :: {:ok, Mutex.Lock.t()} | {:error, :busy}
Attemps to lock a resource on the mutex and returns immediately with the
result, which is either a Mutex.Lock
structure or {:error, :busy}
.
@spec lock!(name :: name(), key :: key()) :: Mutex.Lock.t()
Attemps to lock a resource on the mutex and returns immediately with the lock or raises an exception if the key is already locked.
@spec release(mutex :: name(), lock :: Mutex.Lock.t()) :: :ok
Tells the mutex to free the given lock and immediately returns :ok
without
waiting for the actual release.
If the calling process is not the owner of the key(s), the key(s) is/are
not released and an error is logged.
@spec start(opts :: Keyword.t()) :: GenServer.on_start()
Starts a mutex with no process linking. Given options are passed as options
for a GenServer
, it's a good place to set the name for registering the
process.
See GenServer
options.
A :meta
key can also be given in options to set the mutex metadata.
@spec start_link(opts :: Keyword.t()) :: GenServer.on_start()
Starts a mutex with linking under a supervision tree. Given options are passed
as options for a GenServer
, it's a good place to set the name for
registering the process.
See GenServer
options.
A :meta
key can also be given in options to set the mutex metadata.
@spec under( mutex :: name(), key :: key(), timeout :: timeout(), fun :: (-> any()) | (Mutex.Lock.t() -> any()) ) :: any()
Awaits a lock for the given key, executes the given fun and releases the lock immediately.
If an exeption is raised or thrown in the fun, the lock is automatically released.
If a function of arity 1 is given, it will be passed the lock. Otherwise the arity must be 0. You should not manually release the lock within the function.
@spec under_all( mutex :: name(), keys :: [key()], fun :: (-> any()) | (Mutex.Lock.t() -> any()) ) :: any()
Awaits a lock for the given keys, executes the given fun and releases the lock immediately.
If an exeption is raised or thrown in the fun, the lock is automatically released.
If a function of arity 1 is given, it will be passed the lock. Otherwise the arity must be 0. You should not manually release the lock within the function.