Reader-Writer & Resource Lifecycle Locks
CAS-only, allocation-free spin-locks every concurrent engine structure embeds for shared/exclusive or lifecycle access.
Status: โ Implemented ยท Visibility: Internal ยท Category: Foundation
๐ฏ What it solves
Typhon's microsecond-level latency targets rule out OS-level synchronization (mutexes, semaphores, ReaderWriterLockSlim) for the thousands of small, short-lived locks the engine needs โ page latches, B+Tree node locks, component-table guards, transaction-pool locks. Three purpose-built lock shapes cover the recurring access patterns the engine actually needs โ general reader/writer, a compact reader/writer for high-density embedding, and a three-mode lifecycle lock for structures that grow while being read โ without the cost of kernel objects or heap allocation.
โ๏ธ How it works (in brief)
All three pack their entire state into a single atomic word (8, 4, and 4 bytes respectively) and transition exclusively via Interlocked.CompareExchange โ no wait queues, no kernel handles, no managed allocation. Contention spins via .NET's SpinWait (busy-spin โ yield โ sleep) and never parks a thread. Every blocking entry point takes a ref WaitContext (monotonic deadline + CancellationToken); pass ref WaitContext.Null for an infinite, zero-overhead wait. Picking the right one is a tradeoff between memory footprint, waiter fairness, and access semantics โ see the sub-features below.
Sub-features
| Sub-feature | Size | Use it when... |
|---|---|---|
| AccessControl | 8 bytes | Few instances, many threads, writer starvation under read pressure is unacceptable |
| AccessControlSmall | 4 bytes | Thousands of instances embedded per-node/per-page, fairness isn't needed |
| ResourceAccessControl | 4 bytes | Structural growth must not block concurrent readers; destruction must drain everything |
โ ๏ธ Guarantees & limits
- All three are
internalengine types โ application code never constructs or calls them directly; they're the plumbing insideComponentTable,TransactionChain, page latches, B+Tree nodes, segment chains, etc. - Thread IDs are stored in exactly 16 bits everywhere (max 65,535) โ consistent overflow headroom across the family, sized for 500+ core servers.
- Pure userspace spin-wait, never OS-level parking โ cheap for the engine's typical sub-microsecond hold times, wasteful if misused for long critical sections.
- No deadlock detection by design: correctness rests on Typhon's MVCC (no cross-transaction lock holding) and strict latch-coupling order in the B+Tree/R-Tree, not on runtime detection in these primitives.
- Contention surfaces through the profiler's trace-event stream (
TyphonEvent.Emit*, gated and JIT-eliminated when the profiler is off) โ not an opt-in callback interface.
๐งช Tests
- AccessControlTests โ full-featured RW lock: shared/exclusive/promote-demote, fairness under contention, deadline+cancellation wiring.
- AccessControlSmallTests โ compact RW lock: idle/shared/exclusive transitions, misuse-throws contract.
- ResourceAccessControlTests โ 3-mode Accessing/Modify/Destroy semantics,
MODIFY_PENDINGfairness, promote/demote.
๐ Related
- Sub-features: AccessControl, AccessControlSmall, ResourceAccessControl