diff options
author | bugaevskiy <bugaevskiy@yandex-team.com> | 2022-08-26 16:38:30 +0300 |
---|---|---|
committer | bugaevskiy <bugaevskiy@yandex-team.com> | 2022-08-26 16:38:30 +0300 |
commit | 505ddf87680103d2ee908d9eb05907c7d81b8484 (patch) | |
tree | 74ae5f11bee68a91e066167e838a401e4d387cac /contrib/restricted/boost/thread/src | |
parent | b1cbfc243abcf8461ad3660a5cb70f70706e3fb0 (diff) | |
download | ydb-505ddf87680103d2ee908d9eb05907c7d81b8484.tar.gz |
Reimport boost/thread as a separate library
Diffstat (limited to 'contrib/restricted/boost/thread/src')
4 files changed, 1027 insertions, 0 deletions
diff --git a/contrib/restricted/boost/thread/src/future.cpp b/contrib/restricted/boost/thread/src/future.cpp new file mode 100644 index 00000000000..4aeac94a1b2 --- /dev/null +++ b/contrib/restricted/boost/thread/src/future.cpp @@ -0,0 +1,64 @@ +// (C) Copyright 2012 Vicente J. Botet Escriba +// Use, modification and distribution are subject to 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> +#ifndef BOOST_NO_EXCEPTIONS + + +#include <boost/thread/futures/future_error_code.hpp> +#include <string> + +namespace boost +{ + + namespace thread_detail + { + + class future_error_category : + public boost::system::error_category + { + public: + virtual const char* name() const BOOST_NOEXCEPT; + virtual std::string message(int ev) const; + }; + + const char* + future_error_category::name() const BOOST_NOEXCEPT + { + return "future"; + } + + std::string + future_error_category::message(int ev) const + { + switch (BOOST_SCOPED_ENUM_NATIVE(future_errc)(ev)) + { + case future_errc::broken_promise: + return std::string("The associated promise has been destructed prior " + "to the associated state becoming ready."); + case future_errc::future_already_retrieved: + return std::string("The future has already been retrieved from " + "the promise or packaged_task."); + case future_errc::promise_already_satisfied: + return std::string("The state of the promise has already been set."); + case future_errc::no_state: + return std::string("Operation not permitted on an object without " + "an associated state."); + } + return std::string("unspecified future_errc value\n"); + } + future_error_category future_error_category_var; + } + + BOOST_THREAD_DECL + const system::error_category& + future_category() BOOST_NOEXCEPT + { + return thread_detail::future_error_category_var; + } + +} +#endif + diff --git a/contrib/restricted/boost/thread/src/pthread/once.cpp b/contrib/restricted/boost/thread/src/pthread/once.cpp new file mode 100644 index 00000000000..2395cff6dd1 --- /dev/null +++ b/contrib/restricted/boost/thread/src/pthread/once.cpp @@ -0,0 +1,83 @@ +// Copyright (C) 2007 Anthony Williams +// +// 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> +#ifdef BOOST_THREAD_ONCE_ATOMIC +#include "./once_atomic.cpp" +#else +#define __STDC_CONSTANT_MACROS +#include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp> +#include <boost/thread/once.hpp> +#include <boost/assert.hpp> +#include <boost/throw_exception.hpp> +#include <pthread.h> +#include <stdlib.h> +#include <memory> +#include <string.h> // memcmp. +namespace boost +{ + namespace thread_detail + { + BOOST_THREAD_DECL uintmax_atomic_t once_global_epoch=BOOST_THREAD_DETAIL_UINTMAX_ATOMIC_MAX_C; + BOOST_THREAD_DECL pthread_mutex_t once_epoch_mutex=PTHREAD_MUTEX_INITIALIZER; + BOOST_THREAD_DECL pthread_cond_t once_epoch_cv = PTHREAD_COND_INITIALIZER; + + namespace + { + pthread_key_t epoch_tss_key; + pthread_once_t epoch_tss_key_flag=PTHREAD_ONCE_INIT; + + extern "C" + { + static void delete_epoch_tss_data(void* data) + { + free(data); + } + + static void create_epoch_tss_key() + { + BOOST_VERIFY(!pthread_key_create(&epoch_tss_key,delete_epoch_tss_data)); + } + } + +#if defined BOOST_THREAD_PATCH + const pthread_once_t pthread_once_init_value=PTHREAD_ONCE_INIT; + struct BOOST_THREAD_DECL delete_epoch_tss_key_on_dlclose_t + { + delete_epoch_tss_key_on_dlclose_t() + { + } + ~delete_epoch_tss_key_on_dlclose_t() + { + if(memcmp(&epoch_tss_key_flag, &pthread_once_init_value, sizeof(pthread_once_t))) + { + void* data = pthread_getspecific(epoch_tss_key); + if (data) + delete_epoch_tss_data(data); + pthread_key_delete(epoch_tss_key); + } + } + }; + delete_epoch_tss_key_on_dlclose_t delete_epoch_tss_key_on_dlclose; +#endif + } + + uintmax_atomic_t& get_once_per_thread_epoch() + { + BOOST_VERIFY(!pthread_once(&epoch_tss_key_flag,create_epoch_tss_key)); + void* data=pthread_getspecific(epoch_tss_key); + if(!data) + { + data=malloc(sizeof(thread_detail::uintmax_atomic_t)); + if(!data) BOOST_THROW_EXCEPTION(std::bad_alloc()); + BOOST_VERIFY(!pthread_setspecific(epoch_tss_key,data)); + *static_cast<thread_detail::uintmax_atomic_t*>(data)=BOOST_THREAD_DETAIL_UINTMAX_ATOMIC_MAX_C; + } + return *static_cast<thread_detail::uintmax_atomic_t*>(data); + } + } + +} +#endif // diff --git a/contrib/restricted/boost/thread/src/pthread/once_atomic.cpp b/contrib/restricted/boost/thread/src/pthread/once_atomic.cpp new file mode 100644 index 00000000000..595ad7f1b3d --- /dev/null +++ b/contrib/restricted/boost/thread/src/pthread/once_atomic.cpp @@ -0,0 +1,90 @@ +// (C) Copyright 2013 Andrey Semashev +// (C) Copyright 2013 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) + +//#define __STDC_CONSTANT_MACROS +#include <boost/thread/detail/config.hpp> +#include <boost/thread/once.hpp> +#include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp> +#include <boost/assert.hpp> +#include <boost/static_assert.hpp> +#include <boost/atomic.hpp> +#include <boost/memory_order.hpp> +#include <pthread.h> + +namespace boost +{ + namespace thread_detail + { + + enum flag_states + { + uninitialized, in_progress, initialized + }; + + +#ifndef BOOST_THREAD_PROVIDES_ONCE_CXX11 + BOOST_STATIC_ASSERT_MSG(sizeof(atomic_int_type) == sizeof(atomic_type), "Boost.Thread: unsupported platform"); +#endif + + static pthread_mutex_t once_mutex = PTHREAD_MUTEX_INITIALIZER; + static pthread_cond_t once_cv = PTHREAD_COND_INITIALIZER; + + BOOST_THREAD_DECL bool enter_once_region(once_flag& flag) BOOST_NOEXCEPT + { + atomic_type& f = get_atomic_storage(flag); + if (f.load(memory_order_acquire) != initialized) + { + pthread::pthread_mutex_scoped_lock lk(&once_mutex); + if (f.load(memory_order_acquire) != initialized) + { + for (;;) + { + atomic_int_type expected = uninitialized; + if (f.compare_exchange_strong(expected, in_progress, memory_order_acq_rel, memory_order_acquire)) + { + // We have set the flag to in_progress + return true; + } + else if (expected == initialized) + { + // Another thread managed to complete the initialization + return false; + } + else + { + // Wait until the initialization is complete + //pthread::pthread_mutex_scoped_lock lk(&once_mutex); + BOOST_VERIFY(!pthread_cond_wait(&once_cv, &once_mutex)); + } + } + } + } + return false; + } + + BOOST_THREAD_DECL void commit_once_region(once_flag& flag) BOOST_NOEXCEPT + { + atomic_type& f = get_atomic_storage(flag); + { + pthread::pthread_mutex_scoped_lock lk(&once_mutex); + f.store(initialized, memory_order_release); + } + BOOST_VERIFY(!pthread_cond_broadcast(&once_cv)); + } + + BOOST_THREAD_DECL void rollback_once_region(once_flag& flag) BOOST_NOEXCEPT + { + atomic_type& f = get_atomic_storage(flag); + { + pthread::pthread_mutex_scoped_lock lk(&once_mutex); + f.store(uninitialized, memory_order_release); + } + BOOST_VERIFY(!pthread_cond_broadcast(&once_cv)); + } + + } // namespace thread_detail + +} // namespace boost diff --git a/contrib/restricted/boost/thread/src/pthread/thread.cpp b/contrib/restricted/boost/thread/src/pthread/thread.cpp new file mode 100644 index 00000000000..1be5bae2eb3 --- /dev/null +++ b/contrib/restricted/boost/thread/src/pthread/thread.cpp @@ -0,0 +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> +#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__) +#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(¤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; +#endif + void 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_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 ¤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, + 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); + } + } +} + + + +} |