View Source Mutex (Mutex v3.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 usage instructions.

Summary

Types

A key can be any term.

Identifier for a mutex process.

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 a mutex under a supervisor.

Sets the the process identified by pid as the new owner of the lock.

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.

Releases the given lock synchronously.

Tells the mutex to free the given lock and immediately returns :ok without waiting for the actual release.

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 linked to the calling process.

Alias for with_lock/3.

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() :: GenServer.server()

Identifier for a mutex process.

Functions

Link to this function

await(mutex, key, timeout \\ 5000)

View Source
@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 exits 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 a mutex under a supervisor.

See the "Child specification" section in the Supervisor module for more detailed information.

Link to this function

give_away(mutex, lock, pid, gift_data \\ nil)

View Source (since 3.0.0)
@spec give_away(mutex :: name(), Mutex.Lock.t(), pid(), gift_data :: term()) :: :ok

Sets the the process identified by pid as the new owner of the lock.

If succesful, that new owner will be sent a {:"MUTEX-TRANSFER", from_pid, lock, gift_data} message. If it is not alive, the lock will be released.

This function only supports single key locks.

@spec goodbye(mutex :: name()) :: :ok

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

@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

Releases the given lock synchronously.

Link to this function

release_async(mutex, lock)

View Source

Tells the mutex to free the given lock and immediately returns :ok without waiting for the actual release.

Unlike release/2, this function will not raise if the calling process is not lock owner. In that case, the lock is not released and an error is logged.

Supports only single key locks.

@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 start_link/1 for options.

@spec start_link(opts :: Keyword.t()) :: GenServer.on_start()

Starts a mutex linked to the calling process.

Accepts only t:GenServer.options().

See GenServer options.

Link to this function

under(mutex, key, timeout \\ :infinity, fun)

View Source
This function is deprecated. use with_lock/4 instead.

Alias for with_lock/4.

Link to this function

under_all(mutex, key, fun)

View Source
This function is deprecated. use with_lock/3 instead.

Alias for with_lock/3.

Link to this function

with_lock(mutex, key, timeout \\ :infinity, fun)

View Source (since 3.0.0)
@spec with_lock(
  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.

Link to this function

with_lock_all(mutex, keys, fun)

View Source (since 3.0.0)
@spec with_lock_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.