RWlock
View SourceA concurrent Readers/Writer lock implementation built on GenServer.
RWLock allows multiple readers to acquire a shared (:sh_lock) lock
simultaneously, while ensuring that only one writer (:ex_lock) can hold
an exclusive lock at any given time.
This module manages lock ownership across processes and ensures correct
coordination between readers and writers for a given resource key (referred to as on).
Features
- Multiple readers can hold a lock concurrently (
sh_lock) - Only one writer can hold a lock exclusively (
ex_lock) - Fair queueing via an internal
:queuestructure - Lock ownership tracking via process identifiers
- Automatic wake-up of waiting processes when a lock is released
Installation
The package can be installed by adding rwlock to your list of dependencies in mix.exs:
def deps do
[
{:rwlock, "~> 0.1.1"}
]
endThis library implements a RW Locking as a process that you would generally start under a supervision tree.
defmodule MyApp.Application do
@moduledoc false
use Application
@impl true
def start(_type, _args) do
children = [
{RWLock, name: MyApp.RWLock}
]
Supervisor.start_link(children, strategy: :one_for_one)
end
endExample
iex> RWLock.start_link()
iex> RWLock.sh_lock(:any_term1)
:ok
iex> RWLock.sh_lock(:any_term1)
:ok
iex> RWLock.ex_lock(:any_term2)
:ok
iex> RWLock.unlock(:any_term1)
:ok
iex> RWLock.unlock(:any_term1)
:ok
iex> RWLock.unlock(:any_term2)
:okLock Structure
Internally, each lock entry is a map with these keys:
%{
locked?: boolean(),
type: :ex | :sh | nil,
readers: MapSet.t(),
wlist: :queue.t(),
on: any()
}This structure is maintained per on key in the GenServer’s state.
Copyright and License
Copyright (c) 2025, Hamad Al Marri
This work is free. You can redistribute it and/or modify it under the terms of the MIT License. See the LICENSE file for more details.