diff options
Diffstat (limited to '3rdParty/Boost/src/libs/thread/src/pthread/thread.cpp')
-rw-r--r-- | 3rdParty/Boost/src/libs/thread/src/pthread/thread.cpp | 339 |
1 files changed, 239 insertions, 100 deletions
diff --git a/3rdParty/Boost/src/libs/thread/src/pthread/thread.cpp b/3rdParty/Boost/src/libs/thread/src/pthread/thread.cpp index c83eac1..f218fa8 100644 --- a/3rdParty/Boost/src/libs/thread/src/pthread/thread.cpp +++ b/3rdParty/Boost/src/libs/thread/src/pthread/thread.cpp @@ -1,20 +1,22 @@ // Copyright (C) 2001-2003 // William E. Kempf // Copyright (C) 2007-8 Anthony Williams -// (C) Copyright 2011 Vicente J. Botet Escriba +// (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.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/throw_exception.hpp> +#include <boost/thread/future.hpp> #ifdef __GLIBC__ #include <sys/sysinfo.h> @@ -25,6 +27,15 @@ #include <unistd.h> #endif +#include <boost/algorithm/string/split.hpp> +#include <boost/algorithm/string/trim.hpp> +#include <boost/lexical_cast.hpp> + +#include <fstream> +#include <string> +#include <set> +#include <vector> + #include "./timeconv.inl" #pragma GCC diagnostic ignored "-Wreturn-type" @@ -35,14 +46,17 @@ namespace boost { 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(); } - } + for (async_states_t::iterator i = async_states_.begin(), e = async_states_.end(); + i != e; ++i) + { + (*i)->make_ready(); + } } struct thread_exit_callback_node @@ -74,6 +88,7 @@ namespace boost { 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; @@ -99,7 +114,10 @@ namespace boost thread_info->tss_data.erase(current); } } - thread_info->self.reset(); + if (thread_info) // fixme: should we test this? + { + thread_info->self.reset(); + } } } } @@ -150,38 +168,54 @@ namespace boost boost::detail::thread_data_ptr thread_info = static_cast<boost::detail::thread_data_base*>(param)->self; thread_info->self.reset(); detail::set_current_thread_data(thread_info.get()); +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS BOOST_TRY { +#endif thread_info->run(); +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + } BOOST_CATCH (thread_interrupted const&) { } - BOOST_CATCH_END // 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 +#endif detail::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_INTERRUPTIONS interrupt_enabled=false; +#endif + } + ~externally_launched_thread() { + BOOST_ASSERT(notify.empty()); + notify.clear(); + BOOST_ASSERT(async_states_.empty()); + async_states_.clear(); } - void run() {} void notify_all_at_thread_exit(condition_variable*, mutex*) @@ -192,18 +226,18 @@ namespace boost void operator=(externally_launched_thread&); }; - detail::thread_data_base* make_external_thread_data() + thread_data_base* make_external_thread_data() { - detail::thread_data_base* const me(new externally_launched_thread()); + thread_data_base* const me(detail::heap_new<externally_launched_thread>()); me->self.reset(me); set_current_thread_data(me); return me; } - detail::thread_data_base* get_or_make_current_thread_data() + thread_data_base* get_or_make_current_thread_data() { - detail::thread_data_base* current_thread_data(detail::get_current_thread_data()); + thread_data_base* current_thread_data(get_current_thread_data()); if(!current_thread_data) { current_thread_data=make_external_thread_data(); @@ -217,18 +251,20 @@ namespace boost thread::thread() BOOST_NOEXCEPT {} - void thread::start_thread() + 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(); - boost::throw_exception(thread_resource_error(res, "boost thread: failed in pthread_create")); + return false; +// boost::throw_exception(thread_resource_error(res, "boost thread: failed in pthread_create")); } + return true; } - void thread::start_thread(const attributes& attr) + bool thread::start_thread_noexcept(const attributes& attr) { thread_info->self=thread_info; const attributes::native_handle_type* h = attr.native_handle(); @@ -236,14 +272,16 @@ namespace boost if (res != 0) { thread_info->self.reset(); - boost::throw_exception(thread_resource_error()); + return false; +// boost::throw_exception(thread_resource_error(res, "boost thread: failed in pthread_create")); } int detached_state; res = pthread_attr_getdetachstate(h, &detached_state); if (res != 0) { thread_info->self.reset(); - boost::throw_exception(thread_resource_error()); + return false; +// boost::throw_exception(thread_resource_error(res, "boost thread: failed in pthread_attr_getdetachstate")); } if (PTHREAD_CREATE_DETACHED==detached_state) { @@ -261,6 +299,7 @@ namespace boost } } } + return true; } @@ -270,12 +309,8 @@ namespace boost return thread_info; } - void thread::join() + bool thread::join_noexcept() { - if (this_thread::get_id() == get_id()) - { - boost::throw_exception(thread_resource_error(system::errc::resource_deadlock_would_occur, "boost thread: trying joining itself")); - } detail::thread_data_ptr const local_thread_info=(get_thread_info)(); if(local_thread_info) { @@ -314,21 +349,16 @@ namespace boost { thread_info.reset(); } + return true; } else { -#ifdef BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED - boost::throw_exception(thread_resource_error(system::errc::invalid_argument, "boost thread: thread not joinable")); -#endif + return false; } } - bool thread::do_try_join_until(struct timespec const &timeout) + bool thread::do_try_join_until_noexcept(struct timespec const &timeout, bool& res) { - if (this_thread::get_id() == get_id()) - { - boost::throw_exception(thread_resource_error(system::errc::resource_deadlock_would_occur, "boost thread: trying joining itself")); - } detail::thread_data_ptr const local_thread_info=(get_thread_info)(); if(local_thread_info) { @@ -338,9 +368,10 @@ namespace boost unique_lock<mutex> lock(local_thread_info->data_mutex); while(!local_thread_info->done) { - if(!local_thread_info->done_condition.do_timed_wait(lock,timeout)) + if(!local_thread_info->done_condition.do_wait_until(lock,timeout)) { - return false; + res=false; + return true; } } do_join=!local_thread_info->join_started; @@ -370,19 +401,18 @@ namespace boost { thread_info.reset(); } + res=true; return true; } else { -#ifdef BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED - boost::throw_exception(thread_resource_error(system::errc::invalid_argument, "boost thread: thread not joinable")); -#endif + return false; } } bool thread::joinable() const BOOST_NOEXCEPT { - return (get_thread_info)(); + return (get_thread_info)()?true:false; } @@ -405,61 +435,121 @@ namespace boost namespace this_thread { + namespace no_interruption_point + { + namespace hiden + { + void BOOST_THREAD_DECL sleep_for(const timespec& ts) + { -#ifdef __DECXXX - /// Workaround of DECCXX issue of incorrect template substitution - template<> -#endif - void sleep(const system_time& st) + if (boost::detail::timespec_ge(ts, boost::detail::timespec_zero())) + { + + # if defined(BOOST_HAS_PTHREAD_DELAY_NP) + # if defined(__IBMCPP__) || defined(_AIX) + BOOST_VERIFY(!pthread_delay_np(const_cast<timespec*>(&ts))); + # else + BOOST_VERIFY(!pthread_delay_np(&ts)); + # endif + # elif defined(BOOST_HAS_NANOSLEEP) + // nanosleep takes a timespec that is an offset, not + // an absolute time. + nanosleep(&ts, 0); + # else + mutex mx; + unique_lock<mutex> lock(mx); + condition_variable cond; + cond.do_wait_for(lock, ts); + # endif + } + } + + void BOOST_THREAD_DECL sleep_until(const timespec& ts) + { + timespec now = boost::detail::timespec_now(); + if (boost::detail::timespec_gt(ts, now)) + { + for (int foo=0; foo < 5; ++foo) + { + + # if defined(BOOST_HAS_PTHREAD_DELAY_NP) + timespec d = boost::detail::timespec_minus(ts, now); + BOOST_VERIFY(!pthread_delay_np(&d)); + # elif defined(BOOST_HAS_NANOSLEEP) + // nanosleep takes a timespec that is an offset, not + // an absolute time. + timespec d = boost::detail::timespec_minus(ts, now); + nanosleep(&d, 0); + # else + mutex mx; + unique_lock<mutex> lock(mx); + condition_variable cond; + cond.do_wait_until(lock, ts); + # endif + timespec now2 = boost::detail::timespec_now(); + if (boost::detail::timespec_ge(now2, ts)) + { + return; + } + } + } + } + + } + } + namespace hiden + { + void BOOST_THREAD_DECL sleep_for(const timespec& ts) { - detail::thread_data_base* const thread_info=detail::get_current_thread_data(); + boost::detail::thread_data_base* const thread_info=boost::detail::get_current_thread_data(); if(thread_info) { - unique_lock<mutex> lk(thread_info->sleep_mutex); - while(thread_info->sleep_condition.timed_wait(lk,st)) {} + unique_lock<mutex> lk(thread_info->sleep_mutex); + while( thread_info->sleep_condition.do_wait_for(lk,ts)) {} } else { - xtime const xt=get_xtime(st); + boost::this_thread::no_interruption_point::hiden::sleep_for(ts); + } + } - for (int foo=0; foo < 5; ++foo) - { -# if defined(BOOST_HAS_PTHREAD_DELAY_NP) - timespec ts; - to_timespec_duration(xt, ts); - BOOST_VERIFY(!pthread_delay_np(&ts)); -# elif defined(BOOST_HAS_NANOSLEEP) - timespec ts; - to_timespec_duration(xt, ts); + void BOOST_THREAD_DECL sleep_until(const timespec& ts) + { + boost::detail::thread_data_base* const thread_info=boost::detail::get_current_thread_data(); - // nanosleep takes a timespec that is an offset, not - // an absolute time. - nanosleep(&ts, 0); -# else - mutex mx; - mutex::scoped_lock lock(mx); - condition cond; - cond.timed_wait(lock, xt); -# endif - xtime cur; - xtime_get(&cur, TIME_UTC_); - if (xtime_cmp(xt, cur) <= 0) - return; - } + if(thread_info) + { + unique_lock<mutex> lk(thread_info->sleep_mutex); + while(thread_info->sleep_condition.do_wait_until(lk,ts)) {} + } + else + { + boost::this_thread::no_interruption_point::hiden::sleep_until(ts); } } + } // hiden + } // this_thread + namespace this_thread + { 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 +// xtime xt; +// xtime_get(&xt, TIME_UTC_); +// sleep(xt); +// sleep_for(chrono::milliseconds(0)); # else - xtime xt; - xtime_get(&xt, TIME_UTC_); - sleep(xt); +#error + timespec ts; + ts.tv_sec= 0; + ts.tv_nsec= 0; + hiden::sleep_for(ts); # endif } } @@ -481,24 +571,65 @@ namespace boost #endif } - thread::id thread::get_id() const BOOST_NOEXCEPT + unsigned thread::physical_concurrency() BOOST_NOEXCEPT { - #if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID - //return local_thread_info->thread_handle; - return const_cast<thread*>(this)->native_handle(); - #else - detail::thread_data_ptr const local_thread_info=(get_thread_info)(); - if(local_thread_info) - { - return id(local_thread_info); - } - else - { - return id(); +#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; + + vector<string> key_val(2); + boost::split(key_val, line, boost::is_any_of(":")); + + if (key_val.size() != 2) + return hardware_concurrency(); + + string key = key_val[0]; + string value = key_val[1]; + boost::trim(key); + boost::trim(value); + + if (key == physical_id) { + current_core_entry.first = boost::lexical_cast<unsigned>(value); + continue; + } + + if (key == core_id) { + current_core_entry.second = boost::lexical_cast<unsigned>(value); + 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(); } - #endif +#elif defined(__APPLE__) + int count; + size_t size=sizeof(count); + return sysctlbyname("hw.physicalcpu",&count,&size,NULL,0)?0:count; +#else + return hardware_concurrency(); +#endif } +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS void thread::interrupt() { detail::thread_data_ptr const local_thread_info=(get_thread_info)(); @@ -527,6 +658,7 @@ namespace boost return false; } } +#endif thread::native_handle_type thread::native_handle() { @@ -544,18 +676,9 @@ namespace boost +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS namespace this_thread { - thread::id get_id() BOOST_NOEXCEPT - { - #if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID - return pthread_self(); - #else - boost::detail::thread_data_base* const thread_info=get_or_make_current_thread_data(); - return thread::id(thread_info?thread_info->shared_from_this():detail::thread_data_ptr()); - #endif - } - void interruption_point() { #ifndef BOOST_NO_EXCEPTIONS @@ -625,6 +748,7 @@ namespace boost } } } +#endif namespace detail { @@ -632,7 +756,7 @@ namespace boost { detail::thread_data_base* const current_thread_data(get_or_make_current_thread_data()); thread_exit_callback_node* const new_node= - new thread_exit_callback_node(func,current_thread_data->thread_exit_callbacks); + heap_new<thread_exit_callback_node>(func,current_thread_data->thread_exit_callbacks); current_thread_data->thread_exit_callbacks=new_node; } @@ -670,8 +794,11 @@ namespace boost void erase_tss_node(void const* key) { - detail::thread_data_base* const current_thread_data(get_or_make_current_thread_data()); - current_thread_data->tss_data.erase(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, @@ -700,6 +827,7 @@ namespace boost } } } + 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()); @@ -708,6 +836,17 @@ namespace boost current_thread_data->notify_all_at_thread_exit(&cond, lk.release()); } } +namespace 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); + } + } +} |