// Copyright (C) 2001-2003// William E. Kempf// Copyright (C) 2007-8 Anthony Williams// (C) Copyright 2011-2012 Vicente J. Botet Escriba//// 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)#include <boost/thread/detail/config.hpp>#include <boost/thread/thread_only.hpp>#if defined BOOST_THREAD_USES_DATETIME#include <boost/thread/xtime.hpp>#endif#include <boost/thread/condition_variable.hpp>#include <boost/thread/locks.hpp>#include <boost/thread/once.hpp>#include <boost/thread/tss.hpp>#include <boost/thread/future.hpp>#include <boost/thread/pthread/pthread_helpers.hpp>#include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp>#include <boost/thread/detail/string_trim.hpp>#include <boost/thread/detail/string_to_unsigned.hpp>#ifdef __GLIBC__#include <sys/sysinfo.h>#elif defined(__APPLE__) || defined(__FreeBSD__)#include <sys/types.h>#include <sys/sysctl.h>#elif defined BOOST_HAS_UNISTD_H#include <unistd.h>#endif#if defined(__VXWORKS__)#include <vxCpuLib.h>#endif#include <fstream>#include <string>#include <set>#include <vector>#include <string.h> // memcmp.namespace boost{namespace detail{thread_data_base::~thread_data_base(){for (notify_list_t::iterator i = notify.begin(), e = notify.end();i != e; ++i){i->second->unlock();i->first->notify_all();}//#ifndef BOOST_NO_EXCEPTIONSfor (async_states_t::iterator i = async_states_.begin(), e = async_states_.end();i != e; ++i){(*i)->notify_deferred();}//#endif}struct thread_exit_callback_node{boost::detail::thread_exit_function_base* func;thread_exit_callback_node* next;thread_exit_callback_node(boost::detail::thread_exit_function_base* func_,thread_exit_callback_node* next_):func(func_),next(next_){}};namespace{#ifdef BOOST_THREAD_PROVIDES_ONCE_CXX11boost::once_flag current_thread_tls_init_flag;#elseboost::once_flag current_thread_tls_init_flag=BOOST_ONCE_INIT;#endifpthread_key_t current_thread_tls_key;extern "C"{static void tls_destructor(void* data){//boost::detail::thread_data_base* thread_info=static_cast<boost::detail::thread_data_base*>(data);boost::detail::thread_data_ptr thread_info = static_cast<boost::detail::thread_data_base*>(data)->shared_from_this();if(thread_info){while(!thread_info->tss_data.empty() || thread_info->thread_exit_callbacks){while(thread_info->thread_exit_callbacks){detail::thread_exit_callback_node* const current_node=thread_info->thread_exit_callbacks;thread_info->thread_exit_callbacks=current_node->next;if(current_node->func){(*current_node->func)();delete current_node->func;}delete current_node;}while (!thread_info->tss_data.empty()){std::map<void const*,detail::tss_data_node>::iterator current= thread_info->tss_data.begin();if(current->second.func && (current->second.value!=0)){(*current->second.caller)(current->second.func,current->second.value);}thread_info->tss_data.erase(current);}}thread_info->self.reset();}}}#if defined BOOST_THREAD_PATCHstruct delete_current_thread_tls_key_on_dlclose_t{delete_current_thread_tls_key_on_dlclose_t(){}~delete_current_thread_tls_key_on_dlclose_t(){const boost::once_flag uninitialized = BOOST_ONCE_INIT;if (memcmp(¤t_thread_tls_init_flag, &uninitialized, sizeof(boost::once_flag))){void* data = pthread_getspecific(current_thread_tls_key);if (data)tls_destructor(data);pthread_key_delete(current_thread_tls_key);}}};delete_current_thread_tls_key_on_dlclose_t delete_current_thread_tls_key_on_dlclose;#endifvoid create_current_thread_tls_key(){BOOST_VERIFY(!pthread_key_create(¤t_thread_tls_key,&tls_destructor));}}boost::detail::thread_data_base* get_current_thread_data(){boost::call_once(current_thread_tls_init_flag,&create_current_thread_tls_key);return (boost::detail::thread_data_base*)pthread_getspecific(current_thread_tls_key);}void set_current_thread_data(detail::thread_data_base* new_data){boost::call_once(current_thread_tls_init_flag,create_current_thread_tls_key);BOOST_VERIFY(!pthread_setspecific(current_thread_tls_key,new_data));}}namespace{extern "C"{static void* thread_proxy(void* param){//boost::detail::thread_data_ptr thread_info = static_cast<boost::detail::thread_data_base*>(param)->self;boost::detail::thread_data_ptr thread_info = static_cast<boost::detail::thread_data_base*>(param)->shared_from_this();thread_info->self.reset();detail::set_current_thread_data(thread_info.get());#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONSBOOST_TRY{#endifthread_info->run();#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS}BOOST_CATCH (thread_interrupted const&){}// Removed as it stops the debugger identifying the cause of the exception// Unhandled exceptions still cause the application to terminate// BOOST_CATCH(...)// {// throw;//// std::terminate();// }BOOST_CATCH_END#endifdetail::tls_destructor(thread_info.get());detail::set_current_thread_data(0);boost::lock_guard<boost::mutex> lock(thread_info->data_mutex);thread_info->done=true;thread_info->done_condition.notify_all();return 0;}}}namespace detail{struct externally_launched_thread:detail::thread_data_base{externally_launched_thread(){#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONSinterrupt_enabled=false;#endif}~externally_launched_thread() {BOOST_ASSERT(notify.empty());notify.clear();//#ifndef BOOST_NO_EXCEPTIONSBOOST_ASSERT(async_states_.empty());async_states_.clear();//#endif}void run(){}void notify_all_at_thread_exit(condition_variable*, mutex*){}private:externally_launched_thread(externally_launched_thread&);void operator=(externally_launched_thread&);};thread_data_base* make_external_thread_data(){thread_data_base* const me(detail::heap_new<externally_launched_thread>());me->self.reset(me);set_current_thread_data(me);return me;}thread_data_base* get_or_make_current_thread_data(){thread_data_base* current_thread_data(get_current_thread_data());if(!current_thread_data){current_thread_data=make_external_thread_data();}return current_thread_data;}}thread::thread() BOOST_NOEXCEPT{}bool thread::start_thread_noexcept(){thread_info->self=thread_info;int const res = pthread_create(&thread_info->thread_handle, 0, &thread_proxy, thread_info.get());if (res != 0){thread_info->self.reset();return false;}return true;}bool thread::start_thread_noexcept(const attributes& attr){thread_info->self=thread_info;const attributes::native_handle_type* h = attr.native_handle();int res = pthread_create(&thread_info->thread_handle, h, &thread_proxy, thread_info.get());if (res != 0){thread_info->self.reset();return false;}int detached_state;res = pthread_attr_getdetachstate(h, &detached_state);if (res != 0){thread_info->self.reset();return false;}if (PTHREAD_CREATE_DETACHED==detached_state){detail::thread_data_ptr local_thread_info;thread_info.swap(local_thread_info);if(local_thread_info){//lock_guard<mutex> lock(local_thread_info->data_mutex);if(!local_thread_info->join_started){//BOOST_VERIFY(!pthread_detach(local_thread_info->thread_handle));local_thread_info->join_started=true;local_thread_info->joined=true;}}}return true;}detail::thread_data_ptr thread::get_thread_info BOOST_PREVENT_MACRO_SUBSTITUTION () const{return thread_info;}bool thread::join_noexcept(){detail::thread_data_ptr const local_thread_info=(get_thread_info)();if(local_thread_info){bool do_join=false;{unique_lock<mutex> lock(local_thread_info->data_mutex);while(!local_thread_info->done){local_thread_info->done_condition.wait(lock);}do_join=!local_thread_info->join_started;if(do_join){local_thread_info->join_started=true;}else{while(!local_thread_info->joined){local_thread_info->done_condition.wait(lock);}}}if(do_join){void* result=0;BOOST_VERIFY(!pthread_join(local_thread_info->thread_handle,&result));lock_guard<mutex> lock(local_thread_info->data_mutex);local_thread_info->joined=true;local_thread_info->done_condition.notify_all();}if(thread_info==local_thread_info){thread_info.reset();}return true;}else{return false;}}bool thread::do_try_join_until_noexcept(detail::internal_platform_timepoint const &timeout, bool& res){detail::thread_data_ptr const local_thread_info=(get_thread_info)();if(local_thread_info){bool do_join=false;{unique_lock<mutex> lock(local_thread_info->data_mutex);while(!local_thread_info->done){if(!local_thread_info->done_condition.do_wait_until(lock,timeout)) break; // timeout occurred}if(!local_thread_info->done){res=false;return true;}do_join=!local_thread_info->join_started;if(do_join){local_thread_info->join_started=true;}else{while(!local_thread_info->joined){local_thread_info->done_condition.wait(lock);}}}if(do_join){void* result=0;BOOST_VERIFY(!pthread_join(local_thread_info->thread_handle,&result));lock_guard<mutex> lock(local_thread_info->data_mutex);local_thread_info->joined=true;local_thread_info->done_condition.notify_all();}if(thread_info==local_thread_info){thread_info.reset();}res=true;return true;}else{return false;}}bool thread::joinable() const BOOST_NOEXCEPT{return (get_thread_info)()?true:false;}void thread::detach(){detail::thread_data_ptr local_thread_info;thread_info.swap(local_thread_info);if(local_thread_info){lock_guard<mutex> lock(local_thread_info->data_mutex);if(!local_thread_info->join_started){BOOST_VERIFY(!pthread_detach(local_thread_info->thread_handle));local_thread_info->join_started=true;local_thread_info->joined=true;}}}namespace this_thread{namespace no_interruption_point{namespace hidden{void BOOST_THREAD_DECL sleep_for_internal(const detail::platform_duration& ts){if (ts > detail::platform_duration::zero()){// Use pthread_delay_np or nanosleep whenever possible here in the no_interruption_point// namespace because they do not provide an interruption point.# if defined(BOOST_HAS_PTHREAD_DELAY_NP)# if defined(__IBMCPP__) || defined(_AIX)BOOST_VERIFY(!pthread_delay_np(const_cast<timespec*>(&ts.getTs())));# elseBOOST_VERIFY(!pthread_delay_np(&ts.getTs()));# endif# elif defined(BOOST_HAS_NANOSLEEP)nanosleep(&ts.getTs(), 0);# else// This should never be reached due to BOOST_THREAD_SLEEP_FOR_IS_STEADY# endif}}}}void yield() BOOST_NOEXCEPT{# if defined(BOOST_HAS_SCHED_YIELD)BOOST_VERIFY(!sched_yield());# elif defined(BOOST_HAS_PTHREAD_YIELD)BOOST_VERIFY(!pthread_yield());//# elif defined BOOST_THREAD_USES_DATETIME// ::boost::xtime xt;// xtime_get(&xt, TIME_UTC_);// sleep(xt);// sleep_for(chrono::milliseconds(0));# elsemutex mx;unique_lock<mutex> lock(mx);condition_variable cond;cond.do_wait_until(lock, detail::internal_platform_clock::now());# endif}}unsigned thread::hardware_concurrency() BOOST_NOEXCEPT{#if defined(PTW32_VERSION) || defined(__hpux)return pthread_num_processors_np();#elif defined(__APPLE__) || defined(__FreeBSD__)int count;size_t size=sizeof(count);return sysctlbyname("hw.ncpu",&count,&size,NULL,0)?0:count;#elif defined(BOOST_HAS_UNISTD_H) && defined(_SC_NPROCESSORS_ONLN)int const count=sysconf(_SC_NPROCESSORS_ONLN);return (count>0)?count:0;#elif defined(__VXWORKS__)cpuset_t set = ::vxCpuEnabledGet();#ifdef __DCC__int i;for( i = 0; set; ++i){set &= set -1;}return(i);#elsereturn (__builtin_popcount(set) );#endif#elif defined(__GLIBC__)return get_nprocs();#elsereturn 0;#endif}unsigned thread::physical_concurrency() BOOST_NOEXCEPT{#ifdef __linux__try {using namespace std;ifstream proc_cpuinfo ("/proc/cpuinfo");const string physical_id("physical id"), core_id("core id");typedef std::pair<unsigned, unsigned> core_entry; // [physical ID, core id]std::set<core_entry> cores;core_entry current_core_entry;string line;while ( getline(proc_cpuinfo, line) ) {if (line.empty())continue;std::size_t i = line.find( ':' );if( i == std::string::npos ){return hardware_concurrency();}std::string key = line.substr( 0, i );std::string value = line.substr( i+1 );key = thread_detail::string_trim( key );value = thread_detail::string_trim( value );if (key == physical_id) {if( !thread_detail::string_to_unsigned( value, current_core_entry.first ) ){return hardware_concurrency();}continue;}if (key == core_id) {if( !thread_detail::string_to_unsigned( value, current_core_entry.second ) ){return hardware_concurrency();}cores.insert(current_core_entry);continue;}}// Fall back to hardware_concurrency() in case// /proc/cpuinfo is formatted differently than we expect.return cores.size() != 0 ? cores.size() : hardware_concurrency();} catch(...) {return hardware_concurrency();}#elif defined(__APPLE__)int count;size_t size=sizeof(count);return sysctlbyname("hw.physicalcpu",&count,&size,NULL,0)?0:count;#elsereturn hardware_concurrency();#endif}#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONSvoid thread::interrupt(){detail::thread_data_ptr const local_thread_info=(get_thread_info)();if(local_thread_info){lock_guard<mutex> lk(local_thread_info->data_mutex);local_thread_info->interrupt_requested=true;if(local_thread_info->current_cond){boost::pthread::pthread_mutex_scoped_lock internal_lock(local_thread_info->cond_mutex);BOOST_VERIFY(!posix::pthread_cond_broadcast(local_thread_info->current_cond));}}}bool thread::interruption_requested() const BOOST_NOEXCEPT{detail::thread_data_ptr const local_thread_info=(get_thread_info)();if(local_thread_info){lock_guard<mutex> lk(local_thread_info->data_mutex);return local_thread_info->interrupt_requested;}else{return false;}}#endifthread::native_handle_type thread::native_handle(){detail::thread_data_ptr const local_thread_info=(get_thread_info)();if(local_thread_info){lock_guard<mutex> lk(local_thread_info->data_mutex);return local_thread_info->thread_handle;}else{return pthread_t();}}#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONSnamespace this_thread{void interruption_point(){#ifndef BOOST_NO_EXCEPTIONSboost::detail::thread_data_base* const thread_info=detail::get_current_thread_data();if(thread_info && thread_info->interrupt_enabled){lock_guard<mutex> lg(thread_info->data_mutex);if(thread_info->interrupt_requested){thread_info->interrupt_requested=false;throw thread_interrupted();}}#endif}bool interruption_enabled() BOOST_NOEXCEPT{boost::detail::thread_data_base* const thread_info=detail::get_current_thread_data();return thread_info && thread_info->interrupt_enabled;}bool interruption_requested() BOOST_NOEXCEPT{boost::detail::thread_data_base* const thread_info=detail::get_current_thread_data();if(!thread_info){return false;}else{lock_guard<mutex> lg(thread_info->data_mutex);return thread_info->interrupt_requested;}}disable_interruption::disable_interruption() BOOST_NOEXCEPT:interruption_was_enabled(interruption_enabled()){if(interruption_was_enabled){detail::get_current_thread_data()->interrupt_enabled=false;}}disable_interruption::~disable_interruption() BOOST_NOEXCEPT{if(detail::get_current_thread_data()){detail::get_current_thread_data()->interrupt_enabled=interruption_was_enabled;}}restore_interruption::restore_interruption(disable_interruption& d) BOOST_NOEXCEPT{if(d.interruption_was_enabled){detail::get_current_thread_data()->interrupt_enabled=true;}}restore_interruption::~restore_interruption() BOOST_NOEXCEPT{if(detail::get_current_thread_data()){detail::get_current_thread_data()->interrupt_enabled=false;}}}#endifnamespace detail{void add_thread_exit_function(thread_exit_function_base* func){detail::thread_data_base* const current_thread_data(get_or_make_current_thread_data());thread_exit_callback_node* const new_node=heap_new<thread_exit_callback_node>(func,current_thread_data->thread_exit_callbacks);current_thread_data->thread_exit_callbacks=new_node;}tss_data_node* find_tss_data(void const* key){detail::thread_data_base* const current_thread_data(get_current_thread_data());if(current_thread_data){std::map<void const*,tss_data_node>::iterator current_node=current_thread_data->tss_data.find(key);if(current_node!=current_thread_data->tss_data.end()){return ¤t_node->second;}}return 0;}void* get_tss_data(void const* key){if(tss_data_node* const current_node=find_tss_data(key)){return current_node->value;}return 0;}void add_new_tss_node(void const* key,detail::tss_data_node::cleanup_caller_t caller,detail::tss_data_node::cleanup_func_t func,void* tss_data){detail::thread_data_base* const current_thread_data(get_or_make_current_thread_data());current_thread_data->tss_data.insert(std::make_pair(key,tss_data_node(caller,func,tss_data)));}void erase_tss_node(void const* key){detail::thread_data_base* const current_thread_data(get_current_thread_data());if(current_thread_data){current_thread_data->tss_data.erase(key);}}void set_tss_data(void const* key,detail::tss_data_node::cleanup_caller_t caller,detail::tss_data_node::cleanup_func_t func,void* tss_data,bool cleanup_existing){if(tss_data_node* const current_node=find_tss_data(key)){if(cleanup_existing && current_node->func && (current_node->value!=0)){(*current_node->caller)(current_node->func,current_node->value);}if(func || (tss_data!=0)){current_node->caller=caller;current_node->func=func;current_node->value=tss_data;}else{erase_tss_node(key);}}else if(func || (tss_data!=0)){add_new_tss_node(key,caller,func,tss_data);}}}BOOST_THREAD_DECL void notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk){detail::thread_data_base* const current_thread_data(detail::get_current_thread_data());if(current_thread_data){current_thread_data->notify_all_at_thread_exit(&cond, lk.release());}}//#ifndef BOOST_NO_EXCEPTIONSnamespace detail {void BOOST_THREAD_DECL make_ready_at_thread_exit(shared_ptr<shared_state_base> as){detail::thread_data_base* const current_thread_data(detail::get_current_thread_data());if(current_thread_data){current_thread_data->make_ready_at_thread_exit(as);}}}//#endif}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。