edits
[model-checker-benchmarks.git] / barrier / barrier-wildcard.h
1 #include <atomic>
2 #include "wildcard.h"
3
4 class spinning_barrier {
5  public:
6         spinning_barrier (unsigned int n) : n_ (n) {
7                 nwait_ = 0;
8                 step_ = 0;
9         }
10
11         // The purpose of wait() is that threads that enter it synchronize with
12         // threads when they get out of it.
13         /** wildcard(2) is acq_rel, ensuring that all threads hb before other
14          *  threads in the rmw chain order, then the wildcard (4) and (5) are
15          *  release/acquire to make sure the last thread synchronize with all other
16          *  earlier threads. Plus, the (4) and (5) synchronization can make sure the
17          *  reset of nwait_ in wildcard(3) happens-before any other threads in the
18          *  later usage of the barrier.
19         */
20
21         // All orderings are SC originally!!!
22         bool wait() {
23                 // Infer relaxed
24                 unsigned int step = step_.load (wildcard(1));
25                 
26                 // Infer acq_rel 
27                 if (nwait_.fetch_add (1, wildcard(2)) == n_ - 1) {
28                         /* OK, last thread to come.  */
29                         // Infer relaxed 
30                         nwait_.store (0, wildcard(3)); // XXX: maybe can use relaxed ordering here ??
31                         // Infer release
32                         step_.fetch_add (1, wildcard(4));
33                         return true;
34                 } else {
35                         /* Run in circles and scream like a little girl.  */
36                         // Infer acquire 
37                         while (step_.load (wildcard(5)) == step)
38                                 thrd_yield();
39                         return false;
40                 }
41         }
42
43  protected:
44         /* Number of synchronized threads. */
45         const unsigned int n_;
46
47         /* Number of threads currently spinning.  */
48         std::atomic<unsigned int> nwait_;
49
50         /* Number of barrier syncronizations completed so far, 
51          *      * it's OK to wrap.  */
52         std::atomic<unsigned int> step_;
53 };