Chris@16: #ifndef BOOST_THREAD_PTHREAD_THREAD_DATA_HPP Chris@16: #define BOOST_THREAD_PTHREAD_THREAD_DATA_HPP 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 2008 Anthony Williams Chris@16: // (C) Copyright 2011-2012 Vicente J. Botet Escriba Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@101: #include Chris@101: Chris@16: #include Chris@16: #ifdef BOOST_THREAD_USES_CHRONO Chris@16: #include Chris@16: #endif Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: #include Chris@16: Chris@16: #ifdef BOOST_MSVC Chris@16: #pragma warning(push) Chris@16: #pragma warning(disable:4251) Chris@16: #endif Chris@16: Chris@16: namespace boost Chris@16: { Chris@16: class condition_variable; Chris@16: class mutex; Chris@16: Chris@16: class thread_attributes { Chris@16: public: Chris@16: thread_attributes() BOOST_NOEXCEPT { Chris@16: val_.stack_size = 0; Chris@16: //val_.lpThreadAttributes=0; Chris@16: } Chris@16: ~thread_attributes() { Chris@16: } Chris@16: // stack size Chris@16: void set_stack_size(std::size_t size) BOOST_NOEXCEPT { Chris@16: val_.stack_size = size; Chris@16: } Chris@16: Chris@16: std::size_t get_stack_size() const BOOST_NOEXCEPT { Chris@16: return val_.stack_size; Chris@16: } Chris@16: Chris@16: //void set_security(LPSECURITY_ATTRIBUTES lpThreadAttributes) Chris@16: //{ Chris@16: // val_.lpThreadAttributes=lpThreadAttributes; Chris@16: //} Chris@16: //LPSECURITY_ATTRIBUTES get_security() Chris@16: //{ Chris@16: // return val_.lpThreadAttributes; Chris@16: //} Chris@16: Chris@16: struct win_attrs { Chris@16: std::size_t stack_size; Chris@16: //LPSECURITY_ATTRIBUTES lpThreadAttributes; Chris@16: }; Chris@16: typedef win_attrs native_handle_type; Chris@16: native_handle_type* native_handle() {return &val_;} Chris@16: const native_handle_type* native_handle() const {return &val_;} Chris@16: Chris@16: private: Chris@16: win_attrs val_; Chris@16: }; Chris@16: Chris@16: namespace detail Chris@16: { Chris@16: struct shared_state_base; Chris@16: struct tss_cleanup_function; Chris@16: struct thread_exit_callback_node; Chris@16: struct tss_data_node Chris@16: { Chris@16: boost::shared_ptr func; Chris@16: void* value; Chris@16: Chris@16: tss_data_node(boost::shared_ptr func_, Chris@16: void* value_): Chris@16: func(func_),value(value_) Chris@16: {} Chris@16: }; Chris@16: Chris@16: struct thread_data_base; Chris@16: void intrusive_ptr_add_ref(thread_data_base * p); Chris@16: void intrusive_ptr_release(thread_data_base * p); Chris@16: Chris@16: struct BOOST_THREAD_DECL thread_data_base Chris@16: { Chris@16: long count; Chris@101: Chris@101: // Win32 threading APIs are not available in store apps so Chris@101: // use abstraction on top of Windows::System::Threading. Chris@101: #if BOOST_PLAT_WINDOWS_RUNTIME Chris@101: detail::win32::scoped_winrt_thread thread_handle; Chris@101: #else Chris@16: detail::win32::handle_manager thread_handle; Chris@101: #endif Chris@101: Chris@16: boost::detail::thread_exit_callback_node* thread_exit_callbacks; Chris@101: unsigned id; Chris@16: std::map tss_data; Chris@16: typedef std::vector Chris@16: //, hidden_allocator > Chris@16: > notify_list_t; Chris@16: notify_list_t notify; Chris@16: Chris@16: typedef std::vector > async_states_t; Chris@16: async_states_t async_states_; Chris@16: //#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS Chris@16: // These data must be at the end so that the access to the other fields doesn't change Chris@16: // when BOOST_THREAD_PROVIDES_INTERRUPTIONS is defined Chris@16: // Another option is to have them always Chris@16: detail::win32::handle_manager interruption_handle; Chris@16: bool interruption_enabled; Chris@16: //#endif Chris@16: Chris@16: thread_data_base(): Chris@101: count(0), Chris@101: thread_handle(), Chris@101: thread_exit_callbacks(0), Chris@16: id(0), Chris@101: tss_data(), Chris@16: notify(), Chris@16: async_states_() Chris@16: //#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS Chris@16: , interruption_handle(create_anonymous_event(detail::win32::manual_reset_event,detail::win32::event_initially_reset)) Chris@16: , interruption_enabled(true) Chris@16: //#endif Chris@16: {} Chris@16: virtual ~thread_data_base(); Chris@16: Chris@16: friend void intrusive_ptr_add_ref(thread_data_base * p) Chris@16: { Chris@16: BOOST_INTERLOCKED_INCREMENT(&p->count); Chris@16: } Chris@16: Chris@16: friend void intrusive_ptr_release(thread_data_base * p) Chris@16: { Chris@16: if(!BOOST_INTERLOCKED_DECREMENT(&p->count)) Chris@16: { Chris@16: detail::heap_delete(p); Chris@16: } Chris@16: } Chris@16: Chris@16: #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS Chris@16: void interrupt() Chris@16: { Chris@16: BOOST_VERIFY(detail::win32::SetEvent(interruption_handle)!=0); Chris@16: } Chris@16: #endif Chris@16: typedef detail::win32::handle native_handle_type; Chris@16: Chris@16: virtual void run()=0; Chris@16: Chris@16: virtual void notify_all_at_thread_exit(condition_variable* cv, mutex* m) Chris@16: { Chris@16: notify.push_back(std::pair(cv, m)); Chris@16: } Chris@16: Chris@16: void make_ready_at_thread_exit(shared_ptr as) Chris@16: { Chris@16: async_states_.push_back(as); Chris@16: } Chris@16: Chris@16: }; Chris@16: BOOST_THREAD_DECL thread_data_base* get_current_thread_data(); Chris@16: Chris@16: typedef boost::intrusive_ptr thread_data_ptr; Chris@16: Chris@16: struct BOOST_SYMBOL_VISIBLE timeout Chris@16: { Chris@16: win32::ticks_type start; Chris@16: uintmax_t milliseconds; Chris@16: bool relative; Chris@16: boost::system_time abs_time; Chris@16: Chris@16: static unsigned long const max_non_infinite_wait=0xfffffffe; Chris@16: Chris@16: timeout(uintmax_t milliseconds_): Chris@101: start(win32::GetTickCount64_()()), Chris@16: milliseconds(milliseconds_), Chris@101: relative(true) Chris@101: //, Chris@101: // abs_time(boost::get_system_time()) Chris@16: {} Chris@16: Chris@16: timeout(boost::system_time const& abs_time_): Chris@101: start(win32::GetTickCount64_()()), Chris@16: milliseconds(0), Chris@16: relative(false), Chris@16: abs_time(abs_time_) Chris@16: {} Chris@16: Chris@16: struct BOOST_SYMBOL_VISIBLE remaining_time Chris@16: { Chris@16: bool more; Chris@16: unsigned long milliseconds; Chris@16: Chris@16: remaining_time(uintmax_t remaining): Chris@16: more(remaining>max_non_infinite_wait), Chris@16: milliseconds(more?max_non_infinite_wait:(unsigned long)remaining) Chris@16: {} Chris@16: }; Chris@16: Chris@16: remaining_time remaining_milliseconds() const Chris@16: { Chris@16: if(is_sentinel()) Chris@16: { Chris@16: return remaining_time(win32::infinite); Chris@16: } Chris@16: else if(relative) Chris@16: { Chris@101: win32::ticks_type const now=win32::GetTickCount64_()(); Chris@16: win32::ticks_type const elapsed=now-start; Chris@16: return remaining_time((elapsed Chris@16: inline BOOST_SYMBOL_VISIBLE void sleep(TimeDuration const& rel_time) Chris@16: { Chris@16: interruptible_wait(detail::pin_to_zero(rel_time.total_milliseconds())); Chris@16: } Chris@16: inline BOOST_SYMBOL_VISIBLE void sleep(system_time const& abs_time) Chris@16: { Chris@16: interruptible_wait(abs_time); Chris@16: } Chris@16: #ifdef BOOST_THREAD_USES_CHRONO Chris@16: inline void BOOST_SYMBOL_VISIBLE sleep_for(const chrono::nanoseconds& ns) Chris@16: { Chris@16: interruptible_wait(chrono::duration_cast(ns).count()); Chris@16: } Chris@16: #endif Chris@101: namespace no_interruption_point Chris@101: { Chris@101: bool BOOST_THREAD_DECL non_interruptible_wait(detail::win32::handle handle_to_wait_for,detail::timeout target_time); Chris@101: inline void non_interruptible_wait(uintmax_t milliseconds) Chris@101: { Chris@101: non_interruptible_wait(detail::win32::invalid_handle_value,milliseconds); Chris@101: } Chris@101: inline BOOST_SYMBOL_VISIBLE void non_interruptible_wait(system_time const& abs_time) Chris@101: { Chris@101: non_interruptible_wait(detail::win32::invalid_handle_value,abs_time); Chris@101: } Chris@101: template Chris@101: inline BOOST_SYMBOL_VISIBLE void sleep(TimeDuration const& rel_time) Chris@101: { Chris@101: non_interruptible_wait(detail::pin_to_zero(rel_time.total_milliseconds())); Chris@101: } Chris@101: inline BOOST_SYMBOL_VISIBLE void sleep(system_time const& abs_time) Chris@101: { Chris@101: non_interruptible_wait(abs_time); Chris@101: } Chris@101: #ifdef BOOST_THREAD_USES_CHRONO Chris@101: inline void BOOST_SYMBOL_VISIBLE sleep_for(const chrono::nanoseconds& ns) Chris@101: { Chris@101: non_interruptible_wait(chrono::duration_cast(ns).count()); Chris@101: } Chris@101: #endif Chris@101: } Chris@16: } Chris@16: Chris@16: } Chris@16: Chris@16: #ifdef BOOST_MSVC Chris@16: #pragma warning(pop) Chris@16: #endif Chris@16: Chris@16: #include Chris@16: Chris@16: #endif