////////////////////////////////////////////////////////////////////////////// // // (C) Copyright Vicente J. Botet Escriba 2008. 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) // // See http://www.boost.org/libs/sync for documentation. // ////////////////////////////////////////////////////////////////////////////// #ifndef BOOST_SYNC_CONC_STATIC_THREAD_GROUP_HPP #define BOOST_SYNC_CONC_STATIC_THREAD_GROUP_HPP #include #include #include #include #include #include #include namespace boost { namespace detail { class static_thread_group_sync { public: static_thread_group_sync() : signaled_(false) { } // boost::thread::id wait() unsigned wait() { boost::mutex::scoped_lock lock(mutex_); cond_.wait(lock); return id_; } // bool post() bool post(unsigned id) { boost::mutex::scoped_lock lock(mutex_); if (!signaled_) { /*< first post assigns the current thread id >*/ signaled_=true; // m_thread_id = this_thread::get_id(); id_ = id; cond_.notify_one(); return true; } else { /*< the other post do nothing >*/ return false; } } private: mutex mutex_; condition_variable cond_; bool signaled_; thread::id m_thread_id; unsigned id_; }; template void signal_when_end(static_thread_group_sync& sem, F fct, unsigned id) { fct(); sem.post(id); } } template class static_thread_group; template class static_thread_group_base { public: static_thread_group_base():sync_(){} ~static_thread_group_base() { } void join() { sync_.wait(); for (unsigned i=0; ijoin(); } } unsigned join_first() { return sync_.wait(); } void interrupt() { for (unsigned i=0; iinterrupt(); } } size_t size() const { return size_; } thread& at(std::size_t i) { return *threads_[i]; } private: static_thread_group_base(static_thread_group_base&); static_thread_group_base& operator=(static_thread_group_base&); protected: detail::static_thread_group_sync sync_; thread* threads_[size_]; }; template <> class static_thread_group<2>: public static_thread_group_base<2> { public: template static_thread_group(F1 f1, F2 f2) : static_thread_group_base<2>() , thread1_(bind(detail::signal_when_end, ref(sync_), f1, 0)) , thread2_(bind(detail::signal_when_end, ref(sync_), f2, 1)) { threads_[0] =&thread1_; threads_[1] =&thread2_; } private: thread thread1_; thread thread2_; }; template <> class static_thread_group<3>: static_thread_group_base<3> { public: template static_thread_group(F1 f1, F2 f2, F3 f3) : static_thread_group_base<3>() , thread1_(bind(detail::signal_when_end, ref(sync_), f1, 0)) , thread2_(bind(detail::signal_when_end, ref(sync_), f2, 1)) , thread3_(bind(detail::signal_when_end, ref(sync_), f3, 2)) { threads_[0] =&thread1_; threads_[1] =&thread2_; threads_[2] =&thread3_; } private: thread thread1_; thread thread2_; thread thread3_; }; // static_thread_group<2> thread_all( // const function0& threadfunc1, // const function0& threadfunc2) { // static_thread_group<2> stg(threadfunc1, threadfunc2); // return stg.move(); // } template void join_all(F1 f1, F2 f2) { static_thread_group<2> stg(f1, f2); stg.join(); } template void join_all(F1 f1, F2 f2, F3 f3) { static_thread_group<2> stg(f1, f2, f3); stg.join(); } template unsigned join_first_then_interrupt(F1 f1, F2 f2) { static_thread_group<2> stg(f1, f2); unsigned res= stg.join_first(); stg.interrupt(); return res; } template unsigned join_first_then_interrupt(F1 f1, F2 f2, F3 f3) { static_thread_group<2> stg(f1, f2, f3); unsigned res= stg.join_first(); stg.interrupt(); return res; } } // namespace boost #endif // // move support //// BOOST_MOVABLE(static_thread_group, detail::thread_move_t, sync_.m_mutex, info) // static_thread_group(detail::thread_move_t x){ // lock_guard lock(sync_.m_mutex); // sync_=x->sync_.move(); // thread1_=x->thread1_.move(); // thread2_=x->thread2_.move(); // } // static_thread_group& operator=(detail::thread_move_t x) { // static_thread_group new_static_thread_group(x); // swap(new_static_thread_group); // return *this; // } // operator detail::thread_move_t() { // return move(); // } // detail::thread_move_t move() { // detail::thread_move_t x(*this); // return x; // }