#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 #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 { boost::shared_ptr func; void* value; tss_data_node(boost::shared_ptr func_, void* value_): 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; detail::win32::handle_manager thread_handle; boost::detail::thread_exit_callback_node* thread_exit_callbacks; std::map tss_data; unsigned id; typedef std::vector //, hidden_allocator > > notify_list_t; notify_list_t notify; typedef std::vector > async_states_t; async_states_t async_states_; //#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(detail::win32::invalid_handle_value), thread_exit_callbacks(0),tss_data(), id(0), notify(), async_states_() //#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(); 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); } } #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS void interrupt() { BOOST_VERIFY(detail::win32::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)); } void make_ready_at_thread_exit(shared_ptr as) { async_states_.push_back(as); } }; BOOST_THREAD_DECL thread_data_base* get_current_thread_data(); typedef boost::intrusive_ptr thread_data_ptr; struct BOOST_SYMBOL_VISIBLE timeout { win32::ticks_type start; uintmax_t milliseconds; bool relative; boost::system_time abs_time; static unsigned long const max_non_infinite_wait=0xfffffffe; timeout(uintmax_t milliseconds_): start(win32::GetTickCount64()()), milliseconds(milliseconds_), relative(true), abs_time(boost::get_system_time()) {} timeout(boost::system_time const& abs_time_): start(win32::GetTickCount64()()), milliseconds(0), relative(false), abs_time(abs_time_) {} struct BOOST_SYMBOL_VISIBLE remaining_time { bool more; unsigned long milliseconds; remaining_time(uintmax_t remaining): more(remaining>max_non_infinite_wait), milliseconds(more?max_non_infinite_wait:(unsigned long)remaining) {} }; remaining_time remaining_milliseconds() const { if(is_sentinel()) { return remaining_time(win32::infinite); } else if(relative) { win32::ticks_type const now=win32::GetTickCount64()(); win32::ticks_type const elapsed=now-start; return remaining_time((elapsed inline BOOST_SYMBOL_VISIBLE void sleep(TimeDuration const& rel_time) { interruptible_wait(detail::pin_to_zero(rel_time.total_milliseconds())); } inline BOOST_SYMBOL_VISIBLE void sleep(system_time const& abs_time) { interruptible_wait(abs_time); } #ifdef BOOST_THREAD_USES_CHRONO inline void BOOST_SYMBOL_VISIBLE sleep_for(const chrono::nanoseconds& ns) { interruptible_wait(chrono::duration_cast(ns).count()); } #endif namespace no_interruption_point { bool BOOST_THREAD_DECL non_interruptible_wait(detail::win32::handle handle_to_wait_for,detail::timeout target_time); inline void non_interruptible_wait(uintmax_t milliseconds) { non_interruptible_wait(detail::win32::invalid_handle_value,milliseconds); } inline BOOST_SYMBOL_VISIBLE void non_interruptible_wait(system_time const& abs_time) { non_interruptible_wait(detail::win32::invalid_handle_value,abs_time); } template inline BOOST_SYMBOL_VISIBLE void sleep(TimeDuration const& rel_time) { non_interruptible_wait(detail::pin_to_zero(rel_time.total_milliseconds())); } inline BOOST_SYMBOL_VISIBLE void sleep(system_time const& abs_time) { non_interruptible_wait(abs_time); } #ifdef BOOST_THREAD_USES_CHRONO inline void BOOST_SYMBOL_VISIBLE sleep_for(const chrono::nanoseconds& ns) { non_interruptible_wait(chrono::duration_cast(ns).count()); } #endif } } } #ifdef BOOST_MSVC #pragma warning(pop) #endif #include #endif