CppCommon 1.0.5.0
C++ Common Library
Loading...
Searching...
No Matches
barrier.cpp
Go to the documentation of this file.
1
9#include "threads/barrier.h"
10
12
13#include <cassert>
14
15#if (defined(unix) || defined(__unix) || defined(__unix__)) && !defined(__APPLE__)
16#include "errors/fatal.h"
17#include <pthread.h>
18#elif defined(__APPLE__) || defined(__MINGW32__) || defined(__MINGW64__)
19#include <condition_variable>
20#include <mutex>
21#elif defined(_WIN32) || defined(_WIN64)
22#include <windows.h>
23#endif
24
25namespace CppCommon {
26
28
29class Barrier::Impl
30{
31public:
32 explicit Impl(int threads) : _threads(threads)
33 {
34 assert((threads > 0) && "Barrier threads counter must be greater than zero!");
35
36#if (defined(unix) || defined(__unix) || defined(__unix__)) && !defined(__APPLE__)
37 int result = pthread_barrier_init(&_barrier, nullptr, threads);
38 if (result != 0)
39 throwex SystemException("Failed to initialize a synchronization barrier!", result);
40#elif defined(__APPLE__) || defined(__MINGW32__) || defined(__MINGW64__)
41 _counter = threads;
42 _generation = 0;
43#elif defined(_WIN32) || defined(_WIN64)
44 if (!InitializeSynchronizationBarrier(&_barrier, threads, -1))
45 throwex SystemException("Failed to initialize a synchronization barrier!");
46#endif
47 }
48
49 ~Impl()
50 {
51#if (defined(unix) || defined(__unix) || defined(__unix__)) && !defined(__APPLE__)
52 int result = pthread_barrier_destroy(&_barrier);
53 if (result != 0)
54 fatality(SystemException("Failed to destroy a synchronization barrier!", result));
55#elif defined(__APPLE__) || defined(__MINGW32__) || defined(__MINGW64__)
56 // Do nothing here...
57#elif defined(_WIN32) || defined(_WIN64)
58 DeleteSynchronizationBarrier(&_barrier);
59#endif
60 }
61
62 int threads() const noexcept
63 {
64 return _threads;
65 }
66
67 bool Wait()
68 {
69#if (defined(unix) || defined(__unix) || defined(__unix__)) && !defined(__APPLE__)
70 int result = pthread_barrier_wait(&_barrier);
71 if ((result != PTHREAD_BARRIER_SERIAL_THREAD) && (result != 0))
72 throwex SystemException("Failed to wait at a synchronization barrier!", result);
73 return (result == PTHREAD_BARRIER_SERIAL_THREAD);
74#elif defined(__APPLE__) || defined(__MINGW32__) || defined(__MINGW64__)
75 std::unique_lock<std::mutex> lock(_mutex);
76
77 // Remember the current barrier generation
78 int generation = _generation;
79
80 // Decrease the count of waiting threads
81 if (--_counter == 0)
82 {
83 // Increase the current barrier generation
84 ++_generation;
85
86 // Reset waiting threads counter
87 _counter = _threads;
88
89 // Notify all waiting threads
90 _cond.notify_all();
91
92 // Notify the last thread that reached the barrier
93 return true;
94 }
95
96 // Wait for the next barrier generation
97 _cond.wait(lock, [&, this]() { return generation != _generation; });
98
99 // Notify each of remaining threads
100 return false;
101#elif defined(_WIN32) || defined(_WIN64)
102 return (EnterSynchronizationBarrier(&_barrier, 0) == TRUE);
103#endif
104 }
105
106private:
107 int _threads;
108#if (defined(unix) || defined(__unix) || defined(__unix__)) && !defined(__APPLE__)
109 pthread_barrier_t _barrier;
110#elif defined(__APPLE__) || defined(__MINGW32__) || defined(__MINGW64__)
111 std::mutex _mutex;
112 std::condition_variable _cond;
113 int _counter;
114 int _generation;
115#elif defined(_WIN32) || defined(_WIN64)
116 SYNCHRONIZATION_BARRIER _barrier;
117#endif
118};
119
121
123{
124 // Check implementation storage parameters
125 [[maybe_unused]] ValidateAlignedStorage<sizeof(Impl), alignof(Impl), StorageSize, StorageAlign> _;
126 static_assert((StorageSize >= sizeof(Impl)), "Barrier::StorageSize must be increased!");
127 static_assert(((StorageAlign % alignof(Impl)) == 0), "Barrier::StorageAlign must be adjusted!");
128
129 // Create the implementation instance
130 new(&_storage)Impl(threads);
131}
132
134{
135 // Delete the implementation instance
136 reinterpret_cast<Impl*>(&_storage)->~Impl();
137}
138
139int Barrier::threads() const noexcept { return impl().threads(); }
140
141bool Barrier::Wait() { return impl().Wait(); }
142
143} // namespace CppCommon
Barrier synchronization primitive definition.
int threads() const noexcept
Get the count of threads to wait at the barrier.
Definition barrier.cpp:139
Barrier(int threads)
Default class constructor.
Definition barrier.cpp:122
bool Wait()
Wait at the barrier until all other threads reach this barrier.
Definition barrier.cpp:141
#define throwex
Throw extended exception macro.
Definition exceptions.h:23
Fatal abort execution definition.
#define fatality(...)
Fatal abort execution extended macro.
Definition fatal.h:22
C++ Common project definitions.
Aligned storage validator definition.