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