aboutsummaryrefslogtreecommitdiff
path: root/Src/replicant/nu/lfmpscq.c
diff options
context:
space:
mode:
Diffstat (limited to 'Src/replicant/nu/lfmpscq.c')
-rw-r--r--Src/replicant/nu/lfmpscq.c50
1 files changed, 50 insertions, 0 deletions
diff --git a/Src/replicant/nu/lfmpscq.c b/Src/replicant/nu/lfmpscq.c
new file mode 100644
index 00000000..0f7efa73
--- /dev/null
+++ b/Src/replicant/nu/lfmpscq.c
@@ -0,0 +1,50 @@
+#include "lfmpscq.h"
+#include "foundation/atomics.h"
+
+void mpscq_init(mpscq_t* self)
+{
+ self->head = &self->stub;
+ self->tail = &self->stub;
+ self->stub.Next = 0;
+}
+
+int mpscq_push(mpscq_t *self, queue_node_t *n)
+{
+ queue_node_t *prev;
+ n->Next = 0;
+ prev = nx_atomic_swap_pointer(n, (void * volatile *)&self->head);
+ //(*)
+ prev->Next = n;
+ return prev!=&self->stub;
+}
+
+queue_node_t *mpscq_pop(mpscq_t *self)
+{
+ queue_node_t* tail = self->tail;
+ queue_node_t* next = tail->Next;
+ queue_node_t* head;
+ if (tail == &self->stub)
+ {
+ if (0 == next)
+ return 0;
+ self->tail = next;
+ tail = next;
+ next = next->Next;
+ }
+ if (next)
+ {
+ self->tail = next;
+ return tail;
+ }
+ head = self->head;
+ if (tail != head)
+ return (queue_node_t *)1;
+ mpscq_push(self, &self->stub);
+ next = tail->Next;
+ if (next)
+ {
+ self->tail = next;
+ return tail;
+ }
+ return 0;
+}