diff options
author | Remko Tronçon <git@el-tramo.be> | 2012-12-23 13:16:26 (GMT) |
---|---|---|
committer | Remko Tronçon <git@el-tramo.be> | 2012-12-23 14:43:26 (GMT) |
commit | 491ddd570a752cf9bda85933bed0c6942e39b1f9 (patch) | |
tree | 10c25c1be8cc08d0497df1dccd56a10fbb30beee /3rdParty/Boost/src/libs/thread/src/win32/thread.cpp | |
parent | da7d7a0ca71b80281aa9ff2526290b61ccb0cc60 (diff) | |
download | swift-491ddd570a752cf9bda85933bed0c6942e39b1f9.zip swift-491ddd570a752cf9bda85933bed0c6942e39b1f9.tar.bz2 |
Update Boost to 1.52.0.
Change-Id: I1e56bea2600bf2ed9c5b3aba8c4f9d2a0f350e77
Diffstat (limited to '3rdParty/Boost/src/libs/thread/src/win32/thread.cpp')
-rw-r--r-- | 3rdParty/Boost/src/libs/thread/src/win32/thread.cpp | 331 |
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 ¤t_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()); + } + } } |