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 2007 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: #include Chris@16: #include Chris@16: Chris@16: #include Chris@16: #include 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: #if defined(__ANDROID__) Chris@101: # ifndef PAGE_SIZE Chris@101: # define PAGE_SIZE 4096 Chris@101: # endif Chris@16: #endif Chris@16: Chris@16: #include Chris@16: #include Chris@16: Chris@16: #include Chris@16: Chris@16: namespace boost Chris@16: { Chris@16: class thread_attributes { Chris@16: public: Chris@16: thread_attributes() BOOST_NOEXCEPT { Chris@16: int res = pthread_attr_init(&val_); Chris@16: BOOST_VERIFY(!res && "pthread_attr_init failed"); Chris@16: } Chris@16: ~thread_attributes() { Chris@16: int res = pthread_attr_destroy(&val_); Chris@16: BOOST_VERIFY(!res && "pthread_attr_destroy failed"); Chris@16: } Chris@16: // stack Chris@16: void set_stack_size(std::size_t size) BOOST_NOEXCEPT { Chris@16: if (size==0) return; Chris@16: std::size_t page_size = getpagesize(); Chris@16: #ifdef PTHREAD_STACK_MIN Chris@16: if (size 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: typedef boost::shared_ptr thread_data_ptr; Chris@16: Chris@16: struct BOOST_THREAD_DECL thread_data_base: Chris@16: enable_shared_from_this Chris@16: { Chris@16: thread_data_ptr self; Chris@16: pthread_t thread_handle; Chris@16: boost::mutex data_mutex; Chris@16: boost::condition_variable done_condition; Chris@16: boost::mutex sleep_mutex; Chris@16: boost::condition_variable sleep_condition; Chris@16: bool done; Chris@16: bool join_started; Chris@16: bool joined; Chris@16: boost::detail::thread_exit_callback_node* thread_exit_callbacks; Chris@16: std::map tss_data; Chris@16: Chris@101: //#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS Chris@101: // These data must be at the end so that the access to the other fields doesn't change Chris@101: // when BOOST_THREAD_PROVIDES_INTERRUPTIONS is defined. Chris@101: // Another option is to have them always Chris@16: pthread_mutex_t* cond_mutex; Chris@16: pthread_cond_t* current_cond; Chris@101: //#endif 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: 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: bool interrupt_enabled; Chris@16: bool interrupt_requested; Chris@16: //#endif Chris@16: thread_data_base(): Chris@16: thread_handle(0), Chris@16: done(false),join_started(false),joined(false), Chris@16: thread_exit_callbacks(0), Chris@101: //#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS Chris@16: cond_mutex(0), Chris@16: current_cond(0), Chris@101: //#endif Chris@16: notify(), Chris@16: async_states_() Chris@16: //#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS Chris@16: , interrupt_enabled(true) Chris@16: , interrupt_requested(false) Chris@16: //#endif Chris@16: {} Chris@16: virtual ~thread_data_base(); Chris@16: Chris@16: typedef pthread_t native_handle_type; Chris@16: Chris@16: virtual void run()=0; 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: Chris@16: BOOST_THREAD_DECL thread_data_base* get_current_thread_data(); Chris@16: Chris@16: #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS Chris@16: class interruption_checker Chris@16: { Chris@16: thread_data_base* const thread_info; Chris@16: pthread_mutex_t* m; Chris@16: bool set; Chris@16: Chris@16: void check_for_interruption() Chris@16: { Chris@16: #ifndef BOOST_NO_EXCEPTIONS Chris@16: if(thread_info->interrupt_requested) Chris@16: { Chris@16: thread_info->interrupt_requested=false; Chris@16: throw thread_interrupted(); // BOOST_NO_EXCEPTIONS protected Chris@16: } Chris@16: #endif Chris@16: } Chris@16: Chris@16: void operator=(interruption_checker&); Chris@16: public: Chris@16: explicit interruption_checker(pthread_mutex_t* cond_mutex,pthread_cond_t* cond): Chris@16: thread_info(detail::get_current_thread_data()),m(cond_mutex), Chris@16: set(thread_info && thread_info->interrupt_enabled) Chris@16: { Chris@16: if(set) Chris@16: { Chris@16: lock_guard guard(thread_info->data_mutex); Chris@16: check_for_interruption(); Chris@16: thread_info->cond_mutex=cond_mutex; Chris@16: thread_info->current_cond=cond; Chris@16: BOOST_VERIFY(!pthread_mutex_lock(m)); Chris@16: } Chris@16: else Chris@16: { Chris@16: BOOST_VERIFY(!pthread_mutex_lock(m)); Chris@16: } Chris@16: } Chris@16: ~interruption_checker() Chris@16: { Chris@16: if(set) Chris@16: { Chris@16: BOOST_VERIFY(!pthread_mutex_unlock(m)); Chris@16: lock_guard guard(thread_info->data_mutex); Chris@16: thread_info->cond_mutex=NULL; Chris@16: thread_info->current_cond=NULL; Chris@16: } Chris@16: else Chris@16: { Chris@16: BOOST_VERIFY(!pthread_mutex_unlock(m)); Chris@16: } Chris@16: } Chris@16: }; Chris@16: #endif Chris@16: } Chris@16: Chris@16: namespace this_thread Chris@16: { Chris@101: namespace hiden Chris@101: { Chris@101: void BOOST_THREAD_DECL sleep_for(const timespec& ts); Chris@101: void BOOST_THREAD_DECL sleep_until(const timespec& ts); Chris@101: } Chris@16: Chris@16: #ifdef BOOST_THREAD_USES_CHRONO Chris@16: #ifdef BOOST_THREAD_SLEEP_FOR_IS_STEADY Chris@16: Chris@16: inline Chris@16: void BOOST_SYMBOL_VISIBLE sleep_for(const chrono::nanoseconds& ns) Chris@16: { Chris@16: return boost::this_thread::hiden::sleep_for(boost::detail::to_timespec(ns)); Chris@16: } Chris@16: #endif Chris@16: #endif // BOOST_THREAD_USES_CHRONO Chris@16: Chris@101: namespace no_interruption_point Chris@101: { Chris@101: namespace hiden Chris@101: { Chris@101: void BOOST_THREAD_DECL sleep_for(const timespec& ts); Chris@101: void BOOST_THREAD_DECL sleep_until(const timespec& ts); Chris@101: } Chris@101: Chris@101: #ifdef BOOST_THREAD_USES_CHRONO Chris@101: #ifdef BOOST_THREAD_SLEEP_FOR_IS_STEADY Chris@101: Chris@101: inline Chris@101: void BOOST_SYMBOL_VISIBLE sleep_for(const chrono::nanoseconds& ns) Chris@101: { Chris@101: return boost::this_thread::no_interruption_point::hiden::sleep_for(boost::detail::to_timespec(ns)); Chris@101: } Chris@101: #endif Chris@101: #endif // BOOST_THREAD_USES_CHRONO Chris@101: Chris@101: } // no_interruption_point Chris@101: Chris@16: void BOOST_THREAD_DECL yield() BOOST_NOEXCEPT; Chris@16: Chris@16: #if defined BOOST_THREAD_USES_DATETIME Chris@16: #ifdef __DECXXX Chris@16: /// Workaround of DECCXX issue of incorrect template substitution Chris@16: template<> Chris@16: #endif Chris@16: inline void sleep(system_time const& abs_time) Chris@16: { Chris@16: return boost::this_thread::hiden::sleep_until(boost::detail::to_timespec(abs_time)); Chris@16: } Chris@16: Chris@16: template Chris@16: inline BOOST_SYMBOL_VISIBLE void sleep(TimeDuration const& rel_time) Chris@16: { Chris@16: this_thread::sleep(get_system_time()+rel_time); Chris@16: } Chris@16: #endif // BOOST_THREAD_USES_DATETIME Chris@16: } // this_thread Chris@16: } Chris@16: Chris@16: #include Chris@16: Chris@16: #endif