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