256 lines
		
	
	
		
			7.2 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			256 lines
		
	
	
		
			7.2 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
| // 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
 |