Chris@16: // Copyright (C) 2002-2003 Chris@16: // David Moore, William E. Kempf Chris@16: // Copyright (C) 2007-8 Anthony Williams Chris@101: // (C) Copyright 2013 Vicente J. Botet Escriba Chris@16: // Chris@16: // Distributed under the Boost Software License, Version 1.0. (See accompanying Chris@16: // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) Chris@16: Chris@16: #ifndef BOOST_BARRIER_JDM030602_HPP Chris@16: #define BOOST_BARRIER_JDM030602_HPP Chris@16: Chris@16: #include Chris@16: #include Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@101: #include Chris@16: #include Chris@16: #include Chris@101: #include Chris@16: #include Chris@16: Chris@16: #include Chris@16: Chris@16: namespace boost Chris@16: { Chris@16: namespace thread_detail Chris@16: { Chris@101: typedef detail::nullary_function void_completion_function; Chris@101: typedef detail::nullary_function size_completion_function; Chris@16: Chris@16: struct default_barrier_reseter Chris@16: { Chris@16: unsigned int size_; Chris@16: default_barrier_reseter(unsigned int size) : Chris@16: size_(size) Chris@16: { Chris@16: } Chris@101: BOOST_THREAD_MOVABLE(default_barrier_reseter) Chris@101: //BOOST_THREAD_COPYABLE_AND_MOVABLE(default_barrier_reseter) Chris@101: Chris@101: default_barrier_reseter(default_barrier_reseter const& other) BOOST_NOEXCEPT : Chris@101: size_(other.size_) Chris@101: { Chris@101: } Chris@101: default_barrier_reseter(BOOST_THREAD_RV_REF(default_barrier_reseter) other) BOOST_NOEXCEPT : Chris@101: size_(BOOST_THREAD_RV(other).size_) Chris@101: { Chris@101: } Chris@101: Chris@16: unsigned int operator()() Chris@16: { Chris@16: return size_; Chris@16: } Chris@16: }; Chris@16: Chris@16: struct void_functor_barrier_reseter Chris@16: { Chris@16: unsigned int size_; Chris@16: void_completion_function fct_; Chris@16: template Chris@16: void_functor_barrier_reseter(unsigned int size, BOOST_THREAD_RV_REF(F) funct) Chris@16: : size_(size), fct_(boost::move(funct)) Chris@16: {} Chris@101: template Chris@101: void_functor_barrier_reseter(unsigned int size, F& funct) Chris@16: : size_(size), fct_(funct) Chris@16: {} Chris@101: Chris@101: BOOST_THREAD_MOVABLE(void_functor_barrier_reseter) Chris@101: //BOOST_THREAD_COPYABLE_AND_MOVABLE(void_functor_barrier_reseter) Chris@101: Chris@101: void_functor_barrier_reseter(void_functor_barrier_reseter const& other) BOOST_NOEXCEPT : Chris@101: size_(other.size_), fct_(other.fct_) Chris@101: { Chris@101: } Chris@101: void_functor_barrier_reseter(BOOST_THREAD_RV_REF(void_functor_barrier_reseter) other) BOOST_NOEXCEPT : Chris@101: size_(BOOST_THREAD_RV(other).size_), fct_(BOOST_THREAD_RV(other).fct_) Chris@101: //size_(BOOST_THREAD_RV(other).size_), fct_(boost::move(BOOST_THREAD_RV(other).fct_)) Chris@101: { Chris@101: } Chris@101: Chris@16: unsigned int operator()() Chris@16: { Chris@16: fct_(); Chris@16: return size_; Chris@16: } Chris@16: }; Chris@16: struct void_fct_ptr_barrier_reseter Chris@16: { Chris@16: unsigned int size_; Chris@16: void(*fct_)(); Chris@16: void_fct_ptr_barrier_reseter(unsigned int size, void(*funct)()) : Chris@16: size_(size), fct_(funct) Chris@16: { Chris@16: } Chris@101: BOOST_THREAD_MOVABLE(void_fct_ptr_barrier_reseter) Chris@101: //BOOST_THREAD_COPYABLE_AND_MOVABLE(void_fct_ptr_barrier_reseter) Chris@101: Chris@101: void_fct_ptr_barrier_reseter(void_fct_ptr_barrier_reseter const& other) BOOST_NOEXCEPT : Chris@101: size_(other.size_), fct_(other.fct_) Chris@101: { Chris@101: } Chris@101: void_fct_ptr_barrier_reseter(BOOST_THREAD_RV_REF(void_fct_ptr_barrier_reseter) other) BOOST_NOEXCEPT : Chris@101: size_(BOOST_THREAD_RV(other).size_), fct_(BOOST_THREAD_RV(other).fct_) Chris@101: { Chris@101: } Chris@16: unsigned int operator()() Chris@16: { Chris@16: fct_(); Chris@16: return size_; Chris@16: } Chris@16: }; Chris@16: } Chris@101: //BOOST_THREAD_DCL_MOVABLE(thread_detail::default_barrier_reseter) Chris@101: //BOOST_THREAD_DCL_MOVABLE(thread_detail::void_functor_barrier_reseter) Chris@101: //BOOST_THREAD_DCL_MOVABLE(thread_detail::void_fct_ptr_barrier_reseter) Chris@101: Chris@16: class barrier Chris@16: { Chris@16: static inline unsigned int check_counter(unsigned int count) Chris@16: { Chris@16: if (count == 0) boost::throw_exception( Chris@16: thread_exception(system::errc::invalid_argument, "barrier constructor: count cannot be zero.")); Chris@16: return count; Chris@16: } Chris@16: struct dummy Chris@16: { Chris@16: }; Chris@16: Chris@16: public: Chris@16: BOOST_THREAD_NO_COPYABLE( barrier) Chris@16: Chris@16: explicit barrier(unsigned int count) : Chris@101: m_count(check_counter(count)), m_generation(0), fct_(BOOST_THREAD_MAKE_RV_REF(thread_detail::default_barrier_reseter(count))) Chris@16: { Chris@16: } Chris@16: Chris@16: template Chris@16: barrier( Chris@16: unsigned int count, Chris@16: BOOST_THREAD_RV_REF(F) funct, Chris@16: typename enable_if< Chris@16: typename is_void::type>::type, dummy* Chris@16: >::type=0 Chris@16: ) Chris@16: : m_count(check_counter(count)), Chris@101: m_generation(0), Chris@101: fct_(BOOST_THREAD_MAKE_RV_REF(thread_detail::void_functor_barrier_reseter(count, Chris@101: boost::move(funct))) Chris@101: ) Chris@101: { Chris@101: } Chris@101: template Chris@101: barrier( Chris@101: unsigned int count, Chris@101: F &funct, Chris@101: typename enable_if< Chris@101: typename is_void::type>::type, dummy* Chris@101: >::type=0 Chris@101: ) Chris@101: : m_count(check_counter(count)), Chris@101: m_generation(0), Chris@101: fct_(BOOST_THREAD_MAKE_RV_REF(thread_detail::void_functor_barrier_reseter(count, Chris@101: funct)) Chris@16: ) Chris@16: { Chris@16: } Chris@16: Chris@16: template Chris@16: barrier( Chris@16: unsigned int count, Chris@16: BOOST_THREAD_RV_REF(F) funct, Chris@16: typename enable_if< Chris@16: typename is_same::type, unsigned int>::type, dummy* Chris@16: >::type=0 Chris@16: ) Chris@16: : m_count(check_counter(count)), Chris@101: m_generation(0), Chris@101: fct_(boost::move(funct)) Chris@101: { Chris@101: } Chris@101: template Chris@101: barrier( Chris@101: unsigned int count, Chris@101: F& funct, Chris@101: typename enable_if< Chris@101: typename is_same::type, unsigned int>::type, dummy* Chris@101: >::type=0 Chris@16: ) Chris@101: : m_count(check_counter(count)), Chris@101: m_generation(0), Chris@101: fct_(funct) Chris@16: { Chris@16: } Chris@16: Chris@16: barrier(unsigned int count, void(*funct)()) : Chris@16: m_count(check_counter(count)), m_generation(0), Chris@16: fct_(funct Chris@101: ? BOOST_THREAD_MAKE_RV_REF(thread_detail::size_completion_function(BOOST_THREAD_MAKE_RV_REF(thread_detail::void_fct_ptr_barrier_reseter(count, funct)))) Chris@101: : BOOST_THREAD_MAKE_RV_REF(thread_detail::size_completion_function(BOOST_THREAD_MAKE_RV_REF(thread_detail::default_barrier_reseter(count)))) Chris@16: ) Chris@16: { Chris@16: } Chris@16: barrier(unsigned int count, unsigned int(*funct)()) : Chris@16: m_count(check_counter(count)), m_generation(0), Chris@16: fct_(funct Chris@101: ? BOOST_THREAD_MAKE_RV_REF(thread_detail::size_completion_function(funct)) Chris@101: : BOOST_THREAD_MAKE_RV_REF(thread_detail::size_completion_function(BOOST_THREAD_MAKE_RV_REF(thread_detail::default_barrier_reseter(count)))) Chris@16: ) Chris@16: { Chris@16: } Chris@16: Chris@16: bool wait() Chris@16: { Chris@16: boost::unique_lock < boost::mutex > lock(m_mutex); Chris@16: unsigned int gen = m_generation; Chris@16: Chris@16: if (--m_count == 0) Chris@16: { Chris@16: m_generation++; Chris@16: m_count = static_cast(fct_()); Chris@16: BOOST_ASSERT(m_count != 0); Chris@16: m_cond.notify_all(); Chris@16: return true; Chris@16: } Chris@16: Chris@16: while (gen == m_generation) Chris@16: m_cond.wait(lock); Chris@16: return false; Chris@16: } Chris@16: Chris@16: void count_down_and_wait() Chris@16: { Chris@16: wait(); Chris@16: } Chris@16: Chris@16: private: Chris@16: mutex m_mutex; Chris@16: condition_variable m_cond; Chris@16: unsigned int m_count; Chris@16: unsigned int m_generation; Chris@16: thread_detail::size_completion_function fct_; Chris@16: }; Chris@16: Chris@16: } // namespace boost Chris@16: Chris@16: #include Chris@16: Chris@16: #endif