summaryrefslogtreecommitdiffstats
path: root/contrib/restricted/boost/libs/thread/src/pthread/thread.cpp
diff options
context:
space:
mode:
authorneksard <[email protected]>2022-02-10 16:45:33 +0300
committerDaniil Cherednik <[email protected]>2022-02-10 16:45:33 +0300
commit1d9c550e7c38e051d7961f576013a482003a70d9 (patch)
treeb2cc84ee7850122e7ccf51d0ea21e4fa7e7a5685 /contrib/restricted/boost/libs/thread/src/pthread/thread.cpp
parent8f7cf138264e0caa318144bf8a2c950e0b0a8593 (diff)
Restoring authorship annotation for <[email protected]>. Commit 2 of 2.
Diffstat (limited to 'contrib/restricted/boost/libs/thread/src/pthread/thread.cpp')
-rw-r--r--contrib/restricted/boost/libs/thread/src/pthread/thread.cpp1578
1 files changed, 789 insertions, 789 deletions
diff --git a/contrib/restricted/boost/libs/thread/src/pthread/thread.cpp b/contrib/restricted/boost/libs/thread/src/pthread/thread.cpp
index eeec64df5ec..e856e8dcc25 100644
--- a/contrib/restricted/boost/libs/thread/src/pthread/thread.cpp
+++ b/contrib/restricted/boost/libs/thread/src/pthread/thread.cpp
@@ -1,790 +1,790 @@
-// 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>
+// 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>
+
+#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__)
+#error #include <vxCpuLib.h>
#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>
-
-#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__)
-#error #include <vxCpuLib.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 <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();
- }
- for (async_states_t::iterator i = async_states_.begin(), e = async_states_.end();
- i != e; ++i)
- {
- (*i)->notify_deferred();
- }
- }
-
- 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_CXX11
- boost::once_flag current_thread_tls_init_flag;
-#else
- boost::once_flag current_thread_tls_init_flag=BOOST_ONCE_INIT;
-#endif
- pthread_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.func)(current->second.value);
- }
- thread_info->tss_data.erase(current);
- }
- }
- thread_info->self.reset();
- }
- }
- }
-
-#if defined BOOST_THREAD_PATCH
- struct 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(&current_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;
-#endif
- void create_current_thread_tls_key()
- {
- BOOST_VERIFY(!pthread_key_create(&current_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_INTERRUPTIONS
- BOOST_TRY
- {
-#endif
- thread_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
-#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*)
- {}
-
- 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())));
- # else
- BOOST_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
-// xtime xt;
-// xtime_get(&xt, TIME_UTC_);
-// sleep(xt);
-// sleep_for(chrono::milliseconds(0));
-# else
- mutex 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);
- #else
- return (__builtin_popcount(set) );
- #endif
-#elif defined(__GLIBC__)
- return get_nprocs();
-#else
- return 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;
-
- 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();
- }
-#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)();
- 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(!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;
- }
- }
-#endif
-
- thread::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_INTERRUPTIONS
- namespace this_thread
- {
- void interruption_point()
- {
-#ifndef BOOST_NO_EXCEPTIONS
- boost::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;
- }
- }
- }
-#endif
-
- namespace 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 &current_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,
- boost::shared_ptr<tss_cleanup_function> 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(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,
- boost::shared_ptr<tss_cleanup_function> 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->func)(current_node->value);
- }
- if(func || (tss_data!=0))
- {
- 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,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());
- }
- }
-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);
- }
- }
-}
-
-
-
-}
+
+#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 <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();
+ }
+ for (async_states_t::iterator i = async_states_.begin(), e = async_states_.end();
+ i != e; ++i)
+ {
+ (*i)->notify_deferred();
+ }
+ }
+
+ 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_CXX11
+ boost::once_flag current_thread_tls_init_flag;
+#else
+ boost::once_flag current_thread_tls_init_flag=BOOST_ONCE_INIT;
+#endif
+ pthread_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.func)(current->second.value);
+ }
+ thread_info->tss_data.erase(current);
+ }
+ }
+ thread_info->self.reset();
+ }
+ }
+ }
+
+#if defined BOOST_THREAD_PATCH
+ struct 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(&current_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;
+#endif
+ void create_current_thread_tls_key()
+ {
+ BOOST_VERIFY(!pthread_key_create(&current_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_INTERRUPTIONS
+ BOOST_TRY
+ {
+#endif
+ thread_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
+#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*)
+ {}
+
+ 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())));
+ # else
+ BOOST_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
+// xtime xt;
+// xtime_get(&xt, TIME_UTC_);
+// sleep(xt);
+// sleep_for(chrono::milliseconds(0));
+# else
+ mutex 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);
+ #else
+ return (__builtin_popcount(set) );
+ #endif
+#elif defined(__GLIBC__)
+ return get_nprocs();
+#else
+ return 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;
+
+ 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();
+ }
+#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)();
+ 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(!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;
+ }
+ }
+#endif
+
+ thread::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_INTERRUPTIONS
+ namespace this_thread
+ {
+ void interruption_point()
+ {
+#ifndef BOOST_NO_EXCEPTIONS
+ boost::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;
+ }
+ }
+ }
+#endif
+
+ namespace 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 &current_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,
+ boost::shared_ptr<tss_cleanup_function> 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(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,
+ boost::shared_ptr<tss_cleanup_function> 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->func)(current_node->value);
+ }
+ if(func || (tss_data!=0))
+ {
+ 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,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());
+ }
+ }
+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);
+ }
+ }
+}
+
+
+
+}