Soenneker.Queues.Intrusive.Mpsc
4.0.36
Prefix Reserved
dotnet add package Soenneker.Queues.Intrusive.Mpsc --version 4.0.36
NuGet\Install-Package Soenneker.Queues.Intrusive.Mpsc -Version 4.0.36
<PackageReference Include="Soenneker.Queues.Intrusive.Mpsc" Version="4.0.36" />
<PackageVersion Include="Soenneker.Queues.Intrusive.Mpsc" Version="4.0.36" />
<PackageReference Include="Soenneker.Queues.Intrusive.Mpsc" />
paket add Soenneker.Queues.Intrusive.Mpsc --version 4.0.36
#r "nuget: Soenneker.Queues.Intrusive.Mpsc, 4.0.36"
#:package Soenneker.Queues.Intrusive.Mpsc@4.0.36
#addin nuget:?package=Soenneker.Queues.Intrusive.Mpsc&version=4.0.36
#tool nuget:?package=Soenneker.Queues.Intrusive.Mpsc&version=4.0.36
Soenneker.Queues.Intrusive.Mpsc
A lock-free intrusive multi-producer, single-consumer queue for low-level scheduling and synchronization infrastructure.
The queue stores its forward link on each node, so enqueue and dequeue do not allocate wrapper objects. In exchange, callers must follow the node-ownership and single-consumer rules exactly.
The producer tail is cache-line separated from the consumer head to reduce cache-coherency traffic under contention. This adds 56 bytes to each queue object in exchange for higher concurrent throughput.
Install
dotnet add package Soenneker.Queues.Intrusive.Mpsc
Usage
using Soenneker.Queues.Intrusive.Abstractions;
using Soenneker.Queues.Intrusive.Mpsc;
public sealed class WorkItem : IntrusiveNode<WorkItem>
{
public required string Payload { get; init; }
}
var stub = new WorkItem { Payload = "stub" };
var queue = new IntrusiveMpscQueue<WorkItem>(stub);
queue.Enqueue(new WorkItem { Payload = "one" });
if (queue.TryDequeue(out WorkItem item))
Console.WriteLine(item.Payload);
Any number of producer threads may call Enqueue. Only one consumer thread may call dequeue methods, Drain, IsEmpty, or access Head.
Dequeue choices
TryDequeuedoes not spin. It can returnfalseduring the short window after a producer advances the tail and before it publishes the forward link.TryDequeueSpin(node, maxSpins)waits for that link for a bounded number of spins.TryDequeueSpinUntilLinkedwaits without a spin limit when a producer is already mid-enqueue. It does not wait for a future enqueue when the queue is empty.Drain(action, max)processes currently available nodes with non-spinning dequeue semantics.
After a dequeue method returns true, the returned node is detached and may be reused immediately. Head is different: it exposes an internal queue anchor and must not be modified or enqueued.
Required ownership rules
- Keep the stub alive for the lifetime of the queue and never enqueue it yourself.
- Never enqueue a node that is already in this queue or any other intrusive structure.
- Do not read or write a node’s
Nextlink while the queue owns it. - Use exactly one consumer; the queue is not safe for concurrent dequeue operations.
- Treat
IsEmptyas a point-in-time observation because producers may enqueue immediately afterward.
Use System.Threading.Channels or ConcurrentQueue<T> when multiple consumers, blocking coordination, or general collection semantics matter more than intrusive allocation control.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Soenneker.Queues.Intrusive.Abstractions (>= 4.0.22)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 4.0.36 | 67 | 9/15/2026 |
| 4.0.35 | 72 | 9/15/2026 |
| 4.0.34 | 79 | 9/14/2026 |
| 4.0.33 | 78 | 9/12/2026 |
| 4.0.32 | 92 | 9/3/2026 |
| 4.0.31 | 93 | 8/31/2026 |
| 4.0.30 | 92 | 8/30/2026 |
| 4.0.29 | 106 | 8/30/2026 |
| 4.0.28 | 99 | 8/29/2026 |
| 4.0.27 | 116 | 7/28/2026 |
| 4.0.26 | 108 | 7/28/2026 |
| 4.0.25 | 110 | 7/18/2026 |
| 4.0.24 | 113 | 7/16/2026 |
| 4.0.23 | 129 | 6/19/2026 |
| 4.0.22 | 120 | 6/19/2026 |
| 4.0.21 | 125 | 6/5/2026 |
| 4.0.20 | 129 | 6/5/2026 |
| 4.0.19 | 133 | 6/5/2026 |
| 4.0.18 | 129 | 4/23/2026 |
| 4.0.17 | 125 | 4/23/2026 |
Update dependency Soenneker.Queues.Intrusive.Abstractions to 4.0.22 (#62)
Automatically merged