Mutex v1.0.0 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

Types

A key can be any term

The name of a mutex is an atom, registered with Process.register/2

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

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

Link to this type key()
key() :: any

A key can be any term.

Link to this type name()
name() :: atom

The name of a mutex is an atom, registered with Process.register/2

Link to this section Functions

Link to this function await(mutex, key, timeout \\ 5000)
await(mutex :: name, key :: key, timeout :: timeout) :: {:ok, 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.

Link to this function await_all(mutex, keys)
await_all(mutex :: name, keys :: [key]) :: {:ok, 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.

Link to this function child_spec(name)
child_spec(name :: name) :: Supervisor.Spec.spec

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.

Link to this function goodbye(mutex)
goodbye(mutex :: name) :: :ok

Tells the mutex to release all the keys owned by the calling process and returns immediately with :ok.

Link to this function lock(mutex, key)
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}.

Link to this function lock!(mutex, key)
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.

Link to this function release(mutex, lock)
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.

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.

Link to this function start_link(opts \\ [])
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.

Link to this function under(mutex, key, timeout \\ :infinity, fun)
under(mutex :: name, key :: key, timeout :: timeout, fun :: (() -> any)) :: :ok

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.

Link to this function under_all(mutex, keys, fun)
under_all(mutex :: name, keys :: [key], fun :: (() -> any)) :: :ok

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.