Skip to content

lockfree/smr/nebr/typestates/retire

Retire typestate for adding objects to limbo bags.

Must be pinned to retire objects.

  • retire is sink-form: it consumes RetireReady[MT] and returns Retired[MT]. To retire multiple objects in the same pinned epoch, convert back with retireReadyFromRetired. The var-form wrappers in debra/convenience (retire, retireBatch) handle this for you.
  • The pointer/destructor pair handed to retire(p, dtor) is captured into the limbo bag immediately. The destructor closure must remain valid until reclamation runs (Destructor is a nimcall proc, so a top-level proc or releaseDestructor[T]() result is fine).
  • Retiring the same pointer twice from different threads (or the same thread across multiple pin cycles) double-frees on reclamation. The library does not deduplicate.
  • debra + scope.retireOnCAS / scope.retireOnPublish (or retireReady(scope.state).retire(...)) - the recommended path.
  • debra - eventual reclamation after epoch safety.
RetireContext[MaxThreads; CC] = object of RootObj
handle*: ThreadHandle[MaxThreads, CC]
epoch*: uint64
RetireReady[MaxThreads; CC] = distinct RetireContext[MaxThreads, CC]
Retired[MaxThreads; CC] = distinct RetireContext[MaxThreads, CC]
RetireContextState = enum
fsRetireReady, fsRetired
RetireContextStates[MaxThreads; CC] = RetireReady[MaxThreads, CC] |
Retired[MaxThreads, CC]
proc state[MaxThreads: static int; CC: static PinScopeCardinality = ccSingle](
f: RetireReady[MaxThreads, CC]): RetireContextState

Runtime state inspection for RetireReady. Returns the enum value for pattern matching in case expressions.

proc state[MaxThreads: static int; CC: static PinScopeCardinality = ccSingle](
f: Retired[MaxThreads, CC]): RetireContextState

Runtime state inspection for Retired. Returns the enum value for pattern matching in case expressions.

$

proc `$`[MaxThreads: static int; CC: static PinScopeCardinality = ccSingle](
s: RetireReady[MaxThreads, CC]): string

String representation for state ‘RetireReady’. Returns the bare state name (no fs prefix).

proc `$`[MaxThreads: static int; CC: static PinScopeCardinality = ccSingle](
s: Retired[MaxThreads, CC]): string

String representation for state ‘Retired’. Returns the bare state name (no fs prefix).

proc `$`(s: RetireContextState): string {.raises: [], tags: [], forbids: [].}

String representation of RetireContextState enum. Strips the fs prefix for human-friendly output.

proc `=copy`[MaxThreads: static int; CC: static PinScopeCardinality = ccSingle](
dest: var RetireReady[MaxThreads, CC]; src: RetireReady[MaxThreads, CC]) {.error: "State \'RetireReady\' cannot be copied. Transitions consume the input state.".}
proc `=copy`[MaxThreads: static int; CC: static PinScopeCardinality = ccSingle](
dest: var Retired[MaxThreads, CC]; src: Retired[MaxThreads, CC]) {.error: "State \'Retired\' cannot be copied. Transitions consume the input state.".}
proc retireReady[MaxThreads: static int; CC: static PinScopeCardinality](
p: Pinned[MaxThreads, CC]): RetireReady[MaxThreads, CC]

Create retire context from pinned state.

proc retireReadyFromRetired[MaxThreads: static int;
CC: static PinScopeCardinality](
r: sink Retired[MaxThreads, CC]): RetireReady[MaxThreads, CC] {.
notATransition.}

Get back to RetireReady after retiring (for multiple retires).

proc pinnedFromRetired[MaxThreads: static int; CC: static PinScopeCardinality](
r: sink Retired[MaxThreads, CC]): Pinned[MaxThreads, CC] {.notATransition.}

Return a Pinned[MaxThreads, CC] reconstructed from a Retired[MaxThreads, CC] value, allowing the caller to keep working in the same pinned epoch (e.g. interleaving reads with further retires) instead of unpinning immediately after a retire.

Symmetric to retireReadyFromRetired: same underlying RetireContext[MaxThreads, CC], projected to the Pinned typestate via the EpochGuardContext[MaxThreads, CC] shape (handle + epoch). The slot's pinned flag is unchanged; this is a typestate rebrand, not a re-pin.

See also: retireReadyFromRetired, retire, debra.

proc retire[MaxThreads: static int; CC: static PinScopeCardinality](
r: sink RetireReady[MaxThreads, CC]; p: pointer; destructor: Destructor): Retired[
MaxThreads, CC] {.raises: [], tags: [TypestateOp, RootEffect].}

Retire a raw pointer for epoch-based reclamation.

The destructor will be called when the epoch becomes safe. Use for manually-managed memory (ptr types, alloc/dealloc, etc.)

func handle[MaxThreads: static int; CC: static PinScopeCardinality](
r: RetireReady[MaxThreads, CC]): ThreadHandle[MaxThreads, CC] {.
notATransition.}
macro match[MaxThreads: static int; CC: static PinScopeCardinality = ccSingle](
value: RetireContextStates[MaxThreads, CC]; arms: untyped): untyped

Single-target pattern match on states of typestate ‘RetireContext’; rewrites to block: let bind = move(value); body. Syntax is <StateName>(bind):, with exactly one arm.