Skip to content

Getting Started

This guide walks through setting up and using nim-debra in your lock-free data structures.

Installation

Add nim-debra to your .nimble file:

requires "debra >= 0.3.0"

Or install globally:

nimble install debra

Basic Usage

The following example demonstrates the complete DEBRA+ lifecycle:

  1. Initialize the manager
  2. Register the thread
  3. Pin/unpin critical sections
  4. Retire objects for later reclamation
  5. Periodically reclaim memory
# examples/basic_usage.nim
## Basic DEBRA+ usage: initialize manager, register thread, pin/retire/unpin,
## reclaim. Single-threaded, no atomic field — just the lifecycle.

import debra

type
  NodeObj = object
    value: int

  Node = ref NodeObj

# One pin/retire/unpin cycle.
proc doCycle(handle: ThreadHandle[4], value: int) =
  let u = unpinned(handle)
  let pinned = u.pin()

  # Retain the ref so it survives until DEBRA reclaims it. `retain` returns
  # a raw `ptr NodeObj`; the matching `releaseDestructor[NodeObj](../../examples)` runs
  # GC_unref at reclamation time.
  let node = retain Node(value: value)

  # Retire the node for later reclamation.
  let ready = retireReady(pinned)
  discard ready.retire(cast[pointer](../../examples/node), releaseDestructor[NodeObj](../../examples))

  # Exit critical section. The unpin path may report a neutralization
  # (a stalled-thread escalation); acknowledge if so.
  let unpinResult = pinned.unpin()
  case unpinResult.kind
  of uUnpinned:
    discard
  of uNeutralized:
    discard unpinResult.neutralized.acknowledge()

proc main() =
  # 1. Initialize manager (supports up to 4 threads)
  var manager = initDebraManager[4](../../examples)
  setGlobalManager(addr manager)

  # 2. Register this thread
  let handle = registerThread(manager)

  # 3. Simulate some operations
  for i in 0 ..< 10:
    doCycle(handle, i)

    # Advance epoch periodically
    if i mod 3 == 0:
      manager.advance()

  # 4. Attempt reclamation
  let reclaimResult = reclaimStart(addr manager).loadEpochs().checkSafe()

  case reclaimResult.kind
  of rReclaimReady:
    let count = reclaimResult.reclaimready.tryReclaim()
    echo "Reclaimed ", count, " objects"
  of rReclaimBlocked:
    echo "Reclamation blocked (normal at startup)"

  echo "Basic usage example completed successfully"

when isMainModule:
  main()

View full source

Key Concepts

  • Manager: Coordinates epoch-based reclamation across threads
  • Handle: Per-thread registration for DEBRA operations
  • Pin/Unpin: Mark critical sections where shared data is accessed
  • retain[T]: GC-pin a ref T and return a raw ptr T suitable for atomic storage (debra/refptr)
  • releaseDestructor[T](): Return a captureless Destructor function pointer that pairs the retain at reclamation time
  • Retire: Mark a removed pointer (and its destructor) for later safe reclamation
  • Reclaim: Run pending destructors once all threads have advanced past the retiring epoch

Next Steps