Ion
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
barrier.cc
Go to the documentation of this file.
1 
18 #include "ion/port/barrier.h"
19 
20 #if defined(ION_PLATFORM_WINDOWS)
21 # include <assert.h> // For checking return values since port has no logging.
22 # include <algorithm> // for swap
23 #endif
24 
25 namespace ion {
26 namespace port {
27 
29 
43 
44 
45 #if defined(ION_PLATFORM_WINDOWS)
46 
65 
66 
67 Barrier::Barrier(uint32 thread_count)
68  : thread_count_(thread_count),
69  wait_count_(0),
70  turnstile1_(NULL),
71  turnstile2_(NULL),
72  is_valid_(thread_count_ > 0) {
73  if (IsValid()) {
74  turnstile1_ = CreateSemaphore(NULL, 0, thread_count_, NULL);
75  turnstile2_ = CreateSemaphore(NULL, 0, thread_count_, NULL);
76  }
77 }
78 
79 Barrier::~Barrier() {
80  if (IsValid()) {
85  CloseHandle(turnstile2_);
86  CloseHandle(turnstile1_);
87  }
88 }
89 
90 void Barrier::Wait() {
91  if (IsValid() && thread_count_ > 1) {
93  WaitInternal(1, thread_count_, turnstile1_);
94 
97  WaitInternal(-1, 0, turnstile2_);
98  }
99 }
100 
101 void Barrier::WaitInternal(int32 increment, int32 limit, HANDLE turnstile) {
102  if ((wait_count_ += increment) == limit) {
104  BOOL status = ReleaseSemaphore(turnstile, thread_count_ - 1, NULL);
105  (void)status; // Avoid warnings when the assertion is optimized out.
106  assert(status != 0);
107  } else {
108  DWORD status = WaitForSingleObject(turnstile, INFINITE);
109  (void)status; // Avoid warnings when the assertion is optimized out.
110  assert(status == WAIT_OBJECT_0);
111  }
112 }
113 
114 #elif defined(ION_PLATFORM_LINUX) || defined(ION_PLATFORM_QNX)
115 
121 
122 
123 Barrier::Barrier(uint32 thread_count)
124  : waiting_count_(0),
125  is_valid_(!pthread_barrier_init(&barrier_, NULL, thread_count)) {}
126 
127 Barrier::~Barrier() {
128  if (IsValid()) {
131  while (waiting_count_ != 0) {}
132  pthread_barrier_destroy(&barrier_);
133  }
134 }
135 
136 void Barrier::Wait() {
137  if (IsValid()) {
138  ++waiting_count_;
139  pthread_barrier_wait(&barrier_);
140  --waiting_count_;
141  }
142 }
143 
144 #else
145 
154 
155 
156 Barrier::Barrier(uint32 thread_count)
157  : thread_count_(thread_count),
158  wait_count_(0),
159  exit_count_(1),
160  is_valid_(thread_count_ > 0) {
161  if (IsValid()) {
162  pthread_cond_init(&condition_, NULL);
163  pthread_cond_init(&exit_condition_, NULL);
164  pthread_mutex_init(&mutex_, NULL);
165  }
166 }
167 
169  if (IsValid()) {
170  pthread_mutex_lock(&mutex_);
171  if (thread_count_ > 1 && --exit_count_) {
173  pthread_cond_wait(&exit_condition_, &mutex_);
174  }
175  pthread_mutex_unlock(&mutex_);
176  pthread_cond_destroy(&condition_);
177  pthread_cond_destroy(&exit_condition_);
178  pthread_mutex_destroy(&mutex_);
179  }
180 }
181 
183  if (IsValid()) {
184  pthread_mutex_lock(&mutex_);
186  if (++wait_count_ == thread_count_) {
187  wait_count_ = 0;
188  exit_count_ = thread_count_ + 1;
189  pthread_cond_broadcast(&condition_);
190  } else {
192  pthread_cond_wait(&condition_, &mutex_);
194  }
195 
199  if (--exit_count_ == 0)
200  pthread_cond_broadcast(&exit_condition_);
201  pthread_mutex_unlock(&mutex_);
202  }
203 }
204 
205 #endif
206 
207 } // namespace port
208 } // namespace ion
void Wait()
Causes the current thread to wait at the barrier.
Definition: barrier.cc:182
Barrier(uint32 thread_count)
Constructs an instance that will wait for thread_count threads.
Definition: barrier.cc:156
bool IsValid() const
Returns true if a valid barrier was created by the constructor.
Definition: barrier.h:48