summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '3rdParty/Boost/src/libs/thread/src/pthread/thread.cpp')
-rw-r--r--3rdParty/Boost/src/libs/thread/src/pthread/thread.cpp232
1 files changed, 172 insertions, 60 deletions
diff --git a/3rdParty/Boost/src/libs/thread/src/pthread/thread.cpp b/3rdParty/Boost/src/libs/thread/src/pthread/thread.cpp
index 187c024..c83eac1 100644
--- a/3rdParty/Boost/src/libs/thread/src/pthread/thread.cpp
+++ b/3rdParty/Boost/src/libs/thread/src/pthread/thread.cpp
@@ -1,20 +1,22 @@
// Copyright (C) 2001-2003
// William E. Kempf
// Copyright (C) 2007-8 Anthony Williams
+// (C) Copyright 2011 Vicente J. Botet Escriba
//
-// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/thread/detail/config.hpp>
#include <boost/thread/thread.hpp>
#include <boost/thread/xtime.hpp>
-#include <boost/thread/condition.hpp>
+#include <boost/thread/condition_variable.hpp>
#include <boost/thread/locks.hpp>
#include <boost/thread/once.hpp>
#include <boost/thread/tss.hpp>
#include <boost/throw_exception.hpp>
-#ifdef __linux__
+
+#ifdef __GLIBC__
#include <sys/sysinfo.h>
#elif defined(__APPLE__) || defined(__FreeBSD__)
#include <sys/types.h>
@@ -23,14 +25,25 @@
#include <unistd.h>
#endif
-#include "timeconv.inl"
+#include "./timeconv.inl"
+
+#pragma GCC diagnostic ignored "-Wreturn-type"
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();
+ }
+ }
+ }
struct thread_exit_callback_node
{
@@ -45,12 +58,16 @@ namespace boost
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"
{
- void tls_destructor(void* data)
+ static void tls_destructor(void* data)
{
boost::detail::thread_data_base* thread_info=static_cast<boost::detail::thread_data_base*>(data);
if(thread_info)
@@ -86,14 +103,31 @@ namespace boost
}
}
}
-
+
+#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()
+ {
+ if (current_thread_tls_init_flag.epoch!=BOOST_ONCE_INITIAL_FLAG_VALUE)
+ {
+ 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);
@@ -106,26 +140,27 @@ namespace boost
BOOST_VERIFY(!pthread_setspecific(current_thread_tls_key,new_data));
}
}
-
+
namespace
{
extern "C"
{
- void* thread_proxy(void* param)
+ static void* thread_proxy(void* param)
{
boost::detail::thread_data_ptr thread_info = static_cast<boost::detail::thread_data_base*>(param)->self;
thread_info->self.reset();
detail::set_current_thread_data(thread_info.get());
- try
+ BOOST_TRY
{
thread_info->run();
}
- catch(thread_interrupted const&)
+ BOOST_CATCH (thread_interrupted const&)
{
}
+ BOOST_CATCH_END
// Removed as it stops the debugger identifying the cause of the exception
// Unhandled exceptions still cause the application to terminate
-// catch(...)
+// BOOST_CATCH(...)
// {
// std::terminate();
// }
@@ -146,9 +181,11 @@ namespace boost
{
interrupt_enabled=false;
}
-
+
void run()
{}
+ void notify_all_at_thread_exit(condition_variable*, mutex*)
+ {}
private:
externally_launched_thread(externally_launched_thread&);
@@ -177,7 +214,7 @@ namespace boost
}
- thread::thread()
+ thread::thread() BOOST_NOEXCEPT
{}
void thread::start_thread()
@@ -187,15 +224,47 @@ namespace boost
if (res != 0)
{
thread_info->self.reset();
- boost::throw_exception(thread_resource_error());
+ boost::throw_exception(thread_resource_error(res, "boost thread: failed in pthread_create"));
}
}
- thread::~thread()
+ void thread::start_thread(const attributes& attr)
{
- detach();
+ 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();
+ boost::throw_exception(thread_resource_error());
+ }
+ int detached_state;
+ res = pthread_attr_getdetachstate(h, &detached_state);
+ if (res != 0)
+ {
+ thread_info->self.reset();
+ boost::throw_exception(thread_resource_error());
+ }
+ 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;
+ }
+ }
+ }
}
+
+
detail::thread_data_ptr thread::get_thread_info BOOST_PREVENT_MACRO_SUBSTITUTION () const
{
return thread_info;
@@ -203,11 +272,15 @@ namespace boost
void thread::join()
{
+ if (this_thread::get_id() == get_id())
+ {
+ boost::throw_exception(thread_resource_error(system::errc::resource_deadlock_would_occur, "boost thread: trying joining itself"));
+ }
detail::thread_data_ptr const local_thread_info=(get_thread_info)();
if(local_thread_info)
{
bool do_join=false;
-
+
{
unique_lock<mutex> lock(local_thread_info->data_mutex);
while(!local_thread_info->done)
@@ -215,7 +288,7 @@ namespace boost
local_thread_info->done_condition.wait(lock);
}
do_join=!local_thread_info->join_started;
-
+
if(do_join)
{
local_thread_info->join_started=true;
@@ -236,32 +309,42 @@ namespace boost
local_thread_info->joined=true;
local_thread_info->done_condition.notify_all();
}
-
+
if(thread_info==local_thread_info)
{
thread_info.reset();
}
}
+ else
+ {
+#ifdef BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED
+ boost::throw_exception(thread_resource_error(system::errc::invalid_argument, "boost thread: thread not joinable"));
+#endif
+ }
}
- bool thread::timed_join(system_time const& wait_until)
+ bool thread::do_try_join_until(struct timespec const &timeout)
{
+ if (this_thread::get_id() == get_id())
+ {
+ boost::throw_exception(thread_resource_error(system::errc::resource_deadlock_would_occur, "boost thread: trying joining itself"));
+ }
detail::thread_data_ptr const local_thread_info=(get_thread_info)();
if(local_thread_info)
{
bool do_join=false;
-
+
{
unique_lock<mutex> lock(local_thread_info->data_mutex);
while(!local_thread_info->done)
{
- if(!local_thread_info->done_condition.timed_wait(lock,wait_until))
+ if(!local_thread_info->done_condition.do_timed_wait(lock,timeout))
{
return false;
}
}
do_join=!local_thread_info->join_started;
-
+
if(do_join)
{
local_thread_info->join_started=true;
@@ -282,16 +365,22 @@ namespace boost
local_thread_info->joined=true;
local_thread_info->done_condition.notify_all();
}
-
+
if(thread_info==local_thread_info)
{
thread_info.reset();
}
+ return true;
+ }
+ else
+ {
+#ifdef BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED
+ boost::throw_exception(thread_resource_error(system::errc::invalid_argument, "boost thread: thread not joinable"));
+#endif
}
- return true;
}
- bool thread::joinable() const
+ bool thread::joinable() const BOOST_NOEXCEPT
{
return (get_thread_info)();
}
@@ -301,7 +390,7 @@ namespace boost
{
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);
@@ -316,20 +405,24 @@ namespace boost
namespace this_thread
{
-
+
+#ifdef __DECXXX
+ /// Workaround of DECCXX issue of incorrect template substitution
+ template<>
+#endif
void sleep(const system_time& st)
{
detail::thread_data_base* const thread_info=detail::get_current_thread_data();
-
+
if(thread_info)
{
unique_lock<mutex> lk(thread_info->sleep_mutex);
- while(thread_info->sleep_condition.timed_wait(lk,st));
+ while(thread_info->sleep_condition.timed_wait(lk,st)) {}
}
else
{
xtime const xt=get_xtime(st);
-
+
for (int foo=0; foo < 5; ++foo)
{
# if defined(BOOST_HAS_PTHREAD_DELAY_NP)
@@ -339,7 +432,7 @@ namespace boost
# elif defined(BOOST_HAS_NANOSLEEP)
timespec ts;
to_timespec_duration(xt, ts);
-
+
// nanosleep takes a timespec that is an offset, not
// an absolute time.
nanosleep(&ts, 0);
@@ -350,14 +443,14 @@ namespace boost
cond.timed_wait(lock, xt);
# endif
xtime cur;
- xtime_get(&cur, TIME_UTC);
+ xtime_get(&cur, TIME_UTC_);
if (xtime_cmp(xt, cur) <= 0)
return;
}
}
}
- void yield()
+ void yield() BOOST_NOEXCEPT
{
# if defined(BOOST_HAS_SCHED_YIELD)
BOOST_VERIFY(!sched_yield());
@@ -365,13 +458,12 @@ namespace boost
BOOST_VERIFY(!pthread_yield());
# else
xtime xt;
- xtime_get(&xt, TIME_UTC);
+ xtime_get(&xt, TIME_UTC_);
sleep(xt);
# endif
}
}
-
- unsigned thread::hardware_concurrency()
+ unsigned thread::hardware_concurrency() BOOST_NOEXCEPT
{
#if defined(PTW32_VERSION) || defined(__hpux)
return pthread_num_processors_np();
@@ -382,15 +474,19 @@ namespace boost
#elif defined(BOOST_HAS_UNISTD_H) && defined(_SC_NPROCESSORS_ONLN)
int const count=sysconf(_SC_NPROCESSORS_ONLN);
return (count>0)?count:0;
-#elif defined(_GNU_SOURCE)
+#elif defined(__GLIBC__)
return get_nprocs();
#else
return 0;
#endif
}
- thread::id thread::get_id() const
+ thread::id thread::get_id() const BOOST_NOEXCEPT
{
+ #if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID
+ //return local_thread_info->thread_handle;
+ return const_cast<thread*>(this)->native_handle();
+ #else
detail::thread_data_ptr const local_thread_info=(get_thread_info)();
if(local_thread_info)
{
@@ -398,8 +494,9 @@ namespace boost
}
else
{
- return id();
+ return id();
}
+ #endif
}
void thread::interrupt()
@@ -417,7 +514,7 @@ namespace boost
}
}
- bool thread::interruption_requested() const
+ bool thread::interruption_requested() const BOOST_NOEXCEPT
{
detail::thread_data_ptr const local_thread_info=(get_thread_info)();
if(local_thread_info)
@@ -444,19 +541,24 @@ namespace boost
return pthread_t();
}
}
-
-
+
+
namespace this_thread
{
- thread::id get_id()
+ thread::id get_id() BOOST_NOEXCEPT
{
+ #if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID
+ return pthread_self();
+ #else
boost::detail::thread_data_base* const thread_info=get_or_make_current_thread_data();
return thread::id(thread_info?thread_info->shared_from_this():detail::thread_data_ptr());
+ #endif
}
void interruption_point()
{
+#ifndef BOOST_NO_EXCEPTIONS
boost::detail::thread_data_base* const thread_info=detail::get_current_thread_data();
if(thread_info && thread_info->interrupt_enabled)
{
@@ -467,15 +569,16 @@ namespace boost
throw thread_interrupted();
}
}
+#endif
}
-
- bool interruption_enabled()
+
+ 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()
+
+ bool interruption_requested() BOOST_NOEXCEPT
{
boost::detail::thread_data_base* const thread_info=detail::get_current_thread_data();
if(!thread_info)
@@ -489,7 +592,7 @@ namespace boost
}
}
- disable_interruption::disable_interruption():
+ disable_interruption::disable_interruption() BOOST_NOEXCEPT:
interruption_was_enabled(interruption_enabled())
{
if(interruption_was_enabled)
@@ -497,8 +600,8 @@ namespace boost
detail::get_current_thread_data()->interrupt_enabled=false;
}
}
-
- disable_interruption::~disable_interruption()
+
+ disable_interruption::~disable_interruption() BOOST_NOEXCEPT
{
if(detail::get_current_thread_data())
{
@@ -506,15 +609,15 @@ namespace boost
}
}
- restore_interruption::restore_interruption(disable_interruption& d)
+ 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()
+
+ restore_interruption::~restore_interruption() BOOST_NOEXCEPT
{
if(detail::get_current_thread_data())
{
@@ -545,7 +648,7 @@ namespace boost
return &current_node->second;
}
}
- return NULL;
+ return 0;
}
void* get_tss_data(void const* key)
@@ -554,7 +657,7 @@ namespace boost
{
return current_node->value;
}
- return NULL;
+ return 0;
}
void add_new_tss_node(void const* key,
@@ -570,7 +673,7 @@ namespace boost
detail::thread_data_base* const current_thread_data(get_or_make_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)
@@ -591,12 +694,21 @@ namespace boost
erase_tss_node(key);
}
}
- else
+ 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());
+ }
+ }
+
}