Mutex v1.0.2 Mutex
This is the only 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.
Link to this section 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 child specification to integrate the mutex in a supervision tree. The passed name is an atom, it will be the registered name for the mutex
Tells the mutex to release all the keys owned by the calling process and
returns immediately with :ok
Invoked when the server is started. start_link/3 or start/3 will
block until it returns
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
Link to this section Types
A key can be any term.
The name of a mutex is an atom, registered with Process.register/2
Link to this section Functions
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.
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 child specification to integrate the mutex in a supervision tree. The passed name is an atom, it will be the registered name for the mutex.
Tells the mutex to release all the keys owned by the calling process and
returns immediately with :ok.
Invoked when the server is started. start_link/3 or start/3 will
block until it returns.
args is the argument term (second argument) passed to start_link/3.
Returning {:ok, state} will cause start_link/3 to return
{:ok, pid} and the process to enter its loop.
Returning {:ok, state, timeout} is similar to {:ok, state}
except handle_info(:timeout, state) will be called after timeout
milliseconds if no messages are received within the timeout.
Returning {:ok, state, :hibernate} is similar to
{:ok, state} except the process is hibernated before entering the loop. See
c:handle_call/3 for more information on hibernation.
Returning :ignore will cause start_link/3 to return :ignore and the
process will exit normally without entering the loop or calling c:terminate/2.
If used when part of a supervision tree the parent supervisor will not fail
to start nor immediately try to restart the GenServer. The remainder of the
supervision tree will be (re)started and so the GenServer should not be
required by other processes. It can be started later with
Supervisor.restart_child/2 as the child specification is saved in the parent
supervisor. The main use cases for this are:
- The
GenServeris disabled by configuration but might be enabled later. - An error occurred and it will be handled by a different mechanism than the
Supervisor. Likely this approach involves callingSupervisor.restart_child/2after a delay to attempt a restart.
Returning {:stop, reason} will cause start_link/3 to return
{:error, reason} and the process to exit with reason reason without
entering the loop or calling c:terminate/2.
Callback implementation for GenServer.init/1.
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}.
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.
start_link(opts :: GenServer.options) :: 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.
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.
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.