34#include <condition_variable>
57 using lock_t = std::unique_lock<mutex_t>;
61 : m_master(
std::this_thread::get_id())
62 , m_num_threads(nthreads)
64 , m_future(m_promise.get_future().share())
80#if defined(TIMEMORY_INTERNAL_TESTING)
93 while(m_counter < m_num_threads)
95 while(spin_lock.test_and_set(std::memory_order_acquire))
97 spin_lock.clear(std::memory_order_release);
113#if defined(TIMEMORY_INTERNAL_TESTING)
123 m_cv.wait(lk, [&] {
return m_counter >= m_num_threads; });
137 while(m_notify.load() < m_num_threads)
139 m_promise.set_value();
140 while(m_notify.load() > 0)
143 std::promise<void> _ptmp;
144 std::shared_future<void> _ftmp = _ptmp.get_future().share();
145 std::swap(m_promise, _ptmp);
146 std::swap(m_future, _ftmp);
161 bool is_master()
const {
return std::this_thread::get_id() == m_master; }
165 std::thread::id m_master = std::this_thread::get_id();
169 std::atomic_flag spin_lock = ATOMIC_FLAG_INIT;
172 std::atomic<size_type> m_notify;
173 std::promise<void> m_promise;
174 std::shared_future<void> m_future;
std::condition_variable condvar_t
std::atomic< size_type > atomic_t
thread_barrier & operator=(const thread_barrier &)=delete
thread_barrier(const thread_barrier &)=delete
thread_barrier(size_t nthreads)
thread_barrier & operator=(thread_barrier &&)=delete
std::unique_lock< mutex_t > lock_t
thread_barrier(thread_barrier &&)=delete
std::recursive_mutex mutex_t
Recursive mutex is used for convenience since the performance penalty vs. a regular mutex is not real...
#define TIMEMORY_EXCEPTION(...)