Provides a high performance mpsc intrusive queue primitive
$ dotnet add package Soenneker.Queues.Intrusive.ValueMpsc
Soenneker.Queues.Intrusive.ValueMpscdotnet add package Soenneker.Queues.Intrusive.ValueMpsc
ValueIntrusiveMpscQueue<TNode> is a multi-producer / single-consumer (MPSC) queue built around a classic intrusive algorithm with a permanent sentinel (“stub”) node.
This value variant is designed to minimize indirection and memory traffic by storing queue state directly in value fields rather than reference wrappers.
Key characteristics:
This makes it especially suitable for hot paths in low-level concurrency primitives.
Compared to reference-based implementations, this variant:
If you are building performance-critical infrastructure (locks, schedulers, wait queues), this version is usually the right default.
Nodes must implement IIntrusiveNode<TNode> or derive from IntrusiveNode<TNode>.
public sealed class WorkItem : IntrusiveNode<WorkItem>
{
public int Id;
}
Each node carries its own linkage; the queue never allocates or wraps nodes.
var stub = new WorkItem();
var queue = new ValueIntrusiveMpscQueue<WorkItem>(stub);
The stub node must remain alive for the entire lifetime of the queue.
queue.Enqueue(new WorkItem { Id = 42 });
This operation is lock-free and safe to call concurrently from multiple threads.
if (queue.TryDequeue(out var item))
{
// process item
}
If stronger dequeue guarantees are required (for example, when a producer has advanced the tail but not yet published the link), use:
queue.TryDequeueSpin(out var item);
This type intentionally enforces strict usage rules:
TryDequeue may return false while a producer is mid-enqueue — this is expected.Violating these constraints will result in undefined behavior.
This is a low-level primitive, not a general-purpose collection.
This queue is a good fit when:
If you need a general-purpose queue with multiple consumers, prefer ConcurrentQueue<T> or System.Threading.Channels.