spsc-queue: unrelacy
[model-checker-benchmarks.git] / spsc-queue / queue.h
1 #include <unrelacy.h>
2
3 #include "eventcount.h"
4
5 template<typename T>
6 class spsc_queue
7 {
8 public:
9         spsc_queue()
10         {
11                 node* n = RL_NEW node ();
12                 head = n;
13                 tail = n;
14         }
15
16         ~spsc_queue()
17         {
18                 RL_ASSERT(head == tail);
19                 RL_DELETE((node*)head($));
20         }
21
22         void enqueue(T data)
23         {
24                 node* n = RL_NEW node (data);
25                 head($)->next.store(n, std::memory_order_release);
26                 head = n;
27                 ec.signal_relaxed();
28         }
29
30         T dequeue()
31         {
32                 T data = try_dequeue();
33                 while (0 == data)
34                 {
35                         int cmp = ec.get();
36                         data = try_dequeue();
37                         if (data)
38                                 break;
39                         ec.wait(cmp);
40                         data = try_dequeue();
41                         if (data)
42                                 break;
43                 }
44                 return data;
45         }
46
47 private:
48         struct node
49         {
50                 std::atomic<node*> next;
51                 rl::var<T> data;
52
53                 node(T data = T())
54                         : next(0)
55                         , data(data)
56                 {}
57         };
58
59         rl::var<node*> head;
60         rl::var<node*> tail;
61
62         eventcount ec;
63
64         T try_dequeue()
65         {
66                 node* t = tail($);
67                 node* n = t->next.load(std::memory_order_acquire);
68                 if (0 == n)
69                         return 0;
70                 T data = n->data($);
71                 RL_DELETE(t);
72                 tail = n;
73                 return data;
74         }
75 };