Squashed 'boost/' content from commit b4feb19f2

git-subtree-dir: boost
git-subtree-split: b4feb19f287ee92d87a9624b5d36b7cf46aeadeb
This commit is contained in:
Bill Somerville
2018-06-09 21:48:32 +01:00
commit 4ebe6417a5
12444 changed files with 2327021 additions and 0 deletions
+64
View File
@@ -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
+83
View File
@@ -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 //
+90
View File
@@ -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)
{
while (true)
{
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
+846
View File
@@ -0,0 +1,846 @@
// 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
#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)->make_ready();
}
}
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(struct timespec 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))
{
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(const timespec& ts)
{
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 hidden
{
void BOOST_THREAD_DECL sleep_for(const timespec& ts)
{
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.do_wait_for(lk,ts)) {}
}
else
{
boost::this_thread::no_interruption_point::hidden::sleep_for(ts);
}
}
void BOOST_THREAD_DECL sleep_until(const timespec& ts)
{
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.do_wait_until(lk,ts)) {}
}
else
{
boost::this_thread::no_interruption_point::hidden::sleep_until(ts);
}
}
} // hidden
} // 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
#error
timespec ts;
ts.tv_sec= 0;
ts.tv_nsec= 0;
hidden::sleep_for(ts);
# 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(__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);
}
}
}
}
+38
View File
@@ -0,0 +1,38 @@
// (C) Copyright Michael Glassford 2004.
// (C) Copyright 2007 Anthony Williams
// 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>
#if defined(BOOST_HAS_WINTHREADS) && (defined(BOOST_THREAD_BUILD_LIB) || defined(BOOST_THREAD_TEST) || defined(UNDER_CE)) && (!defined(_MSC_VER) || defined(UNDER_CE))
namespace boost
{
/*
This file is a "null" implementation of tss cleanup; it's
purpose is to to eliminate link errors in cases
where it is known that tss cleanup is not needed.
*/
void tss_cleanup_implemented(void)
{
/*
This function's sole purpose is to cause a link error in cases where
automatic tss cleanup is not implemented by Boost.Threads as a
reminder that user code is responsible for calling the necessary
functions at the appropriate times (and for implementing an a
tss_cleanup_implemented() function to eliminate the linker's
missing symbol error).
If Boost.Threads later implements automatic tss cleanup in cases
where it currently doesn't (which is the plan), the duplicate
symbol error will warn the user that their custom solution is no
longer needed and can be removed.
*/
}
}
#endif //defined(BOOST_HAS_WINTHREADS) && defined(BOOST_THREAD_BUILD_LIB) && !defined(_MSC_VER)
File diff suppressed because it is too large Load Diff
+85
View File
@@ -0,0 +1,85 @@
// (C) Copyright Michael Glassford 2004.
// 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/detail/winapi/config.hpp>
#include <boost/thread/detail/config.hpp>
#if defined(BOOST_HAS_WINTHREADS) && defined(BOOST_THREAD_BUILD_DLL)
#include <boost/thread/detail/tss_hooks.hpp>
#include <windows.h>
#if defined(__BORLANDC__)
extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE /*hInstance*/, DWORD dwReason, LPVOID /*lpReserved*/)
#elif defined(_WIN32_WCE)
extern "C" BOOL WINAPI DllMain(HANDLE /*hInstance*/, DWORD dwReason, LPVOID /*lpReserved*/)
#else
extern "C" BOOL WINAPI DllMain(HINSTANCE /*hInstance*/, DWORD dwReason, LPVOID /*lpReserved*/)
#endif
{
switch(dwReason)
{
case DLL_PROCESS_ATTACH:
{
boost::on_process_enter();
boost::on_thread_enter();
break;
}
case DLL_THREAD_ATTACH:
{
boost::on_thread_enter();
break;
}
case DLL_THREAD_DETACH:
{
boost::on_thread_exit();
break;
}
case DLL_PROCESS_DETACH:
{
boost::on_thread_exit();
boost::on_process_exit();
break;
}
}
return TRUE;
}
namespace boost
{
void tss_cleanup_implemented()
{
/*
This function's sole purpose is to cause a link error in cases where
automatic tss cleanup is not implemented by Boost.Threads as a
reminder that user code is responsible for calling the necessary
functions at the appropriate times (and for implementing an a
tss_cleanup_implemented() function to eliminate the linker's
missing symbol error).
If Boost.Threads later implements automatic tss cleanup in cases
where it currently doesn't (which is the plan), the duplicate
symbol error will warn the user that their custom solution is no
longer needed and can be removed.
*/
}
}
#else //defined(BOOST_HAS_WINTHREADS) && defined(BOOST_THREAD_BUILD_DLL)
#ifdef _MSC_VER
// Prevent LNK4221 warning with link=static
namespace boost { namespace link_static_warning_inhibit {
extern __declspec(dllexport) void foo() { }
} }
#endif
#endif //defined(BOOST_HAS_WINTHREADS) && defined(BOOST_THREAD_BUILD_DLL)
+325
View File
@@ -0,0 +1,325 @@
// $Id$
// (C) Copyright Aaron W. LaFramboise, Roland Schwarz, Michael Glassford 2004.
// (C) Copyright 2007 Roland Schwarz
// (C) Copyright 2007 Anthony Williams
// (C) Copyright 2007 David Deakins
// 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/detail/winapi/config.hpp>
#include <boost/thread/detail/config.hpp>
#if defined(BOOST_HAS_WINTHREADS) && defined(BOOST_THREAD_BUILD_LIB)
#if (defined(__MINGW32__) && !defined(_WIN64)) || defined(__MINGW64__) || (__MINGW64_VERSION_MAJOR)
#include <boost/thread/detail/tss_hooks.hpp>
#include <windows.h>
#include <cstdlib>
namespace boost
{
void tss_cleanup_implemented() {}
}
namespace {
void NTAPI on_tls_callback(void* , DWORD dwReason, PVOID )
{
switch (dwReason)
{
case DLL_THREAD_DETACH:
{
boost::on_thread_exit();
break;
}
}
}
}
#if defined(__MINGW64__) || (__MINGW64_VERSION_MAJOR) || (__MINGW32_MAJOR_VERSION >3) || \
((__MINGW32_MAJOR_VERSION==3) && (__MINGW32_MINOR_VERSION>=18))
extern "C"
{
PIMAGE_TLS_CALLBACK __crt_xl_tls_callback__ __attribute__ ((section(".CRT$XLB"))) = on_tls_callback;
}
#else
extern "C" {
void (* after_ctors )() __attribute__((section(".ctors"))) = boost::on_process_enter;
void (* before_dtors)() __attribute__((section(".dtors"))) = boost::on_thread_exit;
void (* after_dtors )() __attribute__((section(".dtors.zzz"))) = boost::on_process_exit;
ULONG __tls_index__ = 0;
char __tls_end__ __attribute__((section(".tls$zzz"))) = 0;
char __tls_start__ __attribute__((section(".tls"))) = 0;
PIMAGE_TLS_CALLBACK __crt_xl_start__ __attribute__ ((section(".CRT$XLA"))) = 0;
PIMAGE_TLS_CALLBACK __crt_xl_end__ __attribute__ ((section(".CRT$XLZ"))) = 0;
}
extern "C" const IMAGE_TLS_DIRECTORY32 _tls_used __attribute__ ((section(".rdata$T"))) =
{
(DWORD) &__tls_start__,
(DWORD) &__tls_end__,
(DWORD) &__tls_index__,
(DWORD) (&__crt_xl_start__+1),
(DWORD) 0,
(DWORD) 0
};
#endif
#elif defined(_MSC_VER) && !defined(UNDER_CE)
#include <boost/thread/detail/tss_hooks.hpp>
#include <stdlib.h>
#include <windows.h>
// _pRawDllMainOrig can be defined by including boost/thread/win32/mfc_thread_init.hpp
// into your dll; it ensures that MFC-Dll-initialization will be done properly
// The following code is adapted from the MFC-Dll-init code
/*
* _pRawDllMainOrig MUST be an extern const variable, which will be aliased to
* _pDefaultRawDllMainOrig if no real user definition is present, thanks to the
* alternatename directive.
*/
// work at least with _MSC_VER 1500 (MSVC++ 9.0, VS 2008)
#if (_MSC_VER >= 1500)
extern "C" {
extern BOOL (WINAPI * const _pRawDllMainOrig)(HANDLE, DWORD, LPVOID);
extern BOOL (WINAPI * const _pDefaultRawDllMainOrig)(HANDLE, DWORD, LPVOID) = NULL;
#if defined (_M_IX86)
#pragma comment(linker, "/alternatename:__pRawDllMainOrig=__pDefaultRawDllMainOrig")
#elif defined (_M_X64) || defined (_M_ARM)
#pragma comment(linker, "/alternatename:_pRawDllMainOrig=_pDefaultRawDllMainOrig")
#else /* defined (_M_X64) || defined (_M_ARM) */
#error Unsupported platform
#endif /* defined (_M_X64) || defined (_M_ARM) */
}
#endif
//Definitions required by implementation
#if (_MSC_VER < 1300) || (_MSC_VER > 1900) // 1300 == VC++ 7.0, 1900 == VC++ 14.0
typedef void (__cdecl *_PVFV)();
#define INIRETSUCCESS
#define PVAPI void __cdecl
#else
typedef int (__cdecl *_PVFV)();
#define INIRETSUCCESS 0
#define PVAPI int __cdecl
#endif
typedef void (NTAPI* _TLSCB)(HINSTANCE, DWORD, PVOID);
//Symbols for connection to the runtime environment
extern "C"
{
extern DWORD _tls_used; //the tls directory (located in .rdata segment)
extern _TLSCB __xl_a[], __xl_z[]; //tls initializers */
}
namespace
{
//Forward declarations
static PVAPI on_tls_prepare();
static PVAPI on_process_init();
static PVAPI on_process_term();
static void NTAPI on_tls_callback(HINSTANCE, DWORD, PVOID);
//The .CRT$Xxx information is taken from Codeguru:
//http://www.codeguru.com/Cpp/misc/misc/threadsprocesses/article.php/c6945__2/
#if (_MSC_VER >= 1400)
#pragma section(".CRT$XIU",long,read)
#pragma section(".CRT$XCU",long,read)
#pragma section(".CRT$XTU",long,read)
#pragma section(".CRT$XLC",long,read)
__declspec(allocate(".CRT$XLC")) _TLSCB __xl_ca=on_tls_callback;
__declspec(allocate(".CRT$XIU"))_PVFV p_tls_prepare = on_tls_prepare;
__declspec(allocate(".CRT$XCU"))_PVFV p_process_init = on_process_init;
__declspec(allocate(".CRT$XTU"))_PVFV p_process_term = on_process_term;
#else
#if (_MSC_VER >= 1300) // 1300 == VC++ 7.0
# pragma data_seg(push, old_seg)
#endif
//Callback to run tls glue code first.
//I don't think it is necessary to run it
//at .CRT$XIB level, since we are only
//interested in thread detachement. But
//this could be changed easily if required.
#pragma data_seg(".CRT$XIU")
static _PVFV p_tls_prepare = on_tls_prepare;
#pragma data_seg()
//Callback after all global ctors.
#pragma data_seg(".CRT$XCU")
static _PVFV p_process_init = on_process_init;
#pragma data_seg()
//Callback for tls notifications.
#pragma data_seg(".CRT$XLB")
_TLSCB p_thread_callback = on_tls_callback;
#pragma data_seg()
//Callback for termination.
#pragma data_seg(".CRT$XTU")
static _PVFV p_process_term = on_process_term;
#pragma data_seg()
#if (_MSC_VER >= 1300) // 1300 == VC++ 7.0
# pragma data_seg(pop, old_seg)
#endif
#endif
#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable:4189)
#endif
PVAPI on_tls_prepare()
{
//The following line has an important side effect:
//if the TLS directory is not already there, it will
//be created by the linker. In other words, it forces a tls
//directory to be generated by the linker even when static tls
//(i.e. __declspec(thread)) is not used.
//The volatile should prevent the optimizer
//from removing the reference.
DWORD volatile dw = _tls_used;
#if (_MSC_VER < 1300) // 1300 == VC++ 7.0
_TLSCB* pfbegin = __xl_a;
_TLSCB* pfend = __xl_z;
_TLSCB* pfdst = pfbegin;
//pfdst = (_TLSCB*)_tls_used.AddressOfCallBacks;
//The following loop will merge the address pointers
//into a contiguous area, since the tlssup code seems
//to require this (at least on MSVC 6)
while (pfbegin < pfend)
{
if (*pfbegin != 0)
{
*pfdst = *pfbegin;
++pfdst;
}
++pfbegin;
}
*pfdst = 0;
#endif
return INIRETSUCCESS;
}
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
PVAPI on_process_init()
{
//Schedule on_thread_exit() to be called for the main
//thread before destructors of global objects have been
//called.
//It will not be run when 'quick' exiting the
//library; however, this is the standard behaviour
//for destructors of global objects, so that
//shouldn't be a problem.
atexit(boost::on_thread_exit);
//Call Boost process entry callback here
boost::on_process_enter();
return INIRETSUCCESS;
}
PVAPI on_process_term()
{
boost::on_process_exit();
return INIRETSUCCESS;
}
void NTAPI on_tls_callback(HINSTANCE /*h*/, DWORD dwReason, PVOID /*pv*/)
{
switch (dwReason)
{
case DLL_THREAD_DETACH:
boost::on_thread_exit();
break;
}
}
#if (_MSC_VER >= 1500)
BOOL WINAPI dll_callback(HANDLE hInstance, DWORD dwReason, LPVOID lpReserved)
#else
BOOL WINAPI dll_callback(HANDLE, DWORD dwReason, LPVOID)
#endif
{
switch (dwReason)
{
case DLL_THREAD_DETACH:
boost::on_thread_exit();
break;
case DLL_PROCESS_DETACH:
boost::on_process_exit();
break;
}
#if (_MSC_VER >= 1500)
if( _pRawDllMainOrig )
{
return _pRawDllMainOrig(hInstance, dwReason, lpReserved);
}
#endif
return true;
}
} //namespace
extern "C"
{
extern BOOL (WINAPI * const _pRawDllMain)(HANDLE, DWORD, LPVOID)=&dll_callback;
}
namespace boost
{
void tss_cleanup_implemented()
{
/*
This function's sole purpose is to cause a link error in cases where
automatic tss cleanup is not implemented by Boost.Threads as a
reminder that user code is responsible for calling the necessary
functions at the appropriate times (and for implementing an a
tss_cleanup_implemented() function to eliminate the linker's
missing symbol error).
If Boost.Threads later implements automatic tss cleanup in cases
where it currently doesn't (which is the plan), the duplicate
symbol error will warn the user that their custom solution is no
longer needed and can be removed.
*/
}
}
#endif //defined(_MSC_VER) && !defined(UNDER_CE)
#endif //defined(BOOST_HAS_WINTHREADS) && defined(BOOST_THREAD_BUILD_LIB)