# RWlock
[](https://hexdocs.pm/rwlock/)
A 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 `:queue` structure
* 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`:
```elixir
def deps do
[
{:rwlock, "~> 0.1.1"}
]
end
```
This library implements a RW Locking as a process that you would generally start
under a supervision tree.
```elixir
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
end
```
## Example
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)
:ok
## Lock 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](./LICENSE) file for more details.