spsc-queue: fixup atomics, mutexes, threads
[model-checker-benchmarks.git] / spsc-queue / eventcount.h
1 #include <unrelacy.h>
2 #include <atomic>
3 #include <mutex>
4
5 class eventcount
6 {
7 public:
8         eventcount() : waiters(0)
9         {
10                 count = 0;
11         }
12
13         void signal_relaxed()
14         {
15                 unsigned cmp = count.load(std::memory_order_relaxed);
16                 signal_impl(cmp);
17         }
18
19         void signal()
20         {
21                 unsigned cmp = count.fetch_add(0, std::memory_order_seq_cst);
22                 signal_impl(cmp);
23         }
24
25         unsigned get()
26         {
27                 unsigned cmp = count.fetch_or(0x80000000,
28 std::memory_order_seq_cst);
29                 return cmp & 0x7FFFFFFF;
30         }
31
32         void wait(unsigned cmp)
33         {
34                 unsigned ec = count.load(std::memory_order_seq_cst);
35                 if (cmp == (ec & 0x7FFFFFFF))
36                 {
37                         guard.lock($);
38                         ec = count.load(std::memory_order_seq_cst);
39                         if (cmp == (ec & 0x7FFFFFFF))
40                         {
41                                 waiters += 1;
42                                 cv.wait(guard, $);
43                         }
44                         guard.unlock($);
45                 }
46         }
47
48 private:
49         std::atomic<unsigned> count;
50         rl::var<unsigned> waiters;
51         std::mutex guard;
52         condition_variable_any cv;
53
54         void signal_impl(unsigned cmp)
55         {
56                 if (cmp & 0x80000000)
57                 {
58                         guard.lock($);
59                         while (false == count.compare_exchange_weak(cmp,
60                                 (cmp + 1) & 0x7FFFFFFF, std::memory_order_relaxed));
61                         unsigned w = waiters($);
62                         waiters = 0;
63                         guard.unlock($);
64                         if (w)
65                                 cv.notify_all($);
66                 }
67         }
68 };