b22b6f2638f3bfd919915f5024319fc9418b21be
[cdsspec-compiler.git] / benchmark / spsc-bugfix / eventcount.h
1 #ifndef _EVENTCOUNT_H
2 #define _EVENTCOUNT_H
3
4 //#include <unrelacy.h>
5 #include <atomic>
6 #include <mutex>
7 #include <condition_variable>
8
9 class eventcount
10 {
11 public:
12         eventcount() : waiters(0)
13         {
14                 count = 0;
15         }
16
17         void signal_relaxed()
18         {
19                 unsigned cmp = count.load(std::memory_order_relaxed);
20                 signal_impl(cmp);
21         }
22
23         void signal()
24         {
25                 // We might be able to use release here because it basically only needs
26                 // to synchronize with the get()
27                 unsigned cmp = count.fetch_add(0, std::memory_order_seq_cst);
28                 signal_impl(cmp);
29         }
30
31         unsigned get()
32         {
33                 unsigned cmp = count.fetch_or(0x80000000,
34 std::memory_order_seq_cst);
35                 return cmp & 0x7FFFFFFF;
36         }
37
38         void wait(unsigned cmp)
39         {
40                 unsigned ec = count.load(std::memory_order_seq_cst);
41                 if (cmp == (ec & 0x7FFFFFFF))
42                 {
43                         guard.lock($);
44                         ec = count.load(std::memory_order_seq_cst);
45                         if (cmp == (ec & 0x7FFFFFFF))
46                         {
47                                 waiters += 1;
48                                 cv.wait(guard);
49                         }
50                         guard.unlock($);
51                 }
52         }
53
54 private:
55         std::atomic<unsigned> count;
56         rl::var<unsigned> waiters;
57         std::mutex guard;
58         std::condition_variable cv;
59
60         void signal_impl(unsigned cmp)
61         {
62                 if (cmp & 0x80000000)
63                 {
64                         guard.lock($);
65                         while (false == count.compare_exchange_weak(cmp,
66                                 (cmp + 1) & 0x7FFFFFFF, std::memory_order_relaxed));
67                         unsigned w = waiters($);
68                         waiters = 0;
69                         guard.unlock($);
70                         if (w)
71                                 cv.notify_all($);
72                 }
73         }
74 };
75
76 #endif