Documentation
¶
Overview ¶
Package keyedlock holds one small primitive internal/session's Manager and internal/server's shellRegistry and terminalRegistry each need: a lazily-created, per-key mutex that serialises one key's whole check-then-act without blocking any other key's (kb:adr/actions-serialized-per-session). internal/session must never import internal/server (kb:diagram/daemon-components), so — like internal/boundedwait — the shared piece lives in its own leaf package, importing nothing internal itself.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Locks ¶
type Locks[K comparable] struct { // contains filtered or unexported fields }
Locks is a set of per-key mutexes, created on first use. The zero value is ready to use. Its own mu guards only the map itself (lookup/insert) — never a caller's actual work, which happens after Lock returns and before unlock is called.
func (*Locks[K]) Forget ¶
func (l *Locks[K]) Forget(key K)
Forget removes key's entry, so a later Lock(key) allocates a fresh *sync.Mutex rather than reusing the old one. That fresh mutex can start a second, independent holder of "key's lock" alongside anyone already queued on the mutex Forget just dropped — Forget itself does not prevent that. It's still safe to call once the resource key names is gone for good (e.g. a session id, never reissued, once its row is gone), provided every Lock(key) caller re-validates that the resource still exists once it actually holds the lock, whichever mutex it got: a caller racing a stale, client-supplied key then finds nothing there and stops, rather than acting through a resurrected lock. Reclaiming the entry is what keeps the map from growing for the life of the daemon; it never claims exclusivity beyond what each caller's own post-lock check enforces.