Thread Registration¶
Understanding thread registration lifecycle in DEBRA+.
State Machine¶
Overview¶
Each thread must register with the DEBRA manager before performing pin/unpin operations. Registration allocates a thread slot and provides a handle for all subsequent operations.
Registration Process¶
Registration performs several steps:
- Search for an unused slot in the thread array
- Claim the slot by setting the thread ID
- Initialize the slot's epoch and flags
- Return a handle containing the slot index
Thread Limits¶
The manager is created with a compile-time maximum thread count:
Attempting to register more threads than the limit will raise DebraRegistrationError.
Multi-Thread Example¶
The following example demonstrates multiple threads registering and using DEBRA:
# examples/thread_registration.nim
## Thread registration lifecycle: multiple threads registering and using DEBRA.
import debra
import std/atomics
var manager: DebraManager[4]
proc workerThread() {.thread.} =
# Register this thread with the manager
let handle = registerThread(manager)
# Perform some pin/unpin cycles
for i in 0..<100:
let u = unpinned(handle)
let pinned = u.pin()
# Simulate work in critical section
discard
let unpinResult = pinned.unpin()
case unpinResult.kind:
of uUnpinned:
discard
of uNeutralized:
discard unpinResult.neutralized.acknowledge()
when isMainModule:
# Initialize manager
manager = initDebraManager[4](../../examples)
setGlobalManager(addr manager)
# Start worker threads
var threads: array[4, Thread[void]]
for i in 0..<4:
createThread(threads[i], workerThread)
# Wait for all threads to complete
for i in 0..<4:
joinThread(threads[i])
echo "Thread registration example completed successfully"
Per-Thread State¶
Each thread slot maintains:
- epoch: Current/pinned epoch
- pinned: Is thread in critical section?
- neutralized: Neutralization flag
- threadId: Thread identifier for signaling
- limboBags: Chain of retired objects
Best Practices¶
- Register once per thread: Don't register multiple times
- Keep handle alive: Store the handle for the thread's lifetime
- Don't share handles: Each thread needs its own handle
- Respect limits: Don't exceed MaxThreads parameter
Current Limitations¶
Thread Slot Lifetime¶
Thread slots are held for the thread's lifetime. Once a thread registers, its slot remains occupied until the manager is destroyed. There is currently no explicit deregistration API.
If a thread exits after registration, its slot remains allocated and cannot be reused until the entire manager shuts down. This means the effective thread limit is determined by the peak number of threads that register over the manager's lifetime, not the number of concurrent threads.
Implication: Plan your MaxThreads parameter based on the total number of threads that will register throughout your application's lifetime, not just the concurrent thread count.
Troubleshooting¶
"Maximum threads already registered"¶
All slots are occupied. Either:
- Increase
MaxThreadswhen creating the manager - Reduce the total number of threads that register over the application lifetime
- Check for thread leaks or unnecessary thread creation
Next Steps¶
- Learn about pin/unpin lifecycle
- Understand retiring objects