Skip to content

Instantly share code, notes, and snippets.

@kassane
Last active December 24, 2023 17:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kassane/a1b66a34576bd6d161fe8182d42047c5 to your computer and use it in GitHub Desktop.
Save kassane/a1b66a34576bd6d161fe8182d42047c5 to your computer and use it in GitHub Desktop.
module intrusive_mpsc_queue;
import core.atomic;
// An intrusive MPSC queue in D.
struct IntrusiveQueue(T)
{
private T* head;
private T* tail;
private T stub;
// Initialize the queue
void init()
{
head = &stub;
tail = &stub;
stub.next = null;
}
// Push an item onto the queue
void push(T* item)
{
T* prev = atomicLoad(head);
atomicStore(head, item);
atomicStore(prev.next, item);
}
// Pop an item from the queue
T* pop()
{
T* tail = atomicLoad(this.head);
auto next = atomicLoad(tail.next);
if (tail is &stub)
{
next = next ? next : null;
atomicStore(this.tail, next);
tail = next;
next = atomicLoad(tail.next);
}
if (next)
{
atomicStore(this.tail, next);
tail.next = null;
return tail;
}
auto head = atomicLoad(this.head);
if (tail != head)
return null;
push(&stub);
next = atomicLoad(tail.next);
if (next)
{
atomicStore(this.tail, next);
tail.next = null;
return tail;
}
return null;
}
}
unittest
{
struct Elem
{
Elem* next;
}
Elem[10] elems;
auto queue = IntrusiveQueue!Elem();
queue.init();
// One element
assert(queue.pop() is null);
queue.push(&elems[0]);
assert(queue.pop() == &elems[0]);
assert(queue.pop() is null);
// Two elements
assert(queue.pop() is null);
queue.push(&elems[0]);
queue.push(&elems[1]);
assert(queue.pop() == &elems[0]);
assert(queue.pop() == &elems[1]);
assert(queue.pop() is null);
}
@kassane
Copy link
Author

kassane commented Nov 20, 2023

⚠️ Not working - WiP

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment