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