Chris@16: // Distributed under the Boost Software License, Version 1.0. (See Chris@16: // accompanying file LICENSE_1_0.txt or copy at Chris@16: // http://www.boost.org/LICENSE_1_0.txt) Chris@16: // (C) Copyright 2009-2012 Anthony Williams Chris@16: // (C) Copyright 2012 Vicente J. Botet Escriba Chris@16: Chris@16: // Based on the Anthony's idea of scoped_thread in CCiA Chris@16: Chris@16: #ifndef BOOST_THREAD_SCOPED_THREAD_HPP Chris@16: #define BOOST_THREAD_SCOPED_THREAD_HPP Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: #include Chris@16: Chris@16: namespace boost Chris@16: { Chris@16: Chris@16: /** Chris@16: * RAI @c thread wrapper adding a specific destroyer allowing to master what can be done at destruction time. Chris@16: * Chris@16: * CallableThread: A callable void(thread&) . Chris@16: * The default is a join_if_joinable. Chris@16: * Chris@16: * thread std/boost::thread destructor terminates the program if the thread is not joinable. Chris@16: * Having a wrapper that can join the thread before destroying it seems a natural need. Chris@16: * Chris@16: * Example: Chris@16: * Chris@16: * boost::strict_scoped_thread<> t((boost::thread(F))); Chris@16: * Chris@16: */ Chris@16: template Chris@16: class strict_scoped_thread Chris@16: { Chris@16: thread t_; Chris@16: struct dummy; Chris@16: public: Chris@16: Chris@16: BOOST_THREAD_NO_COPYABLE( strict_scoped_thread) /// non copyable Chris@16: Chris@16: /* Chris@16: * Chris@16: */ Chris@16: #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) Chris@101: template ::type, thread>, void* >::type> Chris@16: explicit strict_scoped_thread(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(Args)... args) : Chris@16: t_(boost::forward(f), boost::forward(args)...) {} Chris@16: #else Chris@16: template Chris@16: explicit strict_scoped_thread(BOOST_THREAD_FWD_REF(F) f, Chris@101: typename disable_if::type, thread>, void* >::type=0) : Chris@16: t_(boost::forward(f)) {} Chris@16: template Chris@16: strict_scoped_thread(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(A1) a1) : Chris@16: t_(boost::forward(f), boost::forward(a1)) {} Chris@16: template Chris@16: strict_scoped_thread(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(A1) a1, BOOST_THREAD_FWD_REF(A2) a2) : Chris@16: t_(boost::forward(f), boost::forward(a1), boost::forward(a2)) {} Chris@16: template Chris@16: strict_scoped_thread(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(A1) a1, BOOST_THREAD_FWD_REF(A2) a2, BOOST_THREAD_FWD_REF(A3) a3) : Chris@16: t_(boost::forward(f), boost::forward(a1), boost::forward(a2), boost::forward(a3)) {} Chris@16: #endif Chris@16: Chris@16: /** Chris@16: * Constructor from the thread to own. Chris@16: * Chris@16: * @param t: the thread to own. Chris@16: * Chris@16: * Effects: move the thread to own @c t. Chris@16: */ Chris@16: explicit strict_scoped_thread(BOOST_THREAD_RV_REF(thread) t) BOOST_NOEXCEPT : Chris@16: t_(boost::move(t)) Chris@16: { Chris@16: } Chris@16: Chris@16: /** Chris@16: * Destructor Chris@16: * Effects: Call the CallableThread functor before destroying the owned thread. Chris@16: * Remark: The CallableThread should not throw when joining the thread as the scoped variable is on a scope outside the thread function. Chris@16: */ Chris@16: ~strict_scoped_thread() Chris@16: { Chris@16: CallableThread on_destructor; Chris@16: Chris@16: on_destructor(t_); Chris@16: } Chris@16: Chris@16: }; Chris@16: Chris@16: /** Chris@16: * RAI @c thread wrapper adding a specific destroyer allowing to master what can be done at destruction time. Chris@16: * Chris@16: * CallableThread: A callable void(thread&) . Chris@16: * The default is join_if_joinable. Chris@16: * Chris@16: * thread std::thread destructor terminates the program if the thread is not joinable. Chris@16: * Having a wrapper that can join the thread before destroying it seems a natural need. Chris@16: * Chris@16: * Remark: @c scoped_thread is not a @c thread as @c thread is not designed to be derived from as a polymorphic type. Chris@16: * Anyway @c scoped_thread can be used in most of the contexts a @c thread could be used as it has the Chris@16: * same non-deprecated interface with the exception of the construction. Chris@16: * Chris@16: * Example: Chris@16: * Chris@16: * boost::scoped_thread<> t((boost::thread(F))); Chris@16: * t.interrupt(); Chris@16: * Chris@16: */ Chris@16: template Chris@16: class scoped_thread Chris@16: { Chris@16: thread t_; Chris@16: struct dummy; Chris@16: public: Chris@16: Chris@16: typedef thread::id id; Chris@16: Chris@16: BOOST_THREAD_MOVABLE_ONLY( scoped_thread) /// Movable only Chris@16: Chris@16: /** Chris@16: * Default Constructor. Chris@16: * Chris@16: * Effects: wraps a not-a-thread. Chris@16: */ Chris@16: scoped_thread() BOOST_NOEXCEPT: Chris@16: t_() Chris@16: { Chris@16: } Chris@16: Chris@16: /** Chris@16: * Chris@16: */ Chris@16: Chris@16: #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) Chris@101: template ::type, thread>, void* >::type> Chris@16: explicit scoped_thread(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(Args)... args) : Chris@16: t_(boost::forward(f), boost::forward(args)...) {} Chris@16: #else Chris@16: template Chris@16: explicit scoped_thread(BOOST_THREAD_FWD_REF(F) f, Chris@101: typename disable_if::type, thread>, void* >::type=0) : Chris@16: t_(boost::forward(f)) {} Chris@16: template Chris@16: scoped_thread(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(A1) a1) : Chris@16: t_(boost::forward(f), boost::forward(a1)) {} Chris@16: template Chris@16: scoped_thread(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(A1) a1, BOOST_THREAD_FWD_REF(A2) a2) : Chris@16: t_(boost::forward(f), boost::forward(a1), boost::forward(a2)) {} Chris@16: template Chris@16: scoped_thread(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(A1) a1, BOOST_THREAD_FWD_REF(A2) a2, BOOST_THREAD_FWD_REF(A3) a3) : Chris@16: t_(boost::forward(f), boost::forward(a1), boost::forward(a2), boost::forward(a3)) {} Chris@16: Chris@16: #endif Chris@16: /** Chris@16: * Constructor from the thread to own. Chris@16: * Chris@16: * @param t: the thread to own. Chris@16: * Chris@16: * Effects: move the thread to own @c t. Chris@16: */ Chris@16: explicit scoped_thread(BOOST_THREAD_RV_REF(thread) t) BOOST_NOEXCEPT : Chris@16: t_(boost::move(t)) Chris@16: { Chris@16: } Chris@16: Chris@16: // explicit operator thread() Chris@16: // { Chris@16: // return boost::move(t_); Chris@16: // } Chris@16: Chris@16: /** Chris@16: * Move constructor. Chris@16: */ Chris@16: scoped_thread(BOOST_RV_REF(scoped_thread) x) BOOST_NOEXCEPT : Chris@101: t_(boost::move(BOOST_THREAD_RV(x).t_)) Chris@16: {} Chris@16: Chris@16: /** Chris@16: * Destructor Chris@16: * Chris@16: * Effects: Call the CallableThread functor before destroying the owned thread. Chris@16: */ Chris@16: ~scoped_thread() Chris@16: { Chris@16: CallableThread on_destructor; Chris@16: Chris@16: on_destructor(t_); Chris@16: } Chris@16: Chris@16: /** Chris@16: * Move assignment. Chris@16: */ Chris@16: scoped_thread& operator=(BOOST_RV_REF(scoped_thread) x) Chris@16: { Chris@101: t_ = boost::move(BOOST_THREAD_RV(x).t_); Chris@16: return *this; Chris@16: } Chris@16: Chris@16: /** Chris@16: * Chris@16: */ Chris@16: void swap(scoped_thread& x) BOOST_NOEXCEPT Chris@16: { Chris@16: t_.swap(x.t_); Chris@16: } Chris@16: Chris@16: // forwarded thread functions Chris@16: inline thread::id get_id() const BOOST_NOEXCEPT Chris@16: { Chris@16: return t_.get_id(); Chris@16: } Chris@16: Chris@16: void detach() Chris@16: { Chris@16: t_.detach(); Chris@16: } Chris@16: Chris@16: void join() Chris@16: { Chris@16: t_.join(); Chris@16: } Chris@16: Chris@16: #ifdef BOOST_THREAD_USES_CHRONO Chris@16: template Chris@16: bool try_join_for(const chrono::duration& rel_time) Chris@16: { Chris@16: return t_.try_join_for(rel_time); Chris@16: } Chris@16: Chris@16: template Chris@16: bool try_join_until(const chrono::time_point& abs_time) Chris@16: { Chris@16: return t_.try_join_until(abs_time); Chris@16: } Chris@16: #endif Chris@16: Chris@16: thread::native_handle_type native_handle()BOOST_NOEXCEPT Chris@16: { Chris@16: return t_.native_handle(); Chris@16: } Chris@16: Chris@16: bool joinable() const BOOST_NOEXCEPT Chris@16: { Chris@16: return t_.joinable(); Chris@16: } Chris@16: Chris@16: #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS Chris@16: void interrupt() Chris@16: { Chris@16: t_.interrupt(); Chris@16: } Chris@16: Chris@16: bool interruption_requested() const BOOST_NOEXCEPT Chris@16: { Chris@16: return t_.interruption_requested(); Chris@16: } Chris@16: #endif Chris@16: Chris@101: static unsigned hardware_concurrency() BOOST_NOEXCEPT Chris@16: { Chris@16: return thread::hardware_concurrency(); Chris@16: } Chris@16: Chris@101: #ifdef BOOST_THREAD_PROVIDES_PHYSICAL_CONCURRENCY Chris@101: static unsigned physical_concurrency() BOOST_NOEXCEPT Chris@101: { Chris@101: return thread::physical_concurrency(); Chris@101: } Chris@101: #endif Chris@16: }; Chris@16: Chris@16: /** Chris@16: * Effects: swaps the contents of two scoped threads. Chris@16: */ Chris@16: template Chris@16: void swap(scoped_thread& lhs, scoped_thread& rhs) Chris@16: BOOST_NOEXCEPT { Chris@16: return lhs.swap(rhs); Chris@16: } Chris@16: Chris@16: } Chris@16: #include Chris@16: Chris@16: #endif