BQueue¶
Coming from lockfreequeues v5?
See From lockfreequeues v5 for the package rename, import path changes, and the static-thread-affinity endpoint API.
BQueue[T, ccProd, ccCons, N, P, C] is the unified bounded, lock-free
queue exposed by lockfree v0.1.0. A single generic type covers all four
producer/consumer cardinality combinations — SPSC, MPSC, SPMC, and
MPMC — selected at compile time through the ccProd and ccCons
parameters. It replaces the family-prefixed bounded types (Sipsic,
Sipmuc, Mupsic, Mupmuc) shipped by the predecessor package
lockfreequeues through v4.x; the consolidated umbrella lockfree
absorbs that surface verbatim under a single generic.
Overview¶
- Capacity: Fixed at compile time (
N) - Push: Wait-free (SPSC) or lock-free (multi-producer)
- Pop: Wait-free (SPSC) or lock-free (multi-consumer)
- No heap state: the bounded body owns no dynamic memory and needs no memory-reclamation manager. The default destructor is sufficient.
BQueue carries no debra integration and none of the unbounded
Queue's ST / S / MaxThreads axes. Internally it dispatches on
(ccProd, ccCons): the SPSC shape uses an N+1-slot ring with plain
Atomic[int] head/tail; every multi-cardinality shape uses a Vyukov
per-slot seq-counter cell array with Atomic[uint64] head/tail. The
sequence-counter protocol carries the producer→consumer and
consumer→next-producer happens-before edges without a separate
committed flag array.
Supported T¶
Per Path-C of the lockfree v0.1.0 element-type story, BQueue[T, …]
supports the full Nim type vocabulary, including ref T, string, and
seq[T], via the ManagedRef / ManagedSlice wrappers documented in
Managed Ref and
Managed Slice. Plain copyable T (POD,
fixed-size structs) flow through unmodified; GC-managed T flow
through the managed wrappers, which keep the lock-free fast path intact
while preserving ownership.
Type Parameters¶
T— Item typeccProd: static PinScopeCardinality— Producer cardinality (ccSingleorccMulti)ccCons: static PinScopeCardinality— Consumer cardinality (ccSingleorccMulti)N: static int— Queue capacity (must be> 0; power of 2 recommended)P: static int— Producer-registry capacity. Required> 0whenccProd == ccMulti; must be0whenccProd == ccSingle.C: static int— Consumer-registry capacity. Required> 0whenccCons == ccMulti; must be0whenccCons == ccSingle.
The parameter order is load-bearing: T, ccProd, ccCons, N, P, C.
Constructors¶
newBQueue[T, ccProd, ccCons, N, P, C]() is the canonical generic
smart constructor. Family-named thin wrappers are retained for
ergonomic continuity with the lockfreequeues v3.x/v4.x naming and to
minimize churn in downstream call sites migrating to lockfree v0.1.0;
all compile to the same BQueue type:
newSpscQueue[T, N]()—ccSingle × ccSingle(SPSC)newMpscQueue[T, N, P]()—ccMulti × ccSingle(MPSC)newSpmcQueue[T, N, C]()—ccSingle × ccMulti(SPMC)newMpmcQueue[T, N, P, C]()—ccMulti × ccMulti(MPMC)
Usage¶
import lockfree
# SPSC: single producer, single consumer, capacity 16.
# No handles needed — push/pop go directly on the queue.
var spsc = newSpscQueue[int, 16]()
discard spsc.push(42)
let a = spsc.pop() # some(42)
# MPMC: capacity 64, up to 4 producers and 4 consumers.
var mpmc = newBQueue[int, ccMulti, ccMulti, 64, 4, 4]()
var producer = mpmc.getProducer()
discard producer.bindToThread() # claim the view on this thread
discard producer.push(99)
var consumer = mpmc.getConsumer()
discard consumer.bindToThread()
let b = consumer.pop() # some(99)
# MPMC: when the calling thread is also the operating thread,
# `getProducerHere` / `getConsumerHere` are sugar for getX() + attach().
# Use the explicit form when handing the view off to a worker thread.
var mpmc2 = newBQueue[int, ccMulti, ccMulti, 64, 4, 4]()
var producer2 = mpmc2.getProducerHere()
discard producer2.push(99)
var consumer2 = mpmc2.getConsumerHere()
let c = consumer2.pop() # some(99)
Calling Convention by Cardinality¶
The single side of each axis operates directly on the queue; the multi
side requires a per-thread handle obtained from getProducer() /
getConsumer():
| Shape | Push | Pop |
|---|---|---|
| SPSC | queue.push(item) |
queue.pop() |
| MPSC | producer.push(item) |
queue.pop() |
| SPMC | queue.push(item) |
consumer.pop() |
| MPMC | producer.push(item) |
consumer.pop() |
Calling push directly on a multi-producer BQueue (or pop on a
multi-consumer BQueue) is a compile-time error — a {.error.}
overload directs the caller to BQueue.getProducer().push(item) /
BQueue.getConsumer().pop(). The diagnostic names only the
user-visible Bound[T, Tag, BQueue[...]] endpoint / Bound[T, Tag, BQueue[...]] endpoint aliases.
When all P producer slots are taken, getProducer() raises
NoProducersAvailableError; when all C consumer slots are taken,
getConsumer() raises NoConsumersAvailableError.
For the common same-thread case (the calling thread is also the
thread that will push/pop through the returned view),
getProducerHere() / getConsumerHere() are templates that combine
getX() + attach() in one call. Use the explicit
getX() + attach() pair when the view is handed off to a worker
thread that does the push/pop.
Typestate Notes¶
BQueue carries a Lifecycle typestate (BQueueInit -> BQueueDestroyed)
driven by =destroy; the per-thread Bound[T, Tag, BQueue[...]] endpoint / Bound[T, Tag, BQueue[...]] endpoint
views carry a Claim-state typestate (Unclaimed -> BothClaimed). All
push/pop/attach/detach operations are state-preserving and emit no
static transition; only the destructor moves a value to its terminal
state. Use-after-destroy is a documented limitation (typestates does
not statically catch a method call on an already-destroyed value); see
the lockfree CHANGELOG [0.1.0] entry for details.
See also¶
- Bounded Vyukov queues — the shared bounded protocol used across all four cardinalities.
- Managed Ref — Path-C wrapper for
ref T. - Managed Slice — Path-C wrapper for
stringandseq[T]. - Safety Model — happens-before guarantees
and the Vyukov per-slot
seqprotocol. - Slot Ownership Typestates — the shared internal state machine across all bounded shapes.
- Bounded vs Unbounded — choosing
between
BQueueandQueue.
bqueue
¶
Bounded lock-free queue — BQueue[T, ccProd, ccCons, N, P, C].
A 6-param bounded ring-buffer surface with no debra integration and
no ST/S/MaxThreads axes. Cardinality dispatch uses
when (ccProd, ccCons) is internally.
Param order is LOAD-BEARING: T, ccProd, ccCons, N, P, C.
No cross-import. bqueue.nim MUST NOT import ./queue (or
vice-versa). Shared helpers route through ./internal/shared. Any
helper added to internal/shared is available to both modules
without creating a backward dependency that would defeat the split.
Queueable[T] concept hookup. Bare
BQueue[T, ccSingle, ccSingle, ...] satisfies the Queueable[T]
concept defined in ./typestates/with_bound. Conformance is pinned
by static doAsserts in that module across the full Path-C-encoded
payload set (ref / string / seq / POD). No code change to this
module is required for concept conformance — the existing public
push / pop signatures on the SPSC arm already match the
concept's expected shape.
Field-layout invariant. Bounded queue bodies preserve the
offset prefix required by the typestate Base types (SpscBase,
MpscBase, SpmcBase, MpmcBase, *PushBase). The
static: offsetOf asserts below lock the prefix at canonical
instantiations so the unsafe casts in the push/pop bodies remain
sound. Object-field offsets are computed structurally, so a match
for one instantiation implies a match for all.
Cardinality dispatch ladder. The four (ccProd × ccCons) combos
are handled by when arms inside the procs, matching the layout
the legacy per-family files (spsc.nim / mpsc.nim /
spmc.nim / mpmc.nim) used pre-unification:
- ccSingle × ccSingle (SPSC): direct Queue.push / Queue.pop.
- ccMulti × ccSingle (MPSC): producer.push / direct pop.
- ccSingle × ccMulti (SPMC): direct push / consumer.pop.
- ccMulti × ccMulti (MPMC): producer.push / consumer.pop.
Multi-side direct-on-queue calls are gated by compile-time
{.error.} overloads — calling BQueue.push(item) on a
ccProd == ccMulti queue (or BQueue.pop() on ccCons == ccMulti)
fails at compile time with a message pointing the caller at
BQueue.getProducer().push(item) / BQueue.getConsumer().pop().
BQueueLifecycleCtx
¶
type BQueueLifecycleCtx[T; ccProd, ccCons: static PinScopeCardinality; N, P, C: static int] = object
Phantom context type for the BQueue Lifecycle typestate. Never
instantiated at runtime; carries the generic param shape so the
state types below can distinct from it.
BQueueInit
¶
type BQueueInit[T; ccProd, ccCons: static PinScopeCardinality; N, P, C: static int] = distinct BQueueLifecycleCtx[T, ccProd, ccCons, N, P, C]
Initial Lifecycle state for a BQueue. Every newly constructed
BQueue enters this state via the {.BQueueLifecycle: BQueueInit.}
attachment pragma on the BQueue object below.
BQueueDestroyed
¶
type BQueueDestroyed[T; ccProd, ccCons: static PinScopeCardinality; N, P, C: static int] = distinct BQueueLifecycleCtx[T, ccProd, ccCons, N, P, C]
Terminal Lifecycle state for a BQueue. Reached exclusively via
the BQueue =destroy destructor's destructorTransition.
validateBQueueParams ¶
proc validateBQueueParams(_: typedesc[BQueue[T, ccProd, ccCons, N, P, C]])
Compile-time entry point for BQueue's 4-5 param-coherence guards
(subset of ). Invoked implicitly by initBQueue;
callers may invoke explicitly to exercise the guards in isolation.
Has no runtime cost.
Parameters
-
_(typedesc[BQueue[T, ccProd, ccCons, N, P, C]])
initBQueue ¶
proc initBQueue(): BQueue[T, ccProd, ccCons, N, P, C]
Bounded-queue constructor. Initializes the slot storage, zeroes
head/tail, and clears any producer/consumer thread-id registry tables (multi-cardinality only).
initBQueue is the primitive that returns a freshly cleared
BQueue value. newBQueue is the canonical smart constructor and
forwards verbatim — callers should prefer newBQueue.
Returns
BQueue[T, ccProd, ccCons, N, P, C]
newBQueue inline ¶
proc newBQueue(): BQueue[T, ccProd, ccCons, N, P, C]
Canonical bounded-queue smart constructor (M4 alias-return lock —
returns the user-visible BQueue alias, never a backing type).
Forwards to initBQueue. The family-named helpers
(newSpscQueue / newMpscQueue / newSpmcQueue /
newMpmcQueue) are thin wrappers around this generic ctor with
the cardinality pre-bound; they exist for ergonomic continuity with
the v3.x → v4.x naming and minimize churn in the test suite.
Returns
BQueue[T, ccProd, ccCons, N, P, C]
newSpscQueue inline ¶
proc newSpscQueue(): BQueue[T, ccSingle, ccSingle, N, 0, 0]
Bounded spsc-equivalent (ccSingle × ccSingle) smart-constructor.
Returns
BQueue[T, ccSingle, ccSingle, N, 0, 0]
newMpscQueue inline ¶
proc newMpscQueue(): BQueue[T, ccMulti, ccSingle, N, P, 0]
Bounded mpsc-equivalent (ccMulti × ccSingle) smart-constructor.
P is the producer-registry capacity.
Returns
BQueue[T, ccMulti, ccSingle, N, P, 0]
newSpmcQueue inline ¶
proc newSpmcQueue(): BQueue[T, ccSingle, ccMulti, N, 0, C]
Bounded spmc-equivalent (ccSingle × ccMulti) smart-constructor.
C is the consumer-registry capacity.
Returns
BQueue[T, ccSingle, ccMulti, N, 0, C]
newMpmcQueue inline ¶
proc newMpmcQueue(): BQueue[T, ccMulti, ccMulti, N, P, C]
Bounded mpmc-equivalent (ccMulti × ccMulti) smart-constructor.
P is the producer-registry capacity, C is the consumer-registry
capacity.
Returns
BQueue[T, ccMulti, ccMulti, N, P, C]
capacity inline ¶
proc capacity(self: var BQueue[T, ccProd, ccCons, N, P, C]): int
Returns the queue's storage capacity (N).
Parameters
-
self(var BQueue[T, ccProd, ccCons, N, P, C])
Returns
int
producerCount inline ¶
proc producerCount(self: var BQueue[T, ccProd, ccCons, N, P, C]): int
Returns the queue's producer-registry capacity (P).
Single-producer shapes report 0.
Parameters
-
self(var BQueue[T, ccProd, ccCons, N, P, C])
Returns
int
consumerCount inline ¶
proc consumerCount(self: var BQueue[T, ccProd, ccCons, N, P, C]): int
Returns the queue's consumer-registry capacity (C).
Single-consumer shapes report 0.
Parameters
-
self(var BQueue[T, ccProd, ccCons, N, P, C])
Returns
int
push ¶
proc push(self: var BQueue[T, ccSingle, ccSingle, N, 0, 0]; item: sink T): bool
SPSC single-item push (lock-free; uses the SPSC typestate verbs).
Parameters
-
self(var BQueue[T, ccSingle, ccSingle, N, 0, 0]) -
item(sink T)
Returns
bool
push ¶
proc push(self: var BQueue[T, ccSingle, ccMulti, N, 0, C]; item: sink T): bool
SPMC single-item push (defensive CAS, single-producer-side).
Parameters
-
self(var BQueue[T, ccSingle, ccMulti, N, 0, C]) -
item(sink T)
Returns
bool
push error ¶
proc push(self: var BQueue[T, ccMulti, ccCons, N, P, C]; item: T): bool
Parameters
-
self(var BQueue[T, ccMulti, ccCons, N, P, C]) -
item(T)
Returns
bool
pop ¶
proc pop(self: var BQueue[T, ccSingle, ccSingle, N, 0, 0]): Option[T]
SPSC single-item pop.
Parameters
-
self(var BQueue[T, ccSingle, ccSingle, N, 0, 0])
Returns
Option[T]
pop ¶
proc pop(self: var BQueue[T, ccMulti, ccSingle, N, P, 0]): Option[T]
MPSC single-item pop (defensive CAS, single-consumer-side).
Parameters
-
self(var BQueue[T, ccMulti, ccSingle, N, P, 0])
Returns
Option[T]
pop error ¶
proc pop(self: var BQueue[T, ccProd, ccMulti, N, P, C]): Option[T]
Parameters
-
self(var BQueue[T, ccProd, ccMulti, N, P, C])
Returns
Option[T]
popBatch ¶
proc popBatch(self: var BQueue[T, ccSingle, ccSingle, N, 0, 0]; dest: var openArray[T]; maxCount: int = -1): int
SPSC direct batch pop into a caller-supplied buffer.
Parameters
-
self(var BQueue[T, ccSingle, ccSingle, N, 0, 0]) -
dest(var openArray[T]) -
maxCount(int)
Returns
int
popBatch ¶
proc popBatch(self: var BQueue[T, ccMulti, ccSingle, N, P, 0]; dest: var openArray[T]; maxCount: int = -1): int
MPSC direct batch pop into a caller-supplied buffer.
Parameters
-
self(var BQueue[T, ccMulti, ccSingle, N, P, 0]) -
dest(var openArray[T]) -
maxCount(int)
Returns
int
popChunk ¶
proc popChunk(self: var BQueue[T, ccSingle, ccSingle, N, 0, 0]; chunkSize: int): seq[T]
Parameters
-
self(var BQueue[T, ccSingle, ccSingle, N, 0, 0]) -
chunkSize(int)
Returns
seq[T]
popChunk ¶
proc popChunk(self: var BQueue[T, ccMulti, ccSingle, N, P, 0]; chunkSize: int): seq[T]
Parameters
-
self(var BQueue[T, ccMulti, ccSingle, N, P, 0]) -
chunkSize(int)
Returns
seq[T]
push ¶
proc push(self: var BQueue[T, ccSingle, ccSingle, N, 0, 0]; items: openArray[T]): Option[HSlice[int, int]]
SPSC batch push.
Parameters
-
self(var BQueue[T, ccSingle, ccSingle, N, 0, 0]) -
items(openArray[T])
Returns
Option[HSlice[int, int]]
push ¶
proc push(self: var BQueue[T, ccSingle, ccMulti, N, 0, C]; items: openArray[T]): Option[HSlice[int, int]]
SPMC batch push (loop of single-item pushes).
Parameters
-
self(var BQueue[T, ccSingle, ccMulti, N, 0, C]) -
items(openArray[T])
Returns
Option[HSlice[int, int]]
push error ¶
proc push(self: var BQueue[T, ccMulti, ccCons, N, P, C]; items: openArray[T]): Option[HSlice[int, int]]
Parameters
-
self(var BQueue[T, ccMulti, ccCons, N, P, C]) -
items(openArray[T])
Returns
Option[HSlice[int, int]]
pop ¶
proc pop(self: var BQueue[T, ccSingle, ccSingle, N, 0, 0]; count: int): Option[seq[T]]
SPSC batch pop.
Parameters
-
self(var BQueue[T, ccSingle, ccSingle, N, 0, 0]) -
count(int)
Returns
Option[seq[T]]
pop ¶
proc pop(self: var BQueue[T, ccMulti, ccSingle, N, P, 0]; count: int): Option[seq[T]]
MPSC batch pop (loop of single-item pops).
Parameters
-
self(var BQueue[T, ccMulti, ccSingle, N, P, 0]) -
count(int)
Returns
Option[seq[T]]
pop error ¶
proc pop(self: var BQueue[T, ccProd, ccMulti, N, P, C]; count: int): Option[seq[T]]
Parameters
-
self(var BQueue[T, ccProd, ccMulti, N, P, C]) -
count(int)
Returns
Option[seq[T]]
= destructorTransition transitionError raises ¶
proc =(self: var BQueue[T, ccProd, ccCons, N, P, C])
BQueue destructor — drives the Lifecycle terminal transition AND
performs the destroy-walk for unpopped slots.
BQueue owns no debra/manager heap state. For POD T the default
destructor would suffice. For ref / string / seq T the cells /
storage hold SlotEncoding(T) values (ManagedRef or
ManagedSlice — distinct uint, no auto-=destroy), so abandoned
items must be explicitly disposed here. This is the ONLY
library-managed cleanup path (push and pop are pure transfers).
Parameters
-
self(var BQueue[T, ccProd, ccCons, N, P, C])
push tags raises notATransition ¶
proc push(self: Bound[T, Tag, BQueue[T, ccMulti, ccSingle, N, P, 0]]; item: sink T): bool
MPSC single-item push on a Bound producer endpoint.
Parameters
-
self(Bound[T, Tag, BQueue[T, ccMulti, ccSingle, N, P, 0]]) -
item(sink T)
Returns
bool
push tags raises notATransition ¶
proc push(self: Bound[T, Tag, BQueue[T, ccMulti, ccMulti, N, P, C]]; item: sink T): bool
MPMC single-item push on a Bound producer endpoint.
Parameters
-
self(Bound[T, Tag, BQueue[T, ccMulti, ccMulti, N, P, C]]) -
item(sink T)
Returns
bool
pop tags raises notATransition ¶
proc pop(self: Bound[T, Tag, BQueue[T, ccSingle, ccMulti, N, 0, C]]): Option[T]
SPMC single-item pop on a Bound consumer endpoint.
Parameters
-
self(Bound[T, Tag, BQueue[T, ccSingle, ccMulti, N, 0, C]])
Returns
Option[T]
pop tags raises notATransition ¶
proc pop(self: Bound[T, Tag, BQueue[T, ccMulti, ccMulti, N, P, C]]): Option[T]
MPMC single-item pop on a Bound consumer endpoint.
Parameters
-
self(Bound[T, Tag, BQueue[T, ccMulti, ccMulti, N, P, C]])
Returns
Option[T]
push tags raises notATransition ¶
proc push(self: Bound[T, Tag, BQueue[T, ccMulti, ccSingle, N, P, 0]]; items: openArray[T]): Option[HSlice[int, int]]
MPSC batch push. Returns none if all items pushed; some(slice)
of unpushed indices otherwise.
Parameters
-
self(Bound[T, Tag, BQueue[T, ccMulti, ccSingle, N, P, 0]]) -
items(openArray[T])
Returns
Option[HSlice[int, int]]
push tags raises notATransition ¶
proc push(self: Bound[T, Tag, BQueue[T, ccMulti, ccMulti, N, P, C]]; items: openArray[T]): Option[HSlice[int, int]]
MPMC batch push. Same semantics as MPSC variant.
Parameters
-
self(Bound[T, Tag, BQueue[T, ccMulti, ccMulti, N, P, C]]) -
items(openArray[T])
Returns
Option[HSlice[int, int]]
pop tags raises notATransition ¶
proc pop(self: Bound[T, Tag, BQueue[T, ccSingle, ccMulti, N, 0, C]]; count: int): Option[seq[T]]
SPMC batch pop.
Parameters
-
self(Bound[T, Tag, BQueue[T, ccSingle, ccMulti, N, 0, C]]) -
count(int)
Returns
Option[seq[T]]
pop tags raises notATransition ¶
proc pop(self: Bound[T, Tag, BQueue[T, ccMulti, ccMulti, N, P, C]]; count: int): Option[seq[T]]
MPMC batch pop.
Parameters
-
self(Bound[T, Tag, BQueue[T, ccMulti, ccMulti, N, P, C]]) -
count(int)
Returns
Option[seq[T]]
popBatch tags raises notATransition ¶
proc popBatch(self: var Bound[T, Tag, BQueue[T, ccProd, ccCons, N, P, C]]; dest: var openArray[T]; maxCount: int = -1): int
Multi-consumer BQueue batch pop into a caller-supplied openArray buffer.
Extracts up to min(dest.len, maxCount) items without allocating intermediate seqs.
Returns the number of items successfully extracted.
Parameters
-
self(var Bound[T, Tag, BQueue[T, ccProd, ccCons, N, P, C]]) -
dest(var openArray[T]) -
maxCount(int)
Returns
int
popBatch tags raises notATransition ¶
proc popBatch(self: Bound[T, Tag, BQueue[T, ccProd, ccCons, N, P, C]]; dest: var openArray[T]; maxCount: int = -1): int
Multi-consumer BQueue batch pop (value-receiver overload).
Parameters
-
self(Bound[T, Tag, BQueue[T, ccProd, ccCons, N, P, C]]) -
dest(var openArray[T]) -
maxCount(int)
Returns
int
popChunk tags raises notATransition ¶
proc popChunk(self: var Bound[T, Tag, BQueue[T, ccProd, ccCons, N, P, C]]; chunkSize: int): seq[T]
Extracts a chunk of up to chunkSize items into a new seq[T].
Parameters
-
self(var Bound[T, Tag, BQueue[T, ccProd, ccCons, N, P, C]]) -
chunkSize(int)
Returns
seq[T]
popChunk tags raises notATransition ¶
proc popChunk(self: Bound[T, Tag, BQueue[T, ccProd, ccCons, N, P, C]]; chunkSize: int): seq[T]
Parameters
-
self(Bound[T, Tag, BQueue[T, ccProd, ccCons, N, P, C]]) -
chunkSize(int)
Returns
seq[T]
drain ¶
iterator drain(self: var BQueue[T, ccProd, ccSingle, N, P, 0]): T
Drain a single-consumer BQueue (SPSC or MPSC). Yields each remaining
item until the queue is empty. Calls the existing pop in a loop — Path-C unwrap is already done by pop.
Parameters
-
self(var BQueue[T, ccProd, ccSingle, N, P, 0])
Returns
T
drain ¶
iterator drain(self: Bound[T, Tag, BQueue[T, ccSingle, ccMulti, N, 0, C]]): T
Drain an SPMC BQueue via its Bound consumer endpoint.
Parameters
-
self(Bound[T, Tag, BQueue[T, ccSingle, ccMulti, N, 0, C]])
Returns
T
drain ¶
iterator drain(self: Bound[T, Tag, BQueue[T, ccMulti, ccMulti, N, P, C]]): T
Drain an MPMC BQueue via its Bound consumer endpoint.
Parameters
-
self(Bound[T, Tag, BQueue[T, ccMulti, ccMulti, N, P, C]])
Returns
T
items ¶
iterator items(self: var BQueue[T, ccProd, ccSingle, N, P, 0]): T
Parameters
-
self(var BQueue[T, ccProd, ccSingle, N, P, 0])
Returns
T
items ¶
iterator items(self: Bound[T, Tag, BQueue[T, ccSingle, ccMulti, N, 0, C]]): T
Parameters
-
self(Bound[T, Tag, BQueue[T, ccSingle, ccMulti, N, 0, C]])
Returns
T
items ¶
iterator items(self: Bound[T, Tag, BQueue[T, ccMulti, ccMulti, N, P, C]]): T
Parameters
-
self(Bound[T, Tag, BQueue[T, ccMulti, ccMulti, N, P, C]])
Returns
T
pairs ¶
iterator pairs(self: var BQueue[T, ccProd, ccSingle, N, P, 0]): (int, T)
Parameters
-
self(var BQueue[T, ccProd, ccSingle, N, P, 0])
Returns
(int, T)
pairs ¶
iterator pairs(self: Bound[T, Tag, BQueue[T, ccSingle, ccMulti, N, 0, C]]): (int, T)
Parameters
-
self(Bound[T, Tag, BQueue[T, ccSingle, ccMulti, N, 0, C]])
Returns
(int, T)
pairs ¶
iterator pairs(self: Bound[T, Tag, BQueue[T, ccMulti, ccMulti, N, P, C]]): (int, T)
Parameters
-
self(Bound[T, Tag, BQueue[T, ccMulti, ccMulti, N, P, C]])
Returns
(int, T)
destroyAndDrain ¶
proc destroyAndDrain(self: sink BQueue[T, ccProd, ccSingle, N, P, 0]; cleanup: proc (item: T) {.gcsafe, raises: [].})
Drain a single-consumer BQueue (SPSC or MPSC), calling cleanup
on each remaining item, then trigger queue destruction. Takes
sink of the queue so the caller's binding is moved-from
(preventing scope-end double-destroy on top of the explicit
destruction here).
Under mm:none this is the ONLY safe teardown path for a non-empty
queue carrying ref / string / seq payloads (strict bit-transport
contract). For POD payloads the cleanup is logically a no-op.
Parameters
-
self(sink BQueue[T, ccProd, ccSingle, N, P, 0]) -
cleanup(proc (item: T) {.gcsafe, raises: [].})
destroyAndDrain ¶
proc destroyAndDrain(self: sink BQueue[T, ccProd, ccSingle, N, P, 0])
POD discard-callback overload for single-consumer BQueue. Takes
sink for the same reason as the callback overload. Safe for
POD T; for non-POD T the queue's =destroy walk handles
disposal under arc/orc/atomicArc/refc — under mm:none, this
overload leaks payload bits (the operator must provide an
explicit cleanup callback under mm:none for non-POD T).
Parameters
-
self(sink BQueue[T, ccProd, ccSingle, N, P, 0])
reset ¶
proc reset(self: var BQueue[T, ccProd, ccCons, N, P, C])
Resets the queue to its default state. For single-threaded unit
tests only.
Parameters
-
self(var BQueue[T, ccProd, ccCons, N, P, C])
checkState ¶
proc checkState(self: var BQueue[T, ccSingle, ccSingle, N, 0, 0]; head: int; tail: int; storage: seq[T])
SPSC checkState.
Parameters
-
self(var BQueue[T, ccSingle, ccSingle, N, 0, 0]) -
head(int) -
tail(int) -
storage(seq[T])
checkState ¶
proc checkState(self: var BQueue[T, ccProd, ccCons, N, P, C]; head: uint64; tail: uint64)
Non-SPSC head+tail-only checkState.
Parameters
-
self(var BQueue[T, ccProd, ccCons, N, P, C]) -
head(uint64) -
tail(uint64)
checkState ¶
proc checkState(self: var BQueue[T, ccProd, ccCons, N, P, C]; head: uint64; tail: uint64; data: seq[T])
Non-SPSC head+tail+data checkState.
Parameters
-
self(var BQueue[T, ccProd, ccCons, N, P, C]) -
head(uint64) -
tail(uint64) -
data(seq[T])