#ifndef BOOST_THREAD_PTHREAD_THREAD_DATA_HPP #define BOOST_THREAD_PTHREAD_THREAD_DATA_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 2008 Anthony Williams // (C) Copyright 2011-2012 Vicente J. Botet Escriba #include #include #include #include #include #include #include #ifdef BOOST_THREAD_USES_CHRONO #include #endif #include #include #include #include #ifdef BOOST_MSVC #pragma warning(push) #pragma warning(disable:4251) #endif namespace boost { class condition_variable; class mutex; class thread_attributes { public: thread_attributes() BOOST_NOEXCEPT { val_.stack_size = 0; //val_.lpThreadAttributes=0; } ~thread_attributes() { } // stack size void set_stack_size(std::size_t size) BOOST_NOEXCEPT { val_.stack_size = size; } std::size_t get_stack_size() const BOOST_NOEXCEPT { return val_.stack_size; } //void set_security(LPSECURITY_ATTRIBUTES lpThreadAttributes) //{ // val_.lpThreadAttributes=lpThreadAttributes; //} //LPSECURITY_ATTRIBUTES get_security() //{ // return val_.lpThreadAttributes; //} struct win_attrs { std::size_t stack_size; //LPSECURITY_ATTRIBUTES lpThreadAttributes; }; typedef win_attrs native_handle_type; native_handle_type* native_handle() {return &val_;} const native_handle_type* native_handle() const {return &val_;} private: win_attrs val_; }; namespace detail { struct shared_state_base; struct tss_cleanup_function; struct thread_exit_callback_node; struct tss_data_node { typedef void(*cleanup_func_t)(void*); typedef void(*cleanup_caller_t)(cleanup_func_t, void*); cleanup_caller_t caller; cleanup_func_t func; void* value; tss_data_node(cleanup_caller_t caller_,cleanup_func_t func_,void* value_): caller(caller_),func(func_),value(value_) {} }; struct thread_data_base; void intrusive_ptr_add_ref(thread_data_base * p); void intrusive_ptr_release(thread_data_base * p); struct BOOST_THREAD_DECL thread_data_base { long count; // Win32 threading APIs are not available in store apps so // use abstraction on top of Windows::System::Threading. #if BOOST_PLAT_WINDOWS_RUNTIME detail::win32::scoped_winrt_thread thread_handle; #else detail::win32::handle_manager thread_handle; #endif boost::detail::thread_exit_callback_node* thread_exit_callbacks; unsigned id; std::map tss_data; typedef std::vector //, hidden_allocator > > notify_list_t; notify_list_t notify; //#ifndef BOOST_NO_EXCEPTIONS typedef std::vector > async_states_t; async_states_t async_states_; //#endif //#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS // These data must be at the end so that the access to the other fields doesn't change // when BOOST_THREAD_PROVIDES_INTERRUPTIONS is defined // Another option is to have them always detail::win32::handle_manager interruption_handle; bool interruption_enabled; //#endif thread_data_base(): count(0), thread_handle(), thread_exit_callbacks(0), id(0), tss_data(), notify() //#ifndef BOOST_NO_EXCEPTIONS , async_states_() //#endif //#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS , interruption_handle(create_anonymous_event(detail::win32::manual_reset_event,detail::win32::event_initially_reset)) , interruption_enabled(true) //#endif {} virtual ~thread_data_base(); #if !defined(BOOST_EMBTC) friend void intrusive_ptr_add_ref(thread_data_base * p) { BOOST_INTERLOCKED_INCREMENT(&p->count); } friend void intrusive_ptr_release(thread_data_base * p) { if(!BOOST_INTERLOCKED_DECREMENT(&p->count)) { detail::heap_delete(p); } } #else friend void intrusive_ptr_add_ref(thread_data_base * p); friend void intrusive_ptr_release(thread_data_base * p); #endif #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS void interrupt() { BOOST_VERIFY(winapi::SetEvent(interruption_handle)!=0); } #endif typedef detail::win32::handle native_handle_type; virtual void run()=0; virtual void notify_all_at_thread_exit(condition_variable* cv, mutex* m) { notify.push_back(std::pair(cv, m)); } //#ifndef BOOST_NO_EXCEPTIONS void make_ready_at_thread_exit(shared_ptr as) { async_states_.push_back(as); } //#endif }; #if defined(BOOST_EMBTC) inline void intrusive_ptr_add_ref(thread_data_base * p) { BOOST_INTERLOCKED_INCREMENT(&p->count); } inline void intrusive_ptr_release(thread_data_base * p) { if(!BOOST_INTERLOCKED_DECREMENT(&p->count)) { detail::heap_delete(p); } } #endif BOOST_THREAD_DECL thread_data_base* get_current_thread_data(); typedef boost::intrusive_ptr thread_data_ptr; } namespace this_thread { void BOOST_THREAD_DECL yield() BOOST_NOEXCEPT; bool BOOST_THREAD_DECL interruptible_wait(detail::win32::handle handle_to_wait_for, detail::internal_platform_timepoint const &timeout); #if defined BOOST_THREAD_USES_DATETIME template BOOST_SYMBOL_VISIBLE void sleep(TimeDuration const& rel_time) { interruptible_wait(detail::win32::invalid_handle_value, detail::internal_platform_clock::now() + detail::platform_duration(rel_time)); } inline BOOST_SYMBOL_VISIBLE void sleep(system_time const& abs_time) { const detail::real_platform_timepoint ts(abs_time); detail::platform_duration d(ts - detail::real_platform_clock::now()); while (d > detail::platform_duration::zero()) { d = (std::min)(d, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS)); interruptible_wait(detail::win32::invalid_handle_value, detail::internal_platform_clock::now() + d); d = ts - detail::real_platform_clock::now(); } } #endif #ifdef BOOST_THREAD_USES_CHRONO template void sleep_for(const chrono::duration& d) { interruptible_wait(detail::win32::invalid_handle_value, detail::internal_platform_clock::now() + detail::platform_duration(d)); } template void sleep_until(const chrono::time_point& t) { sleep_for(t - chrono::steady_clock::now()); } template void sleep_until(const chrono::time_point& t) { typedef typename common_type::type common_duration; common_duration d(t - Clock::now()); while (d > common_duration::zero()) { d = (std::min)(d, common_duration(chrono::milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS))); sleep_for(d); d = t - Clock::now(); } } #endif namespace no_interruption_point { bool BOOST_THREAD_DECL non_interruptible_wait(detail::win32::handle handle_to_wait_for, detail::internal_platform_timepoint const &timeout); #if defined BOOST_THREAD_USES_DATETIME template BOOST_SYMBOL_VISIBLE void sleep(TimeDuration const& rel_time) { non_interruptible_wait(detail::win32::invalid_handle_value, detail::internal_platform_clock::now() + detail::platform_duration(rel_time)); } inline BOOST_SYMBOL_VISIBLE void sleep(system_time const& abs_time) { const detail::real_platform_timepoint ts(abs_time); detail::platform_duration d(ts - detail::real_platform_clock::now()); while (d > detail::platform_duration::zero()) { d = (std::min)(d, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS)); non_interruptible_wait(detail::win32::invalid_handle_value, detail::internal_platform_clock::now() + d); d = ts - detail::real_platform_clock::now(); } } #endif #ifdef BOOST_THREAD_USES_CHRONO template void sleep_for(const chrono::duration& d) { non_interruptible_wait(detail::win32::invalid_handle_value, detail::internal_platform_clock::now() + detail::platform_duration(d)); } template void sleep_until(const chrono::time_point& t) { sleep_for(t - chrono::steady_clock::now()); } template void sleep_until(const chrono::time_point& t) { typedef typename common_type::type common_duration; common_duration d(t - Clock::now()); while (d > common_duration::zero()) { d = (std::min)(d, common_duration(chrono::milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS))); sleep_for(d); d = t - Clock::now(); } } #endif } } } #ifdef BOOST_MSVC #pragma warning(pop) #endif #include #endif