Skip to main content

Module locks

Module locks 

Source
Expand description

v7.37.15 (Phase C.4) — row-level lock table, the four PG tuple-lock modes, and wait-for deadlock detection.

§Why this exists

Phase C’s in-place write path (C.3) lets concurrent transactions update / delete different rows without blocking. But two writers that touch the SAME row must serialise, and a SELECT ... FOR UPDATE must be able to reserve rows ahead of the write. This module is the lock table that arbitrates: it keys locks on the stable (RelId, RowId) identity (Phase C.1) so a held lock keeps naming the same row across concurrent compaction.

§Additive at this commit

Pure no_std logic with no consumer yet: the write path (C.3/C.4) calls acquire / release_all, and the host (spg-server, thread-per-connection) parks a waiting thread behind a Parker informed by LockOutcome::WouldBlock. The engine core only records the wait-for edges and runs the cycle detector — keeping it no_std (no thread primitives leak into the core). Under today’s single external engine lock the table is mutated serially; the sharded lock-free version is Phase C.5.

§The four modes and their conflicts

Mirrors PG’s tuple-lock strengths (weakest → strongest): KeyShare < Share < NoKeyUpdate < Exclusive. The load-bearing compatibility is KeyShare ∥ NoKeyUpdate: an FK existence check (FOR KEY SHARE) runs concurrently with a non-key UPDATE (NoKeyUpdate) on the same parent row — a real concurrency win we match, not a coincidence.

Structs§

LockTable
The row-lock table. Keyed on stable (RelId, RowId); carries the wait-for graph used for deadlock detection.

Enums§

LockMode
A PG tuple-lock strength. FOR KEY SHARE / FOR SHARE / FOR NO KEY UPDATE / FOR UPDATE, plus the implicit modes a write takes: a key-touching UPDATE or any DELETE takes Exclusive; a non-key UPDATE takes NoKeyUpdate.
LockOutcome
The result of an LockTable::acquire attempt.
WaitPolicy
What a caller wants to happen when the lock it requests is not immediately available. Mirrors PG’s LockWaitPolicy.