summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '3rdParty/Boost/src/libs/thread/src/win32/thread.cpp')
-rw-r--r--3rdParty/Boost/src/libs/thread/src/win32/thread.cpp331
1 files changed, 217 insertions, 114 deletions
diff --git a/3rdParty/Boost/src/libs/thread/src/win32/thread.cpp b/3rdParty/Boost/src/libs/thread/src/win32/thread.cpp
index 05c7a6c..5a26f5e 100644
--- a/3rdParty/Boost/src/libs/thread/src/win32/thread.cpp
+++ b/3rdParty/Boost/src/libs/thread/src/win32/thread.cpp
@@ -4,29 +4,60 @@
// (C) Copyright 2007 Anthony Williams
// (C) Copyright 2007 David Deakins
+#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x400
+#endif
+
+#ifndef WINVER
#define WINVER 0x400
+#endif
#include <boost/thread/thread.hpp>
-#include <algorithm>
-#include <windows.h>
-#ifndef UNDER_CE
-#include <process.h>
-#endif
-#include <stdio.h>
#include <boost/thread/once.hpp>
#include <boost/thread/tss.hpp>
+#include <boost/thread/condition_variable.hpp>
+#include <boost/thread/detail/tss_hooks.hpp>
+
#include <boost/assert.hpp>
#include <boost/throw_exception.hpp>
-#include <boost/thread/detail/tss_hooks.hpp>
#include <boost/date_time/posix_time/conversion.hpp>
+#include <memory>
+#include <algorithm>
+#ifndef UNDER_CE
+#include <process.h>
+#endif
+#include <stdio.h>
+#include <windows.h>
+
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();
+ }
+ }
+ }
+ }
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;
- DWORD current_thread_tls_key=0;
+#endif
+#if defined(UNDER_CE)
+ // Windows CE does not define the TLS_OUT_OF_INDEXES constant.
+#define TLS_OUT_OF_INDEXES 0xFFFFFFFF
+#endif
+ DWORD current_thread_tls_key=TLS_OUT_OF_INDEXES;
void create_current_thread_tls_key()
{
@@ -37,16 +68,16 @@ namespace boost
void cleanup_tls_key()
{
- if(current_thread_tls_key)
+ if(current_thread_tls_key!=TLS_OUT_OF_INDEXES)
{
TlsFree(current_thread_tls_key);
- current_thread_tls_key=0;
+ current_thread_tls_key=TLS_OUT_OF_INDEXES;
}
}
detail::thread_data_base* get_current_thread_data()
{
- if(!current_thread_tls_key)
+ if(current_thread_tls_key==TLS_OUT_OF_INDEXES)
{
return 0;
}
@@ -56,13 +87,13 @@ namespace boost
void set_current_thread_data(detail::thread_data_base* new_data)
{
boost::call_once(current_thread_tls_init_flag,create_current_thread_tls_key);
- if(current_thread_tls_key)
+ if(current_thread_tls_key!=TLS_OUT_OF_INDEXES)
BOOST_VERIFY(TlsSetValue(current_thread_tls_key,new_data));
else
boost::throw_exception(thread_resource_error());
}
-#ifdef BOOST_NO_THREADEX
+#ifndef BOOST_HAS_THREADEX
// Windows CE doesn't define _beginthreadex
struct ThreadProxyData
@@ -75,22 +106,25 @@ namespace boost
DWORD WINAPI ThreadProxy(LPVOID args)
{
- ThreadProxyData* data=reinterpret_cast<ThreadProxyData*>(args);
+ std::auto_ptr<ThreadProxyData> data(reinterpret_cast<ThreadProxyData*>(args));
DWORD ret=data->start_address_(data->arglist_);
- delete data;
return ret;
}
-
+
typedef void* uintptr_t;
- inline uintptr_t const _beginthreadex(void* security, unsigned stack_size, unsigned (__stdcall* start_address)(void*),
+ inline uintptr_t _beginthreadex(void* security, unsigned stack_size, unsigned (__stdcall* start_address)(void*),
void* arglist, unsigned initflag, unsigned* thrdaddr)
{
DWORD threadID;
+ ThreadProxyData* data = new ThreadProxyData(start_address,arglist);
HANDLE hthread=CreateThread(static_cast<LPSECURITY_ATTRIBUTES>(security),stack_size,ThreadProxy,
- new ThreadProxyData(start_address,arglist),initflag,&threadID);
- if (hthread!=0)
- *thrdaddr=threadID;
+ data,initflag,&threadID);
+ if (hthread==0) {
+ delete data;
+ return 0;
+ }
+ *thrdaddr=threadID;
return reinterpret_cast<uintptr_t const>(hthread);
}
@@ -111,19 +145,6 @@ namespace boost
{}
};
- struct tss_data_node
- {
- void const* key;
- boost::shared_ptr<boost::detail::tss_cleanup_function> func;
- void* value;
- tss_data_node* next;
-
- tss_data_node(void const* key_,boost::shared_ptr<boost::detail::tss_cleanup_function> func_,void* value_,
- tss_data_node* next_):
- key(key_),func(func_),value(value_),next(next_)
- {}
- };
-
}
namespace
@@ -133,7 +154,7 @@ namespace boost
detail::thread_data_ptr current_thread_data(get_current_thread_data(),false);
if(current_thread_data)
{
- while(current_thread_data->tss_data || current_thread_data->thread_exit_callbacks)
+ while(! current_thread_data->tss_data.empty() || current_thread_data->thread_exit_callbacks)
{
while(current_thread_data->thread_exit_callbacks)
{
@@ -146,36 +167,43 @@ namespace boost
}
boost::detail::heap_delete(current_node);
}
- while(current_thread_data->tss_data)
+ for(std::map<void const*,detail::tss_data_node>::iterator next=current_thread_data->tss_data.begin(),
+ current,
+ end=current_thread_data->tss_data.end();
+ next!=end;)
{
- detail::tss_data_node* const current_node=current_thread_data->tss_data;
- current_thread_data->tss_data=current_node->next;
- if(current_node->func)
+ current=next;
+ ++next;
+ if(current->second.func && (current->second.value!=0))
{
- (*current_node->func)(current_node->value);
+ (*current->second.func)(current->second.value);
}
- boost::detail::heap_delete(current_node);
+ current_thread_data->tss_data.erase(current);
}
}
-
+
set_current_thread_data(0);
}
}
-
+
unsigned __stdcall thread_start_function(void* param)
{
detail::thread_data_base* const thread_info(reinterpret_cast<detail::thread_data_base*>(param));
set_current_thread_data(thread_info);
- try
+#ifndef BOOST_NO_EXCEPTIONS
+ try // BOOST_NO_EXCEPTIONS protected
+#endif
{
thread_info->run();
}
- catch(thread_interrupted const&)
+#ifndef BOOST_NO_EXCEPTIONS
+ catch(thread_interrupted const&) // BOOST_NO_EXCEPTIONS protected
{
}
+#endif
// Removed as it stops the debugger identifying the cause of the exception
// Unhandled exceptions still cause the application to terminate
-// catch(...)
+// catch(...) // BOOST_NO_EXCEPTIONS protected
// {
// std::terminate();
// }
@@ -184,7 +212,7 @@ namespace boost
}
}
- thread::thread()
+ thread::thread() BOOST_NOEXCEPT
{}
void thread::start_thread()
@@ -199,6 +227,19 @@ namespace boost
ResumeThread(thread_info->thread_handle);
}
+ void thread::start_thread(const attributes& attr)
+ {
+ //uintptr_t const new_thread=_beginthreadex(attr.get_security(),attr.get_stack_size(),&thread_start_function,thread_info.get(),CREATE_SUSPENDED,&thread_info->id);
+ uintptr_t const new_thread=_beginthreadex(0,static_cast<unsigned int>(attr.get_stack_size()),&thread_start_function,thread_info.get(),CREATE_SUSPENDED,&thread_info->id);
+ if(!new_thread)
+ {
+ boost::throw_exception(thread_resource_error());
+ }
+ intrusive_ptr_add_ref(thread_info.get());
+ thread_info->thread_handle=(detail::win32::handle)(new_thread);
+ ResumeThread(thread_info->thread_handle);
+ }
+
thread::thread(detail::thread_data_ptr data):
thread_info(data)
{}
@@ -213,9 +254,12 @@ namespace boost
++count;
interruption_enabled=false;
}
-
+
void run()
{}
+ void notify_all_at_thread_exit(condition_variable*, mutex*)
+ {}
+
private:
externally_launched_thread(externally_launched_thread&);
void operator=(externally_launched_thread&);
@@ -224,15 +268,19 @@ namespace boost
void make_external_thread_data()
{
externally_launched_thread* me=detail::heap_new<externally_launched_thread>();
- try
+#ifndef BOOST_NO_EXCEPTIONS
+ try // BOOST_NO_EXCEPTIONS protected
+#endif
{
set_current_thread_data(me);
}
- catch(...)
+#ifndef BOOST_NO_EXCEPTIONS
+ catch(...) // BOOST_NO_EXCEPTIONS protected
{
detail::heap_delete(me);
- throw;
+ throw; // BOOST_NO_EXCEPTIONS protected
}
+#endif
}
detail::thread_data_base* get_or_make_current_thread_data()
@@ -245,48 +293,73 @@ namespace boost
}
return current_thread_data;
}
-
- }
- thread::~thread()
- {
- detach();
}
-
- thread::id thread::get_id() const
+
+ thread::id thread::get_id() const BOOST_NOEXCEPT
{
+ #if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID
+ detail::thread_data_ptr local_thread_info=(get_thread_info)();
+ return local_thread_info?local_thread_info->id:0;
+ //return const_cast<thread*>(this)->native_handle();
+ #else
return thread::id((get_thread_info)());
+ #endif
}
- bool thread::joinable() const
+ bool thread::joinable() const BOOST_NOEXCEPT
{
return (get_thread_info)();
}
-
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 local_thread_info=(get_thread_info)();
if(local_thread_info)
{
this_thread::interruptible_wait(local_thread_info->thread_handle,detail::timeout::sentinel());
release_handle();
}
+ 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(boost::system_time const& wait_until)
{
- detail::thread_data_ptr local_thread_info=(get_thread_info)();
- if(local_thread_info)
- {
- if(!this_thread::interruptible_wait(local_thread_info->thread_handle,get_milliseconds_until(wait_until)))
- {
- return false;
- }
- release_handle();
- }
- return true;
+ return do_try_join_until(get_milliseconds_until(wait_until));
}
-
+
+ bool thread::do_try_join_until(uintmax_t milli)
+ {
+ 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 local_thread_info=(get_thread_info)();
+ if(local_thread_info)
+ {
+ if(!this_thread::interruptible_wait(local_thread_info->thread_handle,milli))
+ {
+ return false;
+ }
+ release_handle();
+ 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
+ }
+ }
+
void thread::detach()
{
release_handle();
@@ -296,7 +369,7 @@ namespace boost
{
thread_info=0;
}
-
+
void thread::interrupt()
{
detail::thread_data_ptr local_thread_info=(get_thread_info)();
@@ -305,20 +378,20 @@ namespace boost
local_thread_info->interrupt();
}
}
-
- bool thread::interruption_requested() const
+
+ bool thread::interruption_requested() const BOOST_NOEXCEPT
{
detail::thread_data_ptr local_thread_info=(get_thread_info)();
return local_thread_info.get() && (detail::win32::WaitForSingleObject(local_thread_info->interruption_handle,0)==0);
}
-
- unsigned thread::hardware_concurrency()
+
+ unsigned thread::hardware_concurrency() BOOST_NOEXCEPT
{
SYSTEM_INFO info={{0}};
GetSystemInfo(&info);
return info.dwNumberOfProcessors;
}
-
+
thread::native_handle_type thread::native_handle()
{
detail::thread_data_ptr local_thread_info=(get_thread_info)();
@@ -369,7 +442,7 @@ namespace boost
target_time.abs_time.time_of_day().ticks_per_second();
if(ticks_per_second>hundred_nanoseconds_in_one_second)
{
- posix_time::time_duration::tick_type const
+ posix_time::time_duration::tick_type const
ticks_per_hundred_nanoseconds=
ticks_per_second/hundred_nanoseconds_in_one_second;
due_time.QuadPart+=
@@ -387,7 +460,7 @@ namespace boost
return due_time;
}
}
-
+
bool interruptible_wait(detail::win32::handle handle_to_wait_for,detail::timeout target_time)
{
@@ -408,10 +481,10 @@ namespace boost
}
detail::win32::handle_manager timer_handle;
-
+
#ifndef UNDER_CE
unsigned const min_timer_wait_period=20;
-
+
if(!target_time.is_sentinel())
{
detail::timeout::remaining_time const time_left=target_time.remaining_milliseconds();
@@ -422,7 +495,7 @@ namespace boost
if(timer_handle!=0)
{
LARGE_INTEGER due_time=get_due_time(target_time);
-
+
bool const set_time_succeeded=SetWaitableTimer(timer_handle,&due_time,0,0,0,false)!=0;
if(set_time_succeeded)
{
@@ -438,17 +511,17 @@ namespace boost
}
}
#endif
-
+
bool const using_timer=timeout_index!=~0u;
detail::timeout::remaining_time time_left(0);
-
+
do
{
if(!using_timer)
{
time_left=target_time.remaining_milliseconds();
}
-
+
if(handle_count)
{
unsigned long const notified_index=detail::win32::WaitForMultipleObjects(handle_count,handles,false,using_timer?INFINITE:time_left.milliseconds);
@@ -482,9 +555,14 @@ namespace boost
return false;
}
- thread::id get_id()
+ thread::id get_id() BOOST_NOEXCEPT
{
+ #if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID
+ //return detail::win32::GetCurrentThread();
+ return detail::win32::GetCurrentThreadId();
+ #else
return thread::id(get_or_make_current_thread_data());
+ #endif
}
void interruption_point()
@@ -495,23 +573,23 @@ namespace boost
throw thread_interrupted();
}
}
-
- bool interruption_enabled()
+
+ bool interruption_enabled() BOOST_NOEXCEPT
{
return get_current_thread_data() && get_current_thread_data()->interruption_enabled;
}
-
- bool interruption_requested()
+
+ bool interruption_requested() BOOST_NOEXCEPT
{
return get_current_thread_data() && (detail::win32::WaitForSingleObject(get_current_thread_data()->interruption_handle,0)==0);
}
- void yield()
+ void yield() BOOST_NOEXCEPT
{
detail::win32::Sleep(0);
}
-
- disable_interruption::disable_interruption():
+
+ disable_interruption::disable_interruption() BOOST_NOEXCEPT:
interruption_was_enabled(interruption_enabled())
{
if(interruption_was_enabled)
@@ -519,8 +597,8 @@ namespace boost
get_current_thread_data()->interruption_enabled=false;
}
}
-
- disable_interruption::~disable_interruption()
+
+ disable_interruption::~disable_interruption() BOOST_NOEXCEPT
{
if(get_current_thread_data())
{
@@ -528,15 +606,15 @@ namespace boost
}
}
- restore_interruption::restore_interruption(disable_interruption& d)
+ restore_interruption::restore_interruption(disable_interruption& d) BOOST_NOEXCEPT
{
if(d.interruption_was_enabled)
{
get_current_thread_data()->interruption_enabled=true;
}
}
-
- restore_interruption::~restore_interruption()
+
+ restore_interruption::~restore_interruption() BOOST_NOEXCEPT
{
if(get_current_thread_data())
{
@@ -561,14 +639,11 @@ namespace boost
detail::thread_data_base* const current_thread_data(get_current_thread_data());
if(current_thread_data)
{
- detail::tss_data_node* current_node=current_thread_data->tss_data;
- while(current_node)
+ 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())
{
- if(current_node->key==key)
- {
- return current_node;
- }
- current_node=current_node->next;
+ return &current_node->second;
}
}
return NULL;
@@ -582,24 +657,44 @@ namespace boost
}
return NULL;
}
-
- void set_tss_data(void const* key,boost::shared_ptr<tss_cleanup_function> func,void* tss_data,bool cleanup_existing)
+
+ 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_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)
{
if(tss_data_node* const current_node=find_tss_data(key))
{
- if(cleanup_existing && current_node->func.get() && current_node->value)
+ if(cleanup_existing && current_node->func && (current_node->value!=0))
{
(*current_node->func)(current_node->value);
}
- current_node->func=func;
- current_node->value=tss_data;
+ if(func || (tss_data!=0))
+ {
+ current_node->func=func;
+ current_node->value=tss_data;
+ }
+ else
+ {
+ erase_tss_node(key);
+ }
}
- else if(func && tss_data)
+ else if(func || (tss_data!=0))
{
- detail::thread_data_base* const current_thread_data(get_or_make_current_thread_data());
- tss_data_node* const new_node=
- heap_new<tss_data_node>(key,func,tss_data,current_thread_data->tss_data);
- current_thread_data->tss_data=new_node;
+ add_new_tss_node(key,func,tss_data);
}
}
}
@@ -619,6 +714,14 @@ namespace boost
boost::run_thread_exit_callbacks();
}
+ BOOST_THREAD_DECL void notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk)
+ {
+ detail::thread_data_base* const current_thread_data(get_current_thread_data());
+ if(current_thread_data)
+ {
+ current_thread_data->notify_all_at_thread_exit(&cond, lk.release());
+ }
+ }
}