12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485(* Writer-mutex + reader-counter built on Lwt_condition.
Semantics (intentionally NOT a classic shared/exclusive lock):
- Many readers run concurrently and never block.
- Writers serialise against other writers via [writer_active].
- Readers do NOT block writers. Writers do NOT block readers.
Rationale for #149: snapshot isolation makes reader/writer
concurrency safe at the pager layer — the writer's dirty bytes and
uncommitted WAL frames are invisible to a snapshot bounded by
[committed_frames]. So the lock only needs to:
(a) serialise concurrent writers, and
(b) track active readers for the checkpoint coordinator (which
lives in [Store] — see [active_reader_frames]). *)openLwt.Syntaxtypet={mutablereaders:int;mutablewriter_active:bool;mutablewriters_waiting:int;cond:unitLwt_condition.t}letcreate()={readers=0;writer_active=false;writers_waiting=0;cond=Lwt_condition.create()};;letreaderst=t.readersletwriter_pendingt=t.writer_active||t.writers_waiting>0letwriter_activet=t.writer_active(* Readers never wait — the snapshot-isolation work upstream makes
concurrent reader/writer access safe at the data layer. *)letacquire_readt=t.readers<-t.readers+1;Lwt.return_unit;;letrelease_readt=t.readers<-t.readers-1;ift.readers=0thenLwt_condition.broadcastt.cond();;(* Writers wait only on other writers, not on readers. The decrement
of [writers_waiting] and the recursive re-check are atomic w.r.t.
the cooperative Lwt scheduler. *)letrecacquire_writet=ift.writer_activethen(t.writers_waiting<-t.writers_waiting+1;let*()=Lwt_condition.waitt.condint.writers_waiting<-t.writers_waiting-1;acquire_writet)else(t.writer_active<-true;Lwt.return_unit);;letrelease_writet=t.writer_active<-false;Lwt_condition.broadcastt.cond();;letwith_readtf=let*()=acquire_readtinLwt.finalizef(fun()->release_readt;Lwt.return_unit);;letwith_writetf=let*()=acquire_writetinLwt.finalizef(fun()->release_writet;Lwt.return_unit);;[@@@ai_disclosure"ai-generated"][@@@ai_model"claude-opus-4-7"][@@@ai_provider"Anthropic"]