| #ifndef BOOST_THREAD_THREAD_COMMON_HPP |
| #define BOOST_THREAD_THREAD_COMMON_HPP |
| // 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) |
| // (C) Copyright 2007-10 Anthony Williams |
| |
| #include <boost/thread/exceptions.hpp> |
| #ifndef BOOST_NO_IOSTREAM |
| #include <ostream> |
| #endif |
| #include <boost/thread/detail/move.hpp> |
| #include <boost/thread/mutex.hpp> |
| #include <boost/thread/xtime.hpp> |
| #include <boost/thread/detail/thread_heap_alloc.hpp> |
| #include <boost/utility.hpp> |
| #include <boost/assert.hpp> |
| #include <list> |
| #include <algorithm> |
| #include <boost/ref.hpp> |
| #include <boost/cstdint.hpp> |
| #include <boost/bind.hpp> |
| #include <stdlib.h> |
| #include <memory> |
| #include <boost/utility/enable_if.hpp> |
| #include <boost/type_traits/remove_reference.hpp> |
| |
| #include <boost/config/abi_prefix.hpp> |
| |
| #ifdef BOOST_MSVC |
| #pragma warning(push) |
| #pragma warning(disable:4251) |
| #endif |
| |
| namespace boost |
| { |
| namespace detail |
| { |
| template<typename F> |
| class thread_data: |
| public detail::thread_data_base |
| { |
| public: |
| #ifndef BOOST_NO_RVALUE_REFERENCES |
| thread_data(F&& f_): |
| f(static_cast<F&&>(f_)) |
| {} |
| thread_data(F& f_): |
| f(f_) |
| {} |
| #else |
| thread_data(F f_): |
| f(f_) |
| {} |
| thread_data(detail::thread_move_t<F> f_): |
| f(f_) |
| {} |
| #endif |
| void run() |
| { |
| f(); |
| } |
| private: |
| F f; |
| |
| void operator=(thread_data&); |
| thread_data(thread_data&); |
| }; |
| |
| template<typename F> |
| class thread_data<boost::reference_wrapper<F> >: |
| public detail::thread_data_base |
| { |
| private: |
| F& f; |
| |
| void operator=(thread_data&); |
| thread_data(thread_data&); |
| public: |
| thread_data(boost::reference_wrapper<F> f_): |
| f(f_) |
| {} |
| |
| void run() |
| { |
| f(); |
| } |
| }; |
| |
| template<typename F> |
| class thread_data<const boost::reference_wrapper<F> >: |
| public detail::thread_data_base |
| { |
| private: |
| F& f; |
| void operator=(thread_data&); |
| thread_data(thread_data&); |
| public: |
| thread_data(const boost::reference_wrapper<F> f_): |
| f(f_) |
| {} |
| |
| void run() |
| { |
| f(); |
| } |
| }; |
| } |
| |
| class BOOST_THREAD_DECL thread |
| { |
| private: |
| thread(thread&); |
| thread& operator=(thread&); |
| |
| void release_handle(); |
| |
| detail::thread_data_ptr thread_info; |
| |
| void start_thread(); |
| |
| explicit thread(detail::thread_data_ptr data); |
| |
| detail::thread_data_ptr get_thread_info BOOST_PREVENT_MACRO_SUBSTITUTION () const; |
| |
| #ifndef BOOST_NO_RVALUE_REFERENCES |
| template<typename F> |
| static inline detail::thread_data_ptr make_thread_info(F&& f) |
| { |
| return detail::thread_data_ptr(detail::heap_new<detail::thread_data<typename boost::remove_reference<F>::type> >(static_cast<F&&>(f))); |
| } |
| static inline detail::thread_data_ptr make_thread_info(void (*f)()) |
| { |
| return detail::thread_data_ptr(detail::heap_new<detail::thread_data<void(*)()> >(static_cast<void(*&&)()>(f))); |
| } |
| #else |
| template<typename F> |
| static inline detail::thread_data_ptr make_thread_info(F f) |
| { |
| return detail::thread_data_ptr(detail::heap_new<detail::thread_data<F> >(f)); |
| } |
| template<typename F> |
| static inline detail::thread_data_ptr make_thread_info(boost::detail::thread_move_t<F> f) |
| { |
| return detail::thread_data_ptr(detail::heap_new<detail::thread_data<F> >(f)); |
| } |
| |
| #endif |
| struct dummy; |
| public: |
| #if BOOST_WORKAROUND(__SUNPRO_CC, < 0x5100) |
| thread(const volatile thread&); |
| #endif |
| thread(); |
| ~thread(); |
| |
| #ifndef BOOST_NO_RVALUE_REFERENCES |
| #ifdef BOOST_MSVC |
| template <class F> |
| explicit thread(F f,typename disable_if<boost::is_convertible<F&,detail::thread_move_t<F> >, dummy* >::type=0): |
| thread_info(make_thread_info(static_cast<F&&>(f))) |
| { |
| start_thread(); |
| } |
| #else |
| template <class F> |
| thread(F&& f): |
| thread_info(make_thread_info(static_cast<F&&>(f))) |
| { |
| start_thread(); |
| } |
| #endif |
| |
| thread(thread&& other) |
| { |
| thread_info.swap(other.thread_info); |
| } |
| |
| thread& operator=(thread&& other) |
| { |
| thread_info=other.thread_info; |
| other.thread_info.reset(); |
| return *this; |
| } |
| |
| thread&& move() |
| { |
| return static_cast<thread&&>(*this); |
| } |
| |
| #else |
| #ifdef BOOST_NO_SFINAE |
| template <class F> |
| explicit thread(F f): |
| thread_info(make_thread_info(f)) |
| { |
| start_thread(); |
| } |
| #else |
| template <class F> |
| explicit thread(F f,typename disable_if<boost::is_convertible<F&,detail::thread_move_t<F> >, dummy* >::type=0): |
| thread_info(make_thread_info(f)) |
| { |
| start_thread(); |
| } |
| #endif |
| |
| template <class F> |
| explicit thread(detail::thread_move_t<F> f): |
| thread_info(make_thread_info(f)) |
| { |
| start_thread(); |
| } |
| |
| thread(detail::thread_move_t<thread> x) |
| { |
| thread_info=x->thread_info; |
| x->thread_info.reset(); |
| } |
| |
| #if BOOST_WORKAROUND(__SUNPRO_CC, < 0x5100) |
| thread& operator=(thread x) |
| { |
| swap(x); |
| return *this; |
| } |
| #else |
| thread& operator=(detail::thread_move_t<thread> x) |
| { |
| thread new_thread(x); |
| swap(new_thread); |
| return *this; |
| } |
| #endif |
| operator detail::thread_move_t<thread>() |
| { |
| return move(); |
| } |
| |
| detail::thread_move_t<thread> move() |
| { |
| detail::thread_move_t<thread> x(*this); |
| return x; |
| } |
| |
| #endif |
| |
| template <class F,class A1> |
| thread(F f,A1 a1): |
| thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1))) |
| { |
| start_thread(); |
| } |
| template <class F,class A1,class A2> |
| thread(F f,A1 a1,A2 a2): |
| thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2))) |
| { |
| start_thread(); |
| } |
| |
| template <class F,class A1,class A2,class A3> |
| thread(F f,A1 a1,A2 a2,A3 a3): |
| thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3))) |
| { |
| start_thread(); |
| } |
| |
| template <class F,class A1,class A2,class A3,class A4> |
| thread(F f,A1 a1,A2 a2,A3 a3,A4 a4): |
| thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3,a4))) |
| { |
| start_thread(); |
| } |
| |
| template <class F,class A1,class A2,class A3,class A4,class A5> |
| thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5): |
| thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3,a4,a5))) |
| { |
| start_thread(); |
| } |
| |
| template <class F,class A1,class A2,class A3,class A4,class A5,class A6> |
| thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6): |
| thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3,a4,a5,a6))) |
| { |
| start_thread(); |
| } |
| |
| template <class F,class A1,class A2,class A3,class A4,class A5,class A6,class A7> |
| thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6,A7 a7): |
| thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3,a4,a5,a6,a7))) |
| { |
| start_thread(); |
| } |
| |
| template <class F,class A1,class A2,class A3,class A4,class A5,class A6,class A7,class A8> |
| thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6,A7 a7,A8 a8): |
| thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3,a4,a5,a6,a7,a8))) |
| { |
| start_thread(); |
| } |
| |
| template <class F,class A1,class A2,class A3,class A4,class A5,class A6,class A7,class A8,class A9> |
| thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6,A7 a7,A8 a8,A9 a9): |
| thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3,a4,a5,a6,a7,a8,a9))) |
| { |
| start_thread(); |
| } |
| |
| void swap(thread& x) |
| { |
| thread_info.swap(x.thread_info); |
| } |
| |
| class id; |
| id get_id() const; |
| |
| |
| bool joinable() const; |
| void join(); |
| bool timed_join(const system_time& wait_until); |
| |
| template<typename TimeDuration> |
| inline bool timed_join(TimeDuration const& rel_time) |
| { |
| return timed_join(get_system_time()+rel_time); |
| } |
| void detach(); |
| |
| static unsigned hardware_concurrency(); |
| |
| typedef detail::thread_data_base::native_handle_type native_handle_type; |
| native_handle_type native_handle(); |
| |
| // backwards compatibility |
| bool operator==(const thread& other) const; |
| bool operator!=(const thread& other) const; |
| |
| static inline void yield() |
| { |
| this_thread::yield(); |
| } |
| |
| static inline void sleep(const system_time& xt) |
| { |
| this_thread::sleep(xt); |
| } |
| |
| // extensions |
| void interrupt(); |
| bool interruption_requested() const; |
| }; |
| |
| inline void swap(thread& lhs,thread& rhs) |
| { |
| return lhs.swap(rhs); |
| } |
| |
| #ifndef BOOST_NO_RVALUE_REFERENCES |
| inline thread&& move(thread& t) |
| { |
| return static_cast<thread&&>(t); |
| } |
| inline thread&& move(thread&& t) |
| { |
| return static_cast<thread&&>(t); |
| } |
| #else |
| inline detail::thread_move_t<thread> move(detail::thread_move_t<thread> t) |
| { |
| return t; |
| } |
| #endif |
| |
| namespace this_thread |
| { |
| thread::id BOOST_THREAD_DECL get_id(); |
| |
| void BOOST_THREAD_DECL interruption_point(); |
| bool BOOST_THREAD_DECL interruption_enabled(); |
| bool BOOST_THREAD_DECL interruption_requested(); |
| |
| inline void sleep(xtime const& abs_time) |
| { |
| sleep(system_time(abs_time)); |
| } |
| } |
| |
| class thread::id |
| { |
| private: |
| detail::thread_data_ptr thread_data; |
| |
| id(detail::thread_data_ptr thread_data_): |
| thread_data(thread_data_) |
| {} |
| friend class thread; |
| friend id BOOST_THREAD_DECL this_thread::get_id(); |
| public: |
| id(): |
| thread_data() |
| {} |
| |
| bool operator==(const id& y) const |
| { |
| return thread_data==y.thread_data; |
| } |
| |
| bool operator!=(const id& y) const |
| { |
| return thread_data!=y.thread_data; |
| } |
| |
| bool operator<(const id& y) const |
| { |
| return thread_data<y.thread_data; |
| } |
| |
| bool operator>(const id& y) const |
| { |
| return y.thread_data<thread_data; |
| } |
| |
| bool operator<=(const id& y) const |
| { |
| return !(y.thread_data<thread_data); |
| } |
| |
| bool operator>=(const id& y) const |
| { |
| return !(thread_data<y.thread_data); |
| } |
| |
| #ifndef BOOST_NO_IOSTREAM |
| #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS |
| template<class charT, class traits> |
| friend std::basic_ostream<charT, traits>& |
| operator<<(std::basic_ostream<charT, traits>& os, const id& x) |
| { |
| if(x.thread_data) |
| { |
| return os<<x.thread_data; |
| } |
| else |
| { |
| return os<<"{Not-any-thread}"; |
| } |
| } |
| #else |
| template<class charT, class traits> |
| std::basic_ostream<charT, traits>& |
| print(std::basic_ostream<charT, traits>& os) const |
| { |
| if(thread_data) |
| { |
| return os<<thread_data; |
| } |
| else |
| { |
| return os<<"{Not-any-thread}"; |
| } |
| } |
| |
| #endif |
| #endif |
| }; |
| |
| #if !defined(BOOST_NO_IOSTREAM) && defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) |
| template<class charT, class traits> |
| std::basic_ostream<charT, traits>& |
| operator<<(std::basic_ostream<charT, traits>& os, const thread::id& x) |
| { |
| return x.print(os); |
| } |
| #endif |
| |
| inline bool thread::operator==(const thread& other) const |
| { |
| return get_id()==other.get_id(); |
| } |
| |
| inline bool thread::operator!=(const thread& other) const |
| { |
| return get_id()!=other.get_id(); |
| } |
| |
| namespace detail |
| { |
| struct thread_exit_function_base |
| { |
| virtual ~thread_exit_function_base() |
| {} |
| virtual void operator()()=0; |
| }; |
| |
| template<typename F> |
| struct thread_exit_function: |
| thread_exit_function_base |
| { |
| F f; |
| |
| thread_exit_function(F f_): |
| f(f_) |
| {} |
| |
| void operator()() |
| { |
| f(); |
| } |
| }; |
| |
| void BOOST_THREAD_DECL add_thread_exit_function(thread_exit_function_base*); |
| } |
| |
| namespace this_thread |
| { |
| template<typename F> |
| void at_thread_exit(F f) |
| { |
| detail::thread_exit_function_base* const thread_exit_func=detail::heap_new<detail::thread_exit_function<F> >(f); |
| detail::add_thread_exit_function(thread_exit_func); |
| } |
| } |
| } |
| |
| #ifdef BOOST_MSVC |
| #pragma warning(pop) |
| #endif |
| |
| #include <boost/config/abi_suffix.hpp> |
| |
| #endif |