diff options
author | Tobias Markmann <tm@ayena.de> | 2014-10-19 20:22:58 (GMT) |
---|---|---|
committer | Tobias Markmann <tm@ayena.de> | 2014-10-20 13:49:33 (GMT) |
commit | 6b22dfcf59474dd016a0355a3102a1dd3692d92c (patch) | |
tree | 2b1fd33be433a91e81fee84fdc2bf1b52575d934 /3rdParty/Boost/src/boost/thread/win32 | |
parent | 38b0cb785fea8eae5e48fae56440695fdfd10ee1 (diff) | |
download | swift-6b22dfcf59474dd016a0355a3102a1dd3692d92c.zip swift-6b22dfcf59474dd016a0355a3102a1dd3692d92c.tar.bz2 |
Update Boost in 3rdParty to version 1.56.0.
This updates Boost in our 3rdParty directory to version 1.56.0.
Updated our update.sh script to stop on error.
Changed error reporting in SwiftTools/CrashReporter.cpp to SWIFT_LOG due to
missing include of <iostream> with newer Boost.
Change-Id: I4b35c77de951333979a524097f35f5f83d325edc
Diffstat (limited to '3rdParty/Boost/src/boost/thread/win32')
10 files changed, 1206 insertions, 155 deletions
diff --git a/3rdParty/Boost/src/boost/thread/win32/basic_recursive_mutex.hpp b/3rdParty/Boost/src/boost/thread/win32/basic_recursive_mutex.hpp index e259121..cfdfa04 100644 --- a/3rdParty/Boost/src/boost/thread/win32/basic_recursive_mutex.hpp +++ b/3rdParty/Boost/src/boost/thread/win32/basic_recursive_mutex.hpp @@ -55,22 +55,24 @@ namespace boost { mutex.lock(); BOOST_INTERLOCKED_EXCHANGE(&locking_thread_id,current_thread_id); recursion_count=1; } } +#if defined BOOST_THREAD_USES_DATETIME bool timed_lock(::boost::system_time const& target) { long const current_thread_id=win32::GetCurrentThreadId(); return try_recursive_lock(current_thread_id) || try_timed_lock(current_thread_id,target); } template<typename Duration> bool timed_lock(Duration const& timeout) { return timed_lock(get_system_time()+timeout); } +#endif #ifdef BOOST_THREAD_USES_CHRONO template <class Rep, class Period> bool try_lock_for(const chrono::duration<Rep, Period>& rel_time) { long const current_thread_id=win32::GetCurrentThreadId(); @@ -111,22 +113,24 @@ namespace boost recursion_count=1; return true; } return false; } +#if defined BOOST_THREAD_USES_DATETIME bool try_timed_lock(long current_thread_id,::boost::system_time const& target) { if(mutex.timed_lock(target)) { BOOST_INTERLOCKED_EXCHANGE(&locking_thread_id,current_thread_id); recursion_count=1; return true; } return false; } +#endif template <typename TP> bool try_timed_lock_until(long current_thread_id,TP const& target) { if(mutex.try_lock_until(target)) { BOOST_INTERLOCKED_EXCHANGE(&locking_thread_id,current_thread_id); diff --git a/3rdParty/Boost/src/boost/thread/win32/basic_timed_mutex.hpp b/3rdParty/Boost/src/boost/thread/win32/basic_timed_mutex.hpp index 6a43077..01db033 100644 --- a/3rdParty/Boost/src/boost/thread/win32/basic_timed_mutex.hpp +++ b/3rdParty/Boost/src/boost/thread/win32/basic_timed_mutex.hpp @@ -11,13 +11,15 @@ // http://www.boost.org/LICENSE_1_0.txt) #include <boost/assert.hpp> #include <boost/thread/win32/thread_primitives.hpp> #include <boost/thread/win32/interlocked_read.hpp> #include <boost/thread/thread_time.hpp> +#if defined BOOST_THREAD_USES_DATETIME #include <boost/thread/xtime.hpp> +#endif #include <boost/detail/interlocked.hpp> #ifdef BOOST_THREAD_USES_CHRONO #include <boost/chrono/system_clocks.hpp> #include <boost/chrono/ceil.hpp> #endif #include <boost/config/abi_prefix.hpp> @@ -76,28 +78,33 @@ namespace boost { bool lock_acquired=false; void* const sem=get_event(); do { - BOOST_VERIFY(win32::WaitForSingleObject( - sem,::boost::detail::win32::infinite)==0); + unsigned const retval(win32::WaitForSingleObject(sem, ::boost::detail::win32::infinite)); + BOOST_VERIFY(0 == retval || ::boost::detail::win32::wait_abandoned == retval); +// BOOST_VERIFY(win32::WaitForSingleObject( +// sem,::boost::detail::win32::infinite)==0); clear_waiting_and_try_lock(old_count); lock_acquired=!(old_count&lock_flag_value); } while(!lock_acquired); } } void mark_waiting_and_try_lock(long& old_count) { for(;;) { - long const new_count=(old_count&lock_flag_value)?(old_count+1):(old_count|lock_flag_value); + bool const was_locked=(old_count&lock_flag_value) ? true : false; + long const new_count=was_locked?(old_count+1):(old_count|lock_flag_value); long const current=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&active_count,new_count,old_count); if(current==old_count) { + if(was_locked) + old_count=new_count; break; } old_count=current; } } @@ -115,12 +122,13 @@ namespace boost } old_count=current; } } +#if defined BOOST_THREAD_USES_DATETIME bool timed_lock(::boost::system_time const& wait_until) { if(try_lock()) { return true; } @@ -144,24 +152,23 @@ namespace boost } while(!lock_acquired); } return true; } - template<typename Duration> bool timed_lock(Duration const& timeout) { return timed_lock(get_system_time()+timeout); } bool timed_lock(boost::xtime const& timeout) { return timed_lock(system_time(timeout)); } - +#endif #ifdef BOOST_THREAD_USES_CHRONO template <class Rep, class Period> bool try_lock_for(const chrono::duration<Rep, Period>& rel_time) { return try_lock_until(chrono::steady_clock::now() + rel_time); } diff --git a/3rdParty/Boost/src/boost/thread/win32/condition_variable.hpp b/3rdParty/Boost/src/boost/thread/win32/condition_variable.hpp index 4c893ad..57aaf8c 100644 --- a/3rdParty/Boost/src/boost/thread/win32/condition_variable.hpp +++ b/3rdParty/Boost/src/boost/thread/win32/condition_variable.hpp @@ -8,15 +8,19 @@ #include <boost/thread/win32/thread_primitives.hpp> #include <boost/thread/win32/thread_data.hpp> #include <boost/thread/win32/thread_data.hpp> #include <boost/thread/win32/interlocked_read.hpp> #include <boost/thread/cv_status.hpp> +#if defined BOOST_THREAD_USES_DATETIME #include <boost/thread/xtime.hpp> +#endif #include <boost/thread/mutex.hpp> #include <boost/thread/thread_time.hpp> +#include <boost/thread/lock_guard.hpp> +#include <boost/thread/lock_types.hpp> #include <boost/assert.hpp> #include <boost/intrusive_ptr.hpp> #ifdef BOOST_THREAD_USES_CHRONO #include <boost/chrono/system_clocks.hpp> @@ -184,24 +188,23 @@ namespace boost } } struct entry_manager { entry_ptr const entry; + boost::mutex& internal_mutex; BOOST_THREAD_NO_COPYABLE(entry_manager) - entry_manager(entry_ptr const& entry_): - entry(entry_) + entry_manager(entry_ptr const& entry_, boost::mutex& mutex_): + entry(entry_), internal_mutex(mutex_) {} ~entry_manager() { - if(! entry->is_notified()) - { + boost::lock_guard<boost::mutex> internal_lock(internal_mutex); entry->remove_waiter(); - } } list_entry* operator->() { return entry.get(); } @@ -211,13 +214,13 @@ namespace boost protected: template<typename lock_type> bool do_wait(lock_type& lock,timeout abs_time) { relocker<lock_type> locker(lock); - entry_manager entry(get_wait_entry()); + entry_manager entry(get_wait_entry(), internal_mutex); locker.unlock(); bool woken=false; while(!woken) { @@ -318,25 +321,35 @@ namespace boost void wait(unique_lock<mutex>& m,predicate_type pred) { while(!pred()) wait(m); } +#if defined BOOST_THREAD_USES_DATETIME bool timed_wait(unique_lock<mutex>& m,boost::system_time const& abs_time) { return do_wait(m,abs_time); } bool timed_wait(unique_lock<mutex>& m,boost::xtime const& abs_time) { return do_wait(m,system_time(abs_time)); } template<typename duration_type> bool timed_wait(unique_lock<mutex>& m,duration_type const& wait_duration) { - return do_wait(m,wait_duration.total_milliseconds()); + if (wait_duration.is_pos_infinity()) + { + wait(m); // or do_wait(m,detail::timeout::sentinel()); + return true; + } + if (wait_duration.is_special()) + { + return true; + } + return do_wait(m,wait_duration.total_milliseconds()); } template<typename predicate_type> bool timed_wait(unique_lock<mutex>& m,boost::system_time const& abs_time,predicate_type pred) { return do_wait(m,abs_time,pred); @@ -348,34 +361,42 @@ namespace boost } template<typename duration_type,typename predicate_type> bool timed_wait(unique_lock<mutex>& m,duration_type const& wait_duration,predicate_type pred) { return do_wait(m,wait_duration.total_milliseconds(),pred); } - +#endif #ifdef BOOST_THREAD_USES_CHRONO template <class Clock, class Duration> cv_status wait_until( unique_lock<mutex>& lock, const chrono::time_point<Clock, Duration>& t) { using namespace chrono; - do_wait(lock, ceil<milliseconds>(t-Clock::now()).count()); + chrono::time_point<Clock, Duration> now = Clock::now(); + if (t<=now) { + return cv_status::timeout; + } + do_wait(lock, ceil<milliseconds>(t-now).count()); return Clock::now() < t ? cv_status::no_timeout : cv_status::timeout; } template <class Rep, class Period> cv_status wait_for( unique_lock<mutex>& lock, const chrono::duration<Rep, Period>& d) { using namespace chrono; + if (d<=chrono::duration<Rep, Period>::zero()) { + return cv_status::timeout; + } + steady_clock::time_point c_now = steady_clock::now(); do_wait(lock, ceil<milliseconds>(d).count()); return steady_clock::now() - c_now < d ? cv_status::no_timeout : cv_status::timeout; } @@ -397,13 +418,13 @@ namespace boost bool wait_for( unique_lock<mutex>& lock, const chrono::duration<Rep, Period>& d, Predicate pred) { - return wait_until(lock, chrono::steady_clock::now() + d, pred); + return wait_until(lock, chrono::steady_clock::now() + d, boost::move(pred)); } #endif }; class condition_variable_any: private detail::basic_condition_variable @@ -425,12 +446,13 @@ namespace boost template<typename lock_type,typename predicate_type> void wait(lock_type& m,predicate_type pred) { while(!pred()) wait(m); } +#if defined BOOST_THREAD_USES_DATETIME template<typename lock_type> bool timed_wait(lock_type& m,boost::system_time const& abs_time) { return do_wait(m,abs_time); } @@ -460,33 +482,41 @@ namespace boost template<typename lock_type,typename duration_type,typename predicate_type> bool timed_wait(lock_type& m,duration_type const& wait_duration,predicate_type pred) { return do_wait(m,wait_duration.total_milliseconds(),pred); } +#endif #ifdef BOOST_THREAD_USES_CHRONO template <class lock_type, class Clock, class Duration> cv_status wait_until( lock_type& lock, const chrono::time_point<Clock, Duration>& t) { using namespace chrono; - do_wait(lock, ceil<milliseconds>(t-Clock::now()).count()); + chrono::time_point<Clock, Duration> now = Clock::now(); + if (t<=now) { + return cv_status::timeout; + } + do_wait(lock, ceil<milliseconds>(t-now).count()); return Clock::now() < t ? cv_status::no_timeout : cv_status::timeout; } template <class lock_type, class Rep, class Period> cv_status wait_for( lock_type& lock, const chrono::duration<Rep, Period>& d) { using namespace chrono; + if (d<=chrono::duration<Rep, Period>::zero()) { + return cv_status::timeout; + } steady_clock::time_point c_now = steady_clock::now(); do_wait(lock, ceil<milliseconds>(d).count()); return steady_clock::now() - c_now < d ? cv_status::no_timeout : cv_status::timeout; } @@ -509,13 +539,13 @@ namespace boost bool wait_for( lock_type& lock, const chrono::duration<Rep, Period>& d, Predicate pred) { - return wait_until(lock, chrono::steady_clock::now() + d, pred); + return wait_until(lock, chrono::steady_clock::now() + d, boost::move(pred)); } #endif }; BOOST_THREAD_DECL void notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk); } diff --git a/3rdParty/Boost/src/boost/thread/win32/mutex.hpp b/3rdParty/Boost/src/boost/thread/win32/mutex.hpp index 85a00e2..0154478 100644 --- a/3rdParty/Boost/src/boost/thread/win32/mutex.hpp +++ b/3rdParty/Boost/src/boost/thread/win32/mutex.hpp @@ -5,13 +5,16 @@ // 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/win32/basic_timed_mutex.hpp> #include <boost/thread/exceptions.hpp> -#include <boost/thread/locks.hpp> +#if defined BOOST_THREAD_PROVIDES_NESTED_LOCKS +#include <boost/thread/lock_types.hpp> +#endif +#include <boost/thread/detail/delete.hpp> #include <boost/config/abi_prefix.hpp> namespace boost { namespace detail @@ -30,14 +33,16 @@ namespace boost } ~mutex() { destroy(); } +#if defined BOOST_THREAD_PROVIDES_NESTED_LOCKS typedef unique_lock<mutex> scoped_lock; typedef detail::try_lock_wrapper<mutex> scoped_try_lock; +#endif }; typedef mutex try_mutex; class timed_mutex: public ::boost::detail::basic_timed_mutex @@ -51,15 +56,17 @@ namespace boost ~timed_mutex() { destroy(); } +#if defined BOOST_THREAD_PROVIDES_NESTED_LOCKS typedef unique_lock<timed_mutex> scoped_timed_lock; typedef detail::try_lock_wrapper<timed_mutex> scoped_try_lock; typedef scoped_timed_lock scoped_lock; +#endif }; } #include <boost/config/abi_suffix.hpp> #endif diff --git a/3rdParty/Boost/src/boost/thread/win32/once.hpp b/3rdParty/Boost/src/boost/thread/win32/once.hpp index 3066b50..0ed56a5 100644 --- a/3rdParty/Boost/src/boost/thread/win32/once.hpp +++ b/3rdParty/Boost/src/boost/thread/win32/once.hpp @@ -2,25 +2,30 @@ #define BOOST_THREAD_WIN32_ONCE_HPP // once.hpp // // (C) Copyright 2005-7 Anthony Williams // (C) Copyright 2005 John Maddock -// (C) Copyright 2011-2012 Vicente J. Botet Escriba +// (C) Copyright 2011-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) #include <cstring> #include <cstddef> #include <boost/assert.hpp> #include <boost/static_assert.hpp> #include <boost/detail/interlocked.hpp> #include <boost/thread/win32/thread_primitives.hpp> #include <boost/thread/win32/interlocked_read.hpp> +#include <boost/core/no_exceptions_support.hpp> +#include <boost/thread/detail/move.hpp> +#include <boost/thread/detail/invoke.hpp> + +#include <boost/bind.hpp> #include <boost/config/abi_prefix.hpp> #ifdef BOOST_NO_STDC_NAMESPACE namespace std { @@ -28,26 +33,36 @@ namespace std using ::ptrdiff_t; } #endif namespace boost { + struct once_flag; + namespace detail + { + struct once_context; + + inline bool enter_once_region(once_flag& flag, once_context& ctx) BOOST_NOEXCEPT; + inline void commit_once_region(once_flag& flag, once_context& ctx) BOOST_NOEXCEPT; + inline void rollback_once_region(once_flag& flag, once_context& ctx) BOOST_NOEXCEPT; + } + #ifdef BOOST_THREAD_PROVIDES_ONCE_CXX11 struct once_flag { BOOST_THREAD_NO_COPYABLE(once_flag) BOOST_CONSTEXPR once_flag() BOOST_NOEXCEPT : status(0), count(0) {} - private: long status; long count; - template<typename Function> - friend - void call_once(once_flag& flag,Function f); + private: + friend inline bool enter_once_region(once_flag& flag, detail::once_context& ctx) BOOST_NOEXCEPT; + friend inline void commit_once_region(once_flag& flag, detail::once_context& ctx) BOOST_NOEXCEPT; + friend inline void rollback_once_region(once_flag& flag, detail::once_context& ctx) BOOST_NOEXCEPT; }; #define BOOST_ONCE_INIT once_flag() #else // BOOST_THREAD_PROVIDES_ONCE_CXX11 struct once_flag @@ -56,12 +71,23 @@ namespace boost long count; }; #define BOOST_ONCE_INIT {0,0} #endif // BOOST_THREAD_PROVIDES_ONCE_CXX11 +#if defined BOOST_THREAD_PROVIDES_INVOKE +#define BOOST_THREAD_INVOKE_RET_VOID detail::invoke +#define BOOST_THREAD_INVOKE_RET_VOID_CALL +#elif defined BOOST_THREAD_PROVIDES_INVOKE_RET +#define BOOST_THREAD_INVOKE_RET_VOID detail::invoke<void> +#define BOOST_THREAD_INVOKE_RET_VOID_CALL +#else +#define BOOST_THREAD_INVOKE_RET_VOID boost::bind +#define BOOST_THREAD_INVOKE_RET_VOID_CALL () +#endif + namespace detail { #ifdef BOOST_NO_ANSI_APIS typedef wchar_t once_char_type; #else typedef char once_char_type; @@ -132,99 +158,933 @@ namespace boost return ::boost::detail::win32::CreateEventA( #endif 0,::boost::detail::win32::manual_reset_event, ::boost::detail::win32::event_initially_reset, mutex_name); } - } + struct once_context { + long const function_complete_flag_value; + long const running_value; + bool counted; + detail::win32::handle_manager event_handle; + detail::once_char_type mutex_name[once_mutex_name_length]; + once_context() : + function_complete_flag_value(0xc15730e2), + running_value(0x7f0725e3), + counted(false) + { + mutex_name[0]=0; + } + }; + enum once_action {try_, break_, continue_}; + inline bool enter_once_region(once_flag& flag, once_context& ctx) BOOST_NOEXCEPT + { + long status=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&flag.status,ctx.running_value,0); + if(!status) + { + if(!ctx.event_handle) + { + ctx.event_handle=detail::open_once_event(ctx.mutex_name,&flag); + } + if(ctx.event_handle) + { + ::boost::detail::win32::ResetEvent(ctx.event_handle); + } + return true; + } + return false; + } + inline void commit_once_region(once_flag& flag, once_context& ctx) BOOST_NOEXCEPT + { + if(!ctx.counted) + { + BOOST_INTERLOCKED_INCREMENT(&flag.count); + ctx.counted=true; + } + BOOST_INTERLOCKED_EXCHANGE(&flag.status,ctx.function_complete_flag_value); + if(!ctx.event_handle && + (::boost::detail::interlocked_read_acquire(&flag.count)>1)) + { + ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); + } + if(ctx.event_handle) + { + ::boost::detail::win32::SetEvent(ctx.event_handle); + } + } + inline void rollback_once_region(once_flag& flag, once_context& ctx) BOOST_NOEXCEPT + { + BOOST_INTERLOCKED_EXCHANGE(&flag.status,0); + if(!ctx.event_handle) + { + ctx.event_handle=detail::open_once_event(ctx.mutex_name,&flag); + } + if(ctx.event_handle) + { + ::boost::detail::win32::SetEvent(ctx.event_handle); + } + } + } + +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) +//#if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR) + inline void call_once(once_flag& flag, void (*f)()) + { + // Try for a quick win: if the procedure has already been called + // just skip through: + detail::once_context ctx; + while(::boost::detail::interlocked_read_acquire(&flag.status) + !=ctx.function_complete_flag_value) + { + if(detail::enter_once_region(flag, ctx)) + { + BOOST_TRY + { + f(); + } + BOOST_CATCH(...) + { + detail::rollback_once_region(flag, ctx); + BOOST_RETHROW + } + BOOST_CATCH_END + detail::commit_once_region(flag, ctx); + break; + } + if(!ctx.counted) + { + BOOST_INTERLOCKED_INCREMENT(&flag.count); + ctx.counted=true; + long status=::boost::detail::interlocked_read_acquire(&flag.status); + if(status==ctx.function_complete_flag_value) + { + break; + } + if(!ctx.event_handle) + { + ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); + continue; + } + } + BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject( + ctx.event_handle,::boost::detail::win32::infinite)); + } + } +//#endif + template<typename Function> + inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f) + { + // Try for a quick win: if the procedure has already been called + // just skip through: + detail::once_context ctx; + while(::boost::detail::interlocked_read_acquire(&flag.status) + !=ctx.function_complete_flag_value) + { + if(detail::enter_once_region(flag, ctx)) + { + BOOST_TRY + { + f(); + } + BOOST_CATCH(...) + { + detail::rollback_once_region(flag, ctx); + BOOST_RETHROW + } + BOOST_CATCH_END + detail::commit_once_region(flag, ctx); + break; + } + if(!ctx.counted) + { + BOOST_INTERLOCKED_INCREMENT(&flag.count); + ctx.counted=true; + long status=::boost::detail::interlocked_read_acquire(&flag.status); + if(status==ctx.function_complete_flag_value) + { + break; + } + if(!ctx.event_handle) + { + ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); + continue; + } + } + BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject( + ctx.event_handle,::boost::detail::win32::infinite)); + } + } + template<typename Function, class A, class ...ArgTypes> + inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(A) a, BOOST_THREAD_RV_REF(ArgTypes)... args) + { + // Try for a quick win: if the procedure has already been called + // just skip through: + detail::once_context ctx; + while(::boost::detail::interlocked_read_acquire(&flag.status) + !=ctx.function_complete_flag_value) + { + if(detail::enter_once_region(flag, ctx)) + { + BOOST_TRY + { + BOOST_THREAD_INVOKE_RET_VOID( + thread_detail::decay_copy(boost::forward<Function>(f)), + thread_detail::decay_copy(boost::forward<A>(a)), + thread_detail::decay_copy(boost::forward<ArgTypes>(args))... + ) BOOST_THREAD_INVOKE_RET_VOID_CALL; + } + BOOST_CATCH(...) + { + detail::rollback_once_region(flag, ctx); + BOOST_RETHROW + } + BOOST_CATCH_END + detail::commit_once_region(flag, ctx); + break; + } + if(!ctx.counted) + { + BOOST_INTERLOCKED_INCREMENT(&flag.count); + ctx.counted=true; + long status=::boost::detail::interlocked_read_acquire(&flag.status); + if(status==ctx.function_complete_flag_value) + { + break; + } + if(!ctx.event_handle) + { + ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); + continue; + } + } + BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject( + ctx.event_handle,::boost::detail::win32::infinite)); + } + } +#else +#if ! defined(BOOST_MSVC) && ! defined(BOOST_INTEL) template<typename Function> void call_once(once_flag& flag,Function f) { // Try for a quick win: if the procedure has already been called // just skip through: - long const function_complete_flag_value=0xc15730e2; - long const running_value=0x7f0725e3; - long status; - bool counted=false; - detail::win32::handle_manager event_handle; - detail::once_char_type mutex_name[detail::once_mutex_name_length]; - mutex_name[0]=0; + detail::once_context ctx; + while(::boost::detail::interlocked_read_acquire(&flag.status) + !=ctx.function_complete_flag_value) + { + if(detail::enter_once_region(flag, ctx)) + { + BOOST_TRY + { + f(); + } + BOOST_CATCH(...) + { + detail::rollback_once_region(flag, ctx); + BOOST_RETHROW + } + BOOST_CATCH_END + detail::commit_once_region(flag, ctx); + break; + } + if(!ctx.counted) + { + BOOST_INTERLOCKED_INCREMENT(&flag.count); + ctx.counted=true; + long status=::boost::detail::interlocked_read_acquire(&flag.status); + if(status==ctx.function_complete_flag_value) + { + break; + } + if(!ctx.event_handle) + { + ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); + continue; + } + } + BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject( + ctx.event_handle,::boost::detail::win32::infinite)); + } + } + template<typename Function, typename T1> + void call_once(once_flag& flag,Function f, T1 p1) + { + // Try for a quick win: if the procedure has already been called + // just skip through: + detail::once_context ctx; + while(::boost::detail::interlocked_read_acquire(&flag.status) + !=ctx.function_complete_flag_value) + { + if(detail::enter_once_region(flag, ctx)) + { + BOOST_TRY + { + BOOST_THREAD_INVOKE_RET_VOID(f,p1) BOOST_THREAD_INVOKE_RET_VOID_CALL; + } + BOOST_CATCH(...) + { + detail::rollback_once_region(flag, ctx); + BOOST_RETHROW + } + BOOST_CATCH_END + detail::commit_once_region(flag, ctx); + break; + } + if(!ctx.counted) + { + BOOST_INTERLOCKED_INCREMENT(&flag.count); + ctx.counted=true; + long status=::boost::detail::interlocked_read_acquire(&flag.status); + if(status==ctx.function_complete_flag_value) + { + break; + } + if(!ctx.event_handle) + { + ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); + continue; + } + } + BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject( + ctx.event_handle,::boost::detail::win32::infinite)); + } + } + template<typename Function, typename T1, typename T2> + void call_once(once_flag& flag,Function f, T1 p1, T2 p2) + { + // Try for a quick win: if the procedure has already been called + // just skip through: + detail::once_context ctx; + while(::boost::detail::interlocked_read_acquire(&flag.status) + !=ctx.function_complete_flag_value) + { + if(detail::enter_once_region(flag, ctx)) + { + BOOST_TRY + { + BOOST_THREAD_INVOKE_RET_VOID(f,p1,p2) BOOST_THREAD_INVOKE_RET_VOID_CALL; + } + BOOST_CATCH(...) + { + detail::rollback_once_region(flag, ctx); + BOOST_RETHROW + } + BOOST_CATCH_END + detail::commit_once_region(flag, ctx); + break; + } + if(!ctx.counted) + { + BOOST_INTERLOCKED_INCREMENT(&flag.count); + ctx.counted=true; + long status=::boost::detail::interlocked_read_acquire(&flag.status); + if(status==ctx.function_complete_flag_value) + { + break; + } + if(!ctx.event_handle) + { + ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); + continue; + } + } + BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject( + ctx.event_handle,::boost::detail::win32::infinite)); + } + } + template<typename Function, typename T1, typename T2, typename T3> + void call_once(once_flag& flag,Function f, T1 p1, T2 p2, T3 p3) + { + // Try for a quick win: if the procedure has already been called + // just skip through: + detail::once_context ctx; + while(::boost::detail::interlocked_read_acquire(&flag.status) + !=ctx.function_complete_flag_value) + { + if(detail::enter_once_region(flag, ctx)) + { + BOOST_TRY + { + BOOST_THREAD_INVOKE_RET_VOID(f,p1,p2,p3) BOOST_THREAD_INVOKE_RET_VOID_CALL; + } + BOOST_CATCH(...) + { + detail::rollback_once_region(flag, ctx); + BOOST_RETHROW + } + BOOST_CATCH_END + detail::commit_once_region(flag, ctx); + break; + } + if(!ctx.counted) + { + BOOST_INTERLOCKED_INCREMENT(&flag.count); + ctx.counted=true; + long status=::boost::detail::interlocked_read_acquire(&flag.status); + if(status==ctx.function_complete_flag_value) + { + break; + } + if(!ctx.event_handle) + { + ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); + continue; + } + } + BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject( + ctx.event_handle,::boost::detail::win32::infinite)); + } + } +#elif defined BOOST_NO_CXX11_RVALUE_REFERENCES - while((status=::boost::detail::interlocked_read_acquire(&flag.status)) - !=function_complete_flag_value) + template<typename Function> + void call_once(once_flag& flag,Function const&f) + { + // Try for a quick win: if the procedure has already been called + // just skip through: + detail::once_context ctx; + while(::boost::detail::interlocked_read_acquire(&flag.status) + !=ctx.function_complete_flag_value) { - status=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&flag.status,running_value,0); - if(!status) + if(detail::enter_once_region(flag, ctx)) + { + BOOST_TRY + { + f(); + } + BOOST_CATCH(...) + { + detail::rollback_once_region(flag, ctx); + BOOST_RETHROW + } + BOOST_CATCH_END + detail::commit_once_region(flag, ctx); + break; + } + if(!ctx.counted) { -#ifndef BOOST_NO_EXCEPTIONS - try // BOOST_NO_EXCEPTIONS protected + BOOST_INTERLOCKED_INCREMENT(&flag.count); + ctx.counted=true; + long status=::boost::detail::interlocked_read_acquire(&flag.status); + if(status==ctx.function_complete_flag_value) + { + break; + } + if(!ctx.event_handle) + { + ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); + continue; + } + } + BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject( + ctx.event_handle,::boost::detail::win32::infinite)); + } + } + template<typename Function, typename T1> + void call_once(once_flag& flag,Function const&f, T1 const&p1) + { + // Try for a quick win: if the procedure has already been called + // just skip through: + detail::once_context ctx; + while(::boost::detail::interlocked_read_acquire(&flag.status) + !=ctx.function_complete_flag_value) + { + if(detail::enter_once_region(flag, ctx)) + { + BOOST_TRY + { + BOOST_THREAD_INVOKE_RET_VOID(f,p1) BOOST_THREAD_INVOKE_RET_VOID_CALL; + } + BOOST_CATCH(...) + { + detail::rollback_once_region(flag, ctx); + BOOST_RETHROW + } + BOOST_CATCH_END + detail::commit_once_region(flag, ctx); + break; + } + if(!ctx.counted) + { + BOOST_INTERLOCKED_INCREMENT(&flag.count); + ctx.counted=true; + long status=::boost::detail::interlocked_read_acquire(&flag.status); + if(status==ctx.function_complete_flag_value) + { + break; + } + if(!ctx.event_handle) + { + ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); + continue; + } + } + BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject( + ctx.event_handle,::boost::detail::win32::infinite)); + } + } + template<typename Function, typename T1, typename T2> + void call_once(once_flag& flag,Function const&f, T1 const&p1, T2 const&p2) + { + // Try for a quick win: if the procedure has already been called + // just skip through: + detail::once_context ctx; + while(::boost::detail::interlocked_read_acquire(&flag.status) + !=ctx.function_complete_flag_value) + { + if(detail::enter_once_region(flag, ctx)) + { + BOOST_TRY + { + BOOST_THREAD_INVOKE_RET_VOID(f,p1,p2) BOOST_THREAD_INVOKE_RET_VOID_CALL; + } + BOOST_CATCH(...) + { + detail::rollback_once_region(flag, ctx); + BOOST_RETHROW + } + BOOST_CATCH_END + detail::commit_once_region(flag, ctx); + break; + } + if(!ctx.counted) + { + BOOST_INTERLOCKED_INCREMENT(&flag.count); + ctx.counted=true; + long status=::boost::detail::interlocked_read_acquire(&flag.status); + if(status==ctx.function_complete_flag_value) + { + break; + } + if(!ctx.event_handle) + { + ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); + continue; + } + } + BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject( + ctx.event_handle,::boost::detail::win32::infinite)); + } + } + template<typename Function, typename T1, typename T2, typename T3> + void call_once(once_flag& flag,Function const&f, T1 const&p1, T2 const&p2, T3 const&p3) + { + // Try for a quick win: if the procedure has already been called + // just skip through: + detail::once_context ctx; + while(::boost::detail::interlocked_read_acquire(&flag.status) + !=ctx.function_complete_flag_value) + { + if(detail::enter_once_region(flag, ctx)) + { + BOOST_TRY + { + BOOST_THREAD_INVOKE_RET_VOID(f,p1,p2,p3) BOOST_THREAD_INVOKE_RET_VOID_CALL; + } + BOOST_CATCH(...) + { + detail::rollback_once_region(flag, ctx); + BOOST_RETHROW + } + BOOST_CATCH_END + detail::commit_once_region(flag, ctx); + break; + } + if(!ctx.counted) + { + BOOST_INTERLOCKED_INCREMENT(&flag.count); + ctx.counted=true; + long status=::boost::detail::interlocked_read_acquire(&flag.status); + if(status==ctx.function_complete_flag_value) + { + break; + } + if(!ctx.event_handle) + { + ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); + continue; + } + } + BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject( + ctx.event_handle,::boost::detail::win32::infinite)); + } + } #endif +#if 1 +#if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR) + inline void call_once(once_flag& flag, void (*f)()) + { + // Try for a quick win: if the procedure has already been called + // just skip through: + detail::once_context ctx; + while(::boost::detail::interlocked_read_acquire(&flag.status) + !=ctx.function_complete_flag_value) + { + if(detail::enter_once_region(flag, ctx)) { - if(!event_handle) + BOOST_TRY { - event_handle=detail::open_once_event(mutex_name,&flag); + f(); } - if(event_handle) + BOOST_CATCH(...) { - ::boost::detail::win32::ResetEvent(event_handle); + detail::rollback_once_region(flag, ctx); + BOOST_RETHROW } - f(); - if(!counted) + BOOST_CATCH_END + detail::commit_once_region(flag, ctx); + break; + } + if(!ctx.counted) + { + BOOST_INTERLOCKED_INCREMENT(&flag.count); + ctx.counted=true; + long status=::boost::detail::interlocked_read_acquire(&flag.status); + if(status==ctx.function_complete_flag_value) + { + break; + } + if(!ctx.event_handle) + { + ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); + continue; + } + } + BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject( + ctx.event_handle,::boost::detail::win32::infinite)); + } + } + template<typename T1> + void call_once(once_flag& flag,void (*f)(BOOST_THREAD_RV_REF(T1)), BOOST_THREAD_RV_REF(T1) p1) + { + // Try for a quick win: if the procedure has already been called + // just skip through: + detail::once_context ctx; + while(::boost::detail::interlocked_read_acquire(&flag.status) + !=ctx.function_complete_flag_value) + { + if(detail::enter_once_region(flag, ctx)) + { + BOOST_TRY + { + f( + thread_detail::decay_copy(boost::forward<T1>(p1)) + ); + } + BOOST_CATCH(...) + { + detail::rollback_once_region(flag, ctx); + BOOST_RETHROW + } + BOOST_CATCH_END + detail::commit_once_region(flag, ctx); + break; + } + if(!ctx.counted) + { + BOOST_INTERLOCKED_INCREMENT(&flag.count); + ctx.counted=true; + long status=::boost::detail::interlocked_read_acquire(&flag.status); + if(status==ctx.function_complete_flag_value) + { + break; + } + if(!ctx.event_handle) + { + ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); + continue; + } + } + BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject( + ctx.event_handle,::boost::detail::win32::infinite)); + } + } + template<typename Function, typename T1, typename T2> + void call_once(once_flag& flag,void (*f)(BOOST_THREAD_RV_REF(T1),BOOST_THREAD_RV_REF(T2)), BOOST_THREAD_RV_REF(T1) p1, BOOST_THREAD_RV_REF(T2) p2) + { + // Try for a quick win: if the procedure has already been called + // just skip through: + detail::once_context ctx; + while(::boost::detail::interlocked_read_acquire(&flag.status) + !=ctx.function_complete_flag_value) + { + if(detail::enter_once_region(flag, ctx)) + { + BOOST_TRY { - BOOST_INTERLOCKED_INCREMENT(&flag.count); - counted=true; + f( + thread_detail::decay_copy(boost::forward<T1>(p1)), + thread_detail::decay_copy(boost::forward<T2>(p2)) + ); } - BOOST_INTERLOCKED_EXCHANGE(&flag.status,function_complete_flag_value); - if(!event_handle && - (::boost::detail::interlocked_read_acquire(&flag.count)>1)) + BOOST_CATCH(...) { - event_handle=detail::create_once_event(mutex_name,&flag); + detail::rollback_once_region(flag, ctx); + BOOST_RETHROW } - if(event_handle) + BOOST_CATCH_END + detail::commit_once_region(flag, ctx); + break; + } + if(!ctx.counted) + { + BOOST_INTERLOCKED_INCREMENT(&flag.count); + ctx.counted=true; + long status=::boost::detail::interlocked_read_acquire(&flag.status); + if(status==ctx.function_complete_flag_value) { - ::boost::detail::win32::SetEvent(event_handle); + break; } + if(!ctx.event_handle) + { + ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); + continue; + } + } + BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject( + ctx.event_handle,::boost::detail::win32::infinite)); + } + } + template<typename Function, typename T1, typename T2, typename T3> + void call_once(once_flag& flag,void (*f)(BOOST_THREAD_RV_REF(T1),BOOST_THREAD_RV_REF(T2)), BOOST_THREAD_RV_REF(T1) p1, BOOST_THREAD_RV_REF(T2) p2, BOOST_THREAD_RV_REF(T3) p3) + { + // Try for a quick win: if the procedure has already been called + // just skip through: + detail::once_context ctx; + while(::boost::detail::interlocked_read_acquire(&flag.status) + !=ctx.function_complete_flag_value) + { + if(detail::enter_once_region(flag, ctx)) + { + BOOST_TRY + { + f( + thread_detail::decay_copy(boost::forward<T1>(p1)), + thread_detail::decay_copy(boost::forward<T2>(p2)), + thread_detail::decay_copy(boost::forward<T3>(p3)) + ); + } + BOOST_CATCH(...) + { + detail::rollback_once_region(flag, ctx); + BOOST_RETHROW + } + BOOST_CATCH_END + detail::commit_once_region(flag, ctx); break; } -#ifndef BOOST_NO_EXCEPTIONS - catch(...) // BOOST_NO_EXCEPTIONS protected + if(!ctx.counted) { - BOOST_INTERLOCKED_EXCHANGE(&flag.status,0); - if(!event_handle) + BOOST_INTERLOCKED_INCREMENT(&flag.count); + ctx.counted=true; + long status=::boost::detail::interlocked_read_acquire(&flag.status); + if(status==ctx.function_complete_flag_value) { - event_handle=detail::open_once_event(mutex_name,&flag); + break; } - if(event_handle) + if(!ctx.event_handle) { - ::boost::detail::win32::SetEvent(event_handle); + ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); + continue; } - throw; // BOOST_NO_EXCEPTIONS protected } + BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject( + ctx.event_handle,::boost::detail::win32::infinite)); + } + } #endif + template<typename Function> + void call_once(once_flag& flag,BOOST_THREAD_RV_REF(Function) f) + { + // Try for a quick win: if the procedure has already been called + // just skip through: + detail::once_context ctx; + while(::boost::detail::interlocked_read_acquire(&flag.status) + !=ctx.function_complete_flag_value) + { + if(detail::enter_once_region(flag, ctx)) + { + BOOST_TRY + { + f(); + } + BOOST_CATCH(...) + { + detail::rollback_once_region(flag, ctx); + BOOST_RETHROW + } + BOOST_CATCH_END + detail::commit_once_region(flag, ctx); + break; + } + if(!ctx.counted) + { + BOOST_INTERLOCKED_INCREMENT(&flag.count); + ctx.counted=true; + long status=::boost::detail::interlocked_read_acquire(&flag.status); + if(status==ctx.function_complete_flag_value) + { + break; + } + if(!ctx.event_handle) + { + ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); + continue; + } } + BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject( + ctx.event_handle,::boost::detail::win32::infinite)); + } + } - if(!counted) + template<typename Function, typename T1> + void call_once(once_flag& flag,BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(T1) p1) + { + // Try for a quick win: if the procedure has already been called + // just skip through: + detail::once_context ctx; + while(::boost::detail::interlocked_read_acquire(&flag.status) + !=ctx.function_complete_flag_value) + { + if(detail::enter_once_region(flag, ctx)) + { + BOOST_TRY + { + BOOST_THREAD_INVOKE_RET_VOID( + thread_detail::decay_copy(boost::forward<Function>(f)), + thread_detail::decay_copy(boost::forward<T1>(p1)) + ) BOOST_THREAD_INVOKE_RET_VOID_CALL; + } + BOOST_CATCH(...) + { + detail::rollback_once_region(flag, ctx); + BOOST_RETHROW + } + BOOST_CATCH_END + detail::commit_once_region(flag, ctx); + break; + } + if(!ctx.counted) { BOOST_INTERLOCKED_INCREMENT(&flag.count); - counted=true; - status=::boost::detail::interlocked_read_acquire(&flag.status); - if(status==function_complete_flag_value) + ctx.counted=true; + long status=::boost::detail::interlocked_read_acquire(&flag.status); + if(status==ctx.function_complete_flag_value) { break; } - if(!event_handle) + if(!ctx.event_handle) { - event_handle=detail::create_once_event(mutex_name,&flag); + ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); continue; } } BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject( - event_handle,::boost::detail::win32::infinite)); + ctx.event_handle,::boost::detail::win32::infinite)); } } + template<typename Function, typename T1, typename T2> + void call_once(once_flag& flag,BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(T1) p1, BOOST_THREAD_RV_REF(T2) p2) + { + // Try for a quick win: if the procedure has already been called + // just skip through: + detail::once_context ctx; + while(::boost::detail::interlocked_read_acquire(&flag.status) + !=ctx.function_complete_flag_value) + { + if(detail::enter_once_region(flag, ctx)) + { + BOOST_TRY + { + BOOST_THREAD_INVOKE_RET_VOID( + thread_detail::decay_copy(boost::forward<Function>(f)), + thread_detail::decay_copy(boost::forward<T1>(p1)), + thread_detail::decay_copy(boost::forward<T2>(p2)) + ) BOOST_THREAD_INVOKE_RET_VOID_CALL; + } + BOOST_CATCH(...) + { + detail::rollback_once_region(flag, ctx); + BOOST_RETHROW + } + BOOST_CATCH_END + detail::commit_once_region(flag, ctx); + break; + } + if(!ctx.counted) + { + BOOST_INTERLOCKED_INCREMENT(&flag.count); + ctx.counted=true; + long status=::boost::detail::interlocked_read_acquire(&flag.status); + if(status==ctx.function_complete_flag_value) + { + break; + } + if(!ctx.event_handle) + { + ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); + continue; + } + } + BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject( + ctx.event_handle,::boost::detail::win32::infinite)); + } + } + template<typename Function, typename T1, typename T2, typename T3> + void call_once(once_flag& flag,BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(T1) p1, BOOST_THREAD_RV_REF(T2) p2, BOOST_THREAD_RV_REF(T3) p3) + { + // Try for a quick win: if the procedure has already been called + // just skip through: + detail::once_context ctx; + while(::boost::detail::interlocked_read_acquire(&flag.status) + !=ctx.function_complete_flag_value) + { + if(detail::enter_once_region(flag, ctx)) + { + BOOST_TRY + { + BOOST_THREAD_INVOKE_RET_VOID( + thread_detail::decay_copy(boost::forward<Function>(f)), + thread_detail::decay_copy(boost::forward<T1>(p1)), + thread_detail::decay_copy(boost::forward<T2>(p2)), + thread_detail::decay_copy(boost::forward<T3>(p3)) + ) BOOST_THREAD_INVOKE_RET_VOID_CALL; + + } + BOOST_CATCH(...) + { + detail::rollback_once_region(flag, ctx); + BOOST_RETHROW + } + BOOST_CATCH_END + detail::commit_once_region(flag, ctx); + break; + } + if(!ctx.counted) + { + BOOST_INTERLOCKED_INCREMENT(&flag.count); + ctx.counted=true; + long status=::boost::detail::interlocked_read_acquire(&flag.status); + if(status==ctx.function_complete_flag_value) + { + break; + } + if(!ctx.event_handle) + { + ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); + continue; + } + } + BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject( + ctx.event_handle,::boost::detail::win32::infinite)); + } + } + +#endif +#endif } #include <boost/config/abi_suffix.hpp> #endif diff --git a/3rdParty/Boost/src/boost/thread/win32/recursive_mutex.hpp b/3rdParty/Boost/src/boost/thread/win32/recursive_mutex.hpp index 5144e77..1f0f7f5 100644 --- a/3rdParty/Boost/src/boost/thread/win32/recursive_mutex.hpp +++ b/3rdParty/Boost/src/boost/thread/win32/recursive_mutex.hpp @@ -9,13 +9,16 @@ // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include <boost/thread/win32/basic_recursive_mutex.hpp> #include <boost/thread/exceptions.hpp> -#include <boost/thread/locks.hpp> +#include <boost/thread/detail/delete.hpp> +#if defined BOOST_THREAD_PROVIDES_NESTED_LOCKS +#include <boost/thread/lock_types.hpp> +#endif #include <boost/config/abi_prefix.hpp> namespace boost { class recursive_mutex: @@ -29,14 +32,16 @@ namespace boost } ~recursive_mutex() { ::boost::detail::basic_recursive_mutex::destroy(); } +#if defined BOOST_THREAD_PROVIDES_NESTED_LOCKS typedef unique_lock<recursive_mutex> scoped_lock; typedef detail::try_lock_wrapper<recursive_mutex> scoped_try_lock; +#endif }; typedef recursive_mutex recursive_try_mutex; class recursive_timed_mutex: public ::boost::detail::basic_recursive_timed_mutex @@ -49,15 +54,17 @@ namespace boost } ~recursive_timed_mutex() { ::boost::detail::basic_recursive_timed_mutex::destroy(); } +#if defined BOOST_THREAD_PROVIDES_NESTED_LOCKS typedef unique_lock<recursive_timed_mutex> scoped_timed_lock; typedef detail::try_lock_wrapper<recursive_timed_mutex> scoped_try_lock; typedef scoped_timed_lock scoped_lock; +#endif }; } #include <boost/config/abi_suffix.hpp> #endif diff --git a/3rdParty/Boost/src/boost/thread/win32/shared_mutex.hpp b/3rdParty/Boost/src/boost/thread/win32/shared_mutex.hpp index fef2d5b..252174f 100644 --- a/3rdParty/Boost/src/boost/thread/win32/shared_mutex.hpp +++ b/3rdParty/Boost/src/boost/thread/win32/shared_mutex.hpp @@ -92,13 +92,13 @@ namespace boost if (!upgrade_sem) { detail::win32::release_semaphore(semaphores[unlock_sem],LONG_MAX); detail::win32::release_semaphore(semaphores[exclusive_sem],LONG_MAX); boost::throw_exception(thread_resource_error()); } - state_data state_={0}; + state_data state_={0,0,0,0,0,0}; state=state_; } ~shared_mutex() { detail::win32::CloseHandle(upgrade_sem); @@ -130,21 +130,25 @@ namespace boost } return !(old_state.exclusive| old_state.exclusive_waiting_blocked); } void lock_shared() { +#if defined BOOST_THREAD_USES_DATETIME BOOST_VERIFY(timed_lock_shared(::boost::detail::get_system_time_sentinel())); +#else + BOOST_VERIFY(try_lock_shared_until(chrono::steady_clock::now())); +#endif } +#if defined BOOST_THREAD_USES_DATETIME template<typename TimeDuration> bool timed_lock_shared(TimeDuration const & relative_time) { return timed_lock_shared(get_system_time()+relative_time); } - bool timed_lock_shared(boost::system_time const& wait_until) { for(;;) { state_data old_state=state; for(;;) @@ -217,12 +221,13 @@ namespace boost return false; } BOOST_ASSERT(res==0); } } +#endif #ifdef BOOST_THREAD_USES_CHRONO template <class Rep, class Period> bool try_lock_shared_for(const chrono::duration<Rep, Period>& rel_time) { return try_lock_shared_until(chrono::steady_clock::now() + rel_time); @@ -375,20 +380,26 @@ namespace boost old_state=current_state; } } void lock() { +#if defined BOOST_THREAD_USES_DATETIME BOOST_VERIFY(timed_lock(::boost::detail::get_system_time_sentinel())); +#else + BOOST_VERIFY(try_lock_until(chrono::steady_clock::now())); +#endif } +#if defined BOOST_THREAD_USES_DATETIME template<typename TimeDuration> bool timed_lock(TimeDuration const & relative_time) { return timed_lock(get_system_time()+relative_time); } +#endif bool try_lock() { state_data old_state=state; for(;;) { @@ -410,12 +421,13 @@ namespace boost old_state=current_state; } return true; } +#if defined BOOST_THREAD_USES_DATETIME bool timed_lock(boost::system_time const& wait_until) { for(;;) { state_data old_state=state; @@ -456,29 +468,36 @@ namespace boost #endif unsigned long const wait_res=detail::win32::WaitForMultipleObjects(2,semaphores,wait_all,::boost::detail::get_milliseconds_until(wait_until)); if(wait_res==detail::win32::timeout) { for(;;) { + bool must_notify = false; state_data new_state=old_state; if(new_state.shared_count || new_state.exclusive) { if(new_state.exclusive_waiting) { if(!--new_state.exclusive_waiting) { new_state.exclusive_waiting_blocked=false; + must_notify = true; } } } else { new_state.exclusive=true; } state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); + if (must_notify) + { + BOOST_VERIFY(detail::win32::ReleaseSemaphore(semaphores[unlock_sem],1,0)!=0); + } + if(current_state==old_state) { break; } old_state=current_state; } @@ -488,13 +507,13 @@ namespace boost } return false; } BOOST_ASSERT(wait_res<2); } } - +#endif #ifdef BOOST_THREAD_USES_CHRONO template <class Rep, class Period> bool try_lock_for(const chrono::duration<Rep, Period>& rel_time) { return try_lock_until(chrono::steady_clock::now() + rel_time); } @@ -565,29 +584,35 @@ namespace boost wait_res=detail::win32::timeout; } if(wait_res==detail::win32::timeout) { for(;;) { + bool must_notify = false; state_data new_state=old_state; if(new_state.shared_count || new_state.exclusive) { if(new_state.exclusive_waiting) { if(!--new_state.exclusive_waiting) { new_state.exclusive_waiting_blocked=false; + must_notify = true; } } } else { new_state.exclusive=true; } state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); + if (must_notify) + { + BOOST_VERIFY(detail::win32::ReleaseSemaphore(semaphores[unlock_sem],1,0)!=0); + } if(current_state==old_state) { break; } old_state=current_state; } @@ -721,15 +746,17 @@ namespace boost state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); if(current_state==old_state) { if(last_reader) { release_waiters(old_state); - } else { - release_waiters(old_state); } + // #7720 + //else { + // release_waiters(old_state); + //} break; } old_state=current_state; } } diff --git a/3rdParty/Boost/src/boost/thread/win32/thread_data.hpp b/3rdParty/Boost/src/boost/thread/win32/thread_data.hpp index 18fd7cb..1d4f572 100644 --- a/3rdParty/Boost/src/boost/thread/win32/thread_data.hpp +++ b/3rdParty/Boost/src/boost/thread/win32/thread_data.hpp @@ -19,12 +19,17 @@ #include <map> #include <vector> #include <utility> #include <boost/config/abi_prefix.hpp> +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4251) +#endif + namespace boost { class condition_variable; class mutex; class thread_attributes { @@ -64,12 +69,13 @@ namespace boost private: win_attrs val_; }; namespace detail { + struct shared_state_base; struct tss_cleanup_function; struct thread_exit_callback_node; struct tss_data_node { boost::shared_ptr<boost::detail::tss_cleanup_function> func; void* value; @@ -85,30 +91,40 @@ namespace boost void intrusive_ptr_release(thread_data_base * p); struct BOOST_THREAD_DECL thread_data_base { long count; detail::win32::handle_manager thread_handle; - detail::win32::handle_manager interruption_handle; boost::detail::thread_exit_callback_node* thread_exit_callbacks; std::map<void const*,boost::detail::tss_data_node> tss_data; - bool interruption_enabled; unsigned id; typedef std::vector<std::pair<condition_variable*, mutex*> //, hidden_allocator<std::pair<condition_variable*, mutex*> > > notify_list_t; notify_list_t notify; + typedef std::vector<shared_ptr<shared_state_base> > async_states_t; + async_states_t async_states_; +//#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + // These data must be at the end so that the access to the other fields doesn't change + // when BOOST_THREAD_PROVIDES_INTERRUPTIONS is defined + // Another option is to have them always + detail::win32::handle_manager interruption_handle; + bool interruption_enabled; +//#endif thread_data_base(): count(0),thread_handle(detail::win32::invalid_handle_value), - interruption_handle(create_anonymous_event(detail::win32::manual_reset_event,detail::win32::event_initially_reset)), thread_exit_callbacks(0),tss_data(), - interruption_enabled(true), id(0), - notify() + notify(), + async_states_() +//#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + , interruption_handle(create_anonymous_event(detail::win32::manual_reset_event,detail::win32::event_initially_reset)) + , interruption_enabled(true) +//#endif {} virtual ~thread_data_base(); friend void intrusive_ptr_add_ref(thread_data_base * p) { BOOST_INTERLOCKED_INCREMENT(&p->count); @@ -119,48 +135,55 @@ namespace boost if(!BOOST_INTERLOCKED_DECREMENT(&p->count)) { detail::heap_delete(p); } } +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS void interrupt() { BOOST_VERIFY(detail::win32::SetEvent(interruption_handle)!=0); } - +#endif typedef detail::win32::handle native_handle_type; virtual void run()=0; - void notify_all_at_thread_exit(condition_variable* cv, mutex* m) + virtual void notify_all_at_thread_exit(condition_variable* cv, mutex* m) { notify.push_back(std::pair<condition_variable*, mutex*>(cv, m)); } + void make_ready_at_thread_exit(shared_ptr<shared_state_base> as) + { + async_states_.push_back(as); + } + }; + BOOST_THREAD_DECL thread_data_base* get_current_thread_data(); typedef boost::intrusive_ptr<detail::thread_data_base> thread_data_ptr; struct BOOST_SYMBOL_VISIBLE timeout { - unsigned long start; + win32::ticks_type start; uintmax_t milliseconds; bool relative; boost::system_time abs_time; static unsigned long const max_non_infinite_wait=0xfffffffe; timeout(uintmax_t milliseconds_): - start(win32::GetTickCount()), + start(win32::GetTickCount64()()), milliseconds(milliseconds_), relative(true), abs_time(boost::get_system_time()) {} timeout(boost::system_time const& abs_time_): - start(win32::GetTickCount()), + start(win32::GetTickCount64()()), milliseconds(0), relative(false), abs_time(abs_time_) {} struct BOOST_SYMBOL_VISIBLE remaining_time @@ -179,14 +202,14 @@ namespace boost if(is_sentinel()) { return remaining_time(win32::infinite); } else if(relative) { - unsigned long const now=win32::GetTickCount(); - unsigned long const elapsed=now-start; + win32::ticks_type const now=win32::GetTickCount64()(); + win32::ticks_type const elapsed=now-start; return remaining_time((elapsed<milliseconds)?(milliseconds-elapsed):0); } else { system_time const now=get_system_time(); if(abs_time<=now) @@ -232,13 +255,12 @@ namespace boost interruptible_wait(detail::win32::invalid_handle_value,milliseconds); } inline BOOST_SYMBOL_VISIBLE void interruptible_wait(system_time const& abs_time) { interruptible_wait(detail::win32::invalid_handle_value,abs_time); } - template<typename TimeDuration> inline BOOST_SYMBOL_VISIBLE void sleep(TimeDuration const& rel_time) { interruptible_wait(detail::pin_to_zero(rel_time.total_milliseconds())); } inline BOOST_SYMBOL_VISIBLE void sleep(system_time const& abs_time) @@ -248,13 +270,44 @@ namespace boost #ifdef BOOST_THREAD_USES_CHRONO inline void BOOST_SYMBOL_VISIBLE sleep_for(const chrono::nanoseconds& ns) { interruptible_wait(chrono::duration_cast<chrono::milliseconds>(ns).count()); } #endif + namespace no_interruption_point + { + bool BOOST_THREAD_DECL non_interruptible_wait(detail::win32::handle handle_to_wait_for,detail::timeout target_time); + inline void non_interruptible_wait(uintmax_t milliseconds) + { + non_interruptible_wait(detail::win32::invalid_handle_value,milliseconds); + } + inline BOOST_SYMBOL_VISIBLE void non_interruptible_wait(system_time const& abs_time) + { + non_interruptible_wait(detail::win32::invalid_handle_value,abs_time); + } + template<typename TimeDuration> + inline BOOST_SYMBOL_VISIBLE void sleep(TimeDuration const& rel_time) + { + non_interruptible_wait(detail::pin_to_zero(rel_time.total_milliseconds())); + } + inline BOOST_SYMBOL_VISIBLE void sleep(system_time const& abs_time) + { + non_interruptible_wait(abs_time); + } +#ifdef BOOST_THREAD_USES_CHRONO + inline void BOOST_SYMBOL_VISIBLE sleep_for(const chrono::nanoseconds& ns) + { + non_interruptible_wait(chrono::duration_cast<chrono::milliseconds>(ns).count()); + } +#endif + } } } +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + #include <boost/config/abi_suffix.hpp> #endif diff --git a/3rdParty/Boost/src/boost/thread/win32/thread_heap_alloc.hpp b/3rdParty/Boost/src/boost/thread/win32/thread_heap_alloc.hpp index 9b6d390..610fe32 100644 --- a/3rdParty/Boost/src/boost/thread/win32/thread_heap_alloc.hpp +++ b/3rdParty/Boost/src/boost/thread/win32/thread_heap_alloc.hpp @@ -2,16 +2,18 @@ // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // (C) Copyright 2007 Anthony Williams #ifndef THREAD_HEAP_ALLOC_HPP #define THREAD_HEAP_ALLOC_HPP #include <new> +#include <boost/thread/detail/config.hpp> #include <boost/thread/win32/thread_primitives.hpp> #include <stdexcept> #include <boost/assert.hpp> #include <boost/throw_exception.hpp> +#include <boost/core/no_exceptions_support.hpp> #if defined( BOOST_USE_WINDOWS_H ) # include <windows.h> namespace boost { @@ -72,186 +74,159 @@ namespace boost } template<typename T> inline T* heap_new() { void* const heap_memory=allocate_raw_heap_memory(sizeof(T)); -#ifndef BOOST_NO_EXCEPTIONS - try // BOOST_NO_EXCEPTIONS protected -#endif + BOOST_TRY { T* const data=new (heap_memory) T(); return data; } -#ifndef BOOST_NO_EXCEPTIONS - catch(...) // BOOST_NO_EXCEPTIONS protected + BOOST_CATCH(...) { free_raw_heap_memory(heap_memory); - throw; // BOOST_NO_EXCEPTIONS protected + BOOST_RETHROW } -#endif + BOOST_CATCH_END } #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES template<typename T,typename A1> inline T* heap_new(A1&& a1) { void* const heap_memory=allocate_raw_heap_memory(sizeof(T)); -#ifndef BOOST_NO_EXCEPTIONS - try // BOOST_NO_EXCEPTIONS protected -#endif + BOOST_TRY { T* const data=new (heap_memory) T(static_cast<A1&&>(a1)); return data; } -#ifndef BOOST_NO_EXCEPTIONS - catch(...) // BOOST_NO_EXCEPTIONS protected + BOOST_CATCH(...) { free_raw_heap_memory(heap_memory); - throw; // BOOST_NO_EXCEPTIONS protected + BOOST_RETHROW } -#endif + BOOST_CATCH_END } template<typename T,typename A1,typename A2> inline T* heap_new(A1&& a1,A2&& a2) { void* const heap_memory=allocate_raw_heap_memory(sizeof(T)); -#ifndef BOOST_NO_EXCEPTIONS - try // BOOST_NO_EXCEPTIONS protected -#endif + BOOST_TRY { T* const data=new (heap_memory) T(static_cast<A1&&>(a1),static_cast<A2&&>(a2)); return data; } -#ifndef BOOST_NO_EXCEPTIONS - catch(...) // BOOST_NO_EXCEPTIONS protected + BOOST_CATCH(...) { free_raw_heap_memory(heap_memory); - throw; // BOOST_NO_EXCEPTIONS protected + BOOST_RETHROW } -#endif + BOOST_CATCH_END } template<typename T,typename A1,typename A2,typename A3> inline T* heap_new(A1&& a1,A2&& a2,A3&& a3) { void* const heap_memory=allocate_raw_heap_memory(sizeof(T)); -#ifndef BOOST_NO_EXCEPTIONS - try // BOOST_NO_EXCEPTIONS protected -#endif + BOOST_TRY { T* const data=new (heap_memory) T(static_cast<A1&&>(a1),static_cast<A2&&>(a2), static_cast<A3&&>(a3)); return data; } -#ifndef BOOST_NO_EXCEPTIONS - catch(...) // BOOST_NO_EXCEPTIONS protected + BOOST_CATCH(...) { free_raw_heap_memory(heap_memory); - throw; // BOOST_NO_EXCEPTIONS protected + BOOST_RETHROW } -#endif + BOOST_CATCH_END } template<typename T,typename A1,typename A2,typename A3,typename A4> inline T* heap_new(A1&& a1,A2&& a2,A3&& a3,A4&& a4) { void* const heap_memory=allocate_raw_heap_memory(sizeof(T)); -#ifndef BOOST_NO_EXCEPTIONS - try // BOOST_NO_EXCEPTIONS protected -#endif + BOOST_TRY { T* const data=new (heap_memory) T(static_cast<A1&&>(a1),static_cast<A2&&>(a2), static_cast<A3&&>(a3),static_cast<A4&&>(a4)); return data; } -#ifndef BOOST_NO_EXCEPTIONS - catch(...) // BOOST_NO_EXCEPTIONS protected + BOOST_CATCH(...) { free_raw_heap_memory(heap_memory); - throw; // BOOST_NO_EXCEPTIONS protected + BOOST_RETHROW } -#endif + BOOST_CATCH_END } #else template<typename T,typename A1> inline T* heap_new_impl(A1 a1) { void* const heap_memory=allocate_raw_heap_memory(sizeof(T)); -#ifndef BOOST_NO_EXCEPTIONS - try // BOOST_NO_EXCEPTIONS protected -#endif + BOOST_TRY { T* const data=new (heap_memory) T(a1); return data; } -#ifndef BOOST_NO_EXCEPTIONS - catch(...) // BOOST_NO_EXCEPTIONS protected + BOOST_CATCH(...) { free_raw_heap_memory(heap_memory); - throw; // BOOST_NO_EXCEPTIONS protected + BOOST_RETHROW } -#endif + BOOST_CATCH_END } template<typename T,typename A1,typename A2> inline T* heap_new_impl(A1 a1,A2 a2) { void* const heap_memory=allocate_raw_heap_memory(sizeof(T)); -#ifndef BOOST_NO_EXCEPTIONS - try // BOOST_NO_EXCEPTIONS protected -#endif + BOOST_TRY { T* const data=new (heap_memory) T(a1,a2); return data; } -#ifndef BOOST_NO_EXCEPTIONS - catch(...) // BOOST_NO_EXCEPTIONS protected + BOOST_CATCH(...) { free_raw_heap_memory(heap_memory); - throw; // BOOST_NO_EXCEPTIONS protected + BOOST_RETHROW } -#endif + BOOST_CATCH_END } template<typename T,typename A1,typename A2,typename A3> inline T* heap_new_impl(A1 a1,A2 a2,A3 a3) { void* const heap_memory=allocate_raw_heap_memory(sizeof(T)); -#ifndef BOOST_NO_EXCEPTIONS - try // BOOST_NO_EXCEPTIONS protected -#endif + BOOST_TRY { T* const data=new (heap_memory) T(a1,a2,a3); return data; } -#ifndef BOOST_NO_EXCEPTIONS - catch(...) // BOOST_NO_EXCEPTIONS protected + BOOST_CATCH(...) { free_raw_heap_memory(heap_memory); - throw; // BOOST_NO_EXCEPTIONS protected + BOOST_RETHROW } -#endif + BOOST_CATCH_END } template<typename T,typename A1,typename A2,typename A3,typename A4> inline T* heap_new_impl(A1 a1,A2 a2,A3 a3,A4 a4) { void* const heap_memory=allocate_raw_heap_memory(sizeof(T)); -#ifndef BOOST_NO_EXCEPTIONS - try // BOOST_NO_EXCEPTIONS protected -#endif + BOOST_TRY { T* const data=new (heap_memory) T(a1,a2,a3,a4); return data; } -#ifndef BOOST_NO_EXCEPTIONS - catch(...) // BOOST_NO_EXCEPTIONS protected + BOOST_CATCH(...) { free_raw_heap_memory(heap_memory); - throw; // BOOST_NO_EXCEPTIONS protected + BOOST_RETHROW } -#endif + BOOST_CATCH_END } template<typename T,typename A1> inline T* heap_new(A1 const& a1) { diff --git a/3rdParty/Boost/src/boost/thread/win32/thread_primitives.hpp b/3rdParty/Boost/src/boost/thread/win32/thread_primitives.hpp index c0dba11..fcf59b3 100644 --- a/3rdParty/Boost/src/boost/thread/win32/thread_primitives.hpp +++ b/3rdParty/Boost/src/boost/thread/win32/thread_primitives.hpp @@ -12,30 +12,32 @@ #include <boost/thread/detail/config.hpp> #include <boost/throw_exception.hpp> #include <boost/assert.hpp> #include <boost/thread/exceptions.hpp> #include <boost/detail/interlocked.hpp> +//#include <boost/detail/winapi/synchronization.hpp> #include <algorithm> #if defined( BOOST_USE_WINDOWS_H ) # include <windows.h> namespace boost { namespace detail { namespace win32 { - typedef ULONG_PTR ulong_ptr; typedef HANDLE handle; unsigned const infinite=INFINITE; unsigned const timeout=WAIT_TIMEOUT; handle const invalid_handle_value=INVALID_HANDLE_VALUE; unsigned const event_modify_state=EVENT_MODIFY_STATE; unsigned const synchronize=SYNCHRONIZE; + unsigned const wait_abandoned=WAIT_ABANDONED; + # ifdef BOOST_NO_ANSI_APIS using ::CreateMutexW; using ::CreateEventW; using ::OpenEventW; using ::CreateSemaphoreW; @@ -57,13 +59,12 @@ namespace boost using ::GetCurrentThread; using ::GetCurrentProcess; using ::DuplicateHandle; using ::SleepEx; using ::Sleep; using ::QueueUserAPC; - using ::GetTickCount; } } } #elif defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) # ifdef UNDER_CE @@ -85,30 +86,31 @@ typedef void* HANDLE; # include <kfuncs.h> # ifdef __cplusplus } # endif # endif + namespace boost { namespace detail { namespace win32 { - # ifdef _WIN64 typedef unsigned __int64 ulong_ptr; # else typedef unsigned long ulong_ptr; # endif typedef void* handle; unsigned const infinite=~0U; unsigned const timeout=258U; handle const invalid_handle_value=(handle)(-1); unsigned const event_modify_state=2; unsigned const synchronize=0x100000u; + unsigned const wait_abandoned=0x00000080u; extern "C" { struct _SECURITY_ATTRIBUTES; # ifdef BOOST_NO_ANSI_APIS __declspec(dllimport) void* __stdcall CreateMutexW(_SECURITY_ATTRIBUTES*,int,wchar_t const*); @@ -129,14 +131,12 @@ namespace boost __declspec(dllimport) int __stdcall DuplicateHandle(void*,void*,void*,void**,unsigned long,int,unsigned long); __declspec(dllimport) unsigned long __stdcall SleepEx(unsigned long,int); __declspec(dllimport) void __stdcall Sleep(unsigned long); typedef void (__stdcall *queue_user_apc_callback_function)(ulong_ptr); __declspec(dllimport) unsigned long __stdcall QueueUserAPC(queue_user_apc_callback_function,void*,ulong_ptr); - __declspec(dllimport) unsigned long __stdcall GetTickCount(); - # ifndef UNDER_CE __declspec(dllimport) unsigned long __stdcall GetCurrentProcessId(); __declspec(dllimport) unsigned long __stdcall GetCurrentThreadId(); __declspec(dllimport) void* __stdcall GetCurrentThread(); __declspec(dllimport) void* __stdcall GetCurrentProcess(); __declspec(dllimport) int __stdcall SetEvent(void*); @@ -162,13 +162,94 @@ namespace boost namespace boost { namespace detail { namespace win32 { - enum event_type + typedef unsigned __int64 ticks_type; + namespace detail { typedef int (__stdcall *farproc_t)(); typedef ticks_type (__stdcall *gettickcount64_t)(); } + extern "C" + { + __declspec(dllimport) detail::farproc_t __stdcall GetProcAddress(void *, const char *); +#if !defined(BOOST_NO_ANSI_APIS) + __declspec(dllimport) void * __stdcall GetModuleHandleA(const char *); +#else + __declspec(dllimport) void * __stdcall GetModuleHandleW(const wchar_t *); +#endif + int __stdcall GetTickCount(); + long _InterlockedCompareExchange(long volatile *, long, long); +#pragma intrinsic(_InterlockedCompareExchange) + } + // Borrowed from https://stackoverflow.com/questions/8211820/userland-interrupt-timer-access-such-as-via-kequeryinterrupttime-or-similar + inline ticks_type __stdcall GetTickCount64emulation() + { + static volatile long count = 0xFFFFFFFF; + unsigned long previous_count, current_tick32, previous_count_zone, current_tick32_zone; + ticks_type current_tick64; + + previous_count = (unsigned long) _InterlockedCompareExchange(&count, 0, 0); + current_tick32 = GetTickCount(); + + if(previous_count == 0xFFFFFFFF) + { + // count has never been written + unsigned long initial_count; + initial_count = current_tick32 >> 28; + previous_count = (unsigned long) _InterlockedCompareExchange(&count, initial_count, 0xFFFFFFFF); + + current_tick64 = initial_count; + current_tick64 <<= 28; + current_tick64 += current_tick32 & 0x0FFFFFFF; + return current_tick64; + } + + previous_count_zone = previous_count & 15; + current_tick32_zone = current_tick32 >> 28; + + if(current_tick32_zone == previous_count_zone) + { + // The top four bits of the 32-bit tick count haven't changed since count was last written. + current_tick64 = previous_count; + current_tick64 <<= 28; + current_tick64 += current_tick32 & 0x0FFFFFFF; + return current_tick64; + } + + if(current_tick32_zone == previous_count_zone + 1 || (current_tick32_zone == 0 && previous_count_zone == 15)) + { + // The top four bits of the 32-bit tick count have been incremented since count was last written. + _InterlockedCompareExchange(&count, previous_count + 1, previous_count); + current_tick64 = previous_count + 1; + current_tick64 <<= 28; + current_tick64 += current_tick32 & 0x0FFFFFFF; + return current_tick64; + } + + // Oops, we weren't called often enough, we're stuck + return 0xFFFFFFFF; + } + inline detail::gettickcount64_t GetTickCount64() + { + static detail::gettickcount64_t gettickcount64impl; + if(gettickcount64impl) + return gettickcount64impl; + detail::farproc_t addr=GetProcAddress( +#if !defined(BOOST_NO_ANSI_APIS) + GetModuleHandleA("KERNEL32.DLL"), +#else + GetModuleHandleW(L"KERNEL32.DLL"), +#endif + "GetTickCount64"); + if(addr) + gettickcount64impl=(detail::gettickcount64_t) addr; + else + gettickcount64impl=&GetTickCount64emulation; + return gettickcount64impl; + } + + enum event_type { auto_reset_event=false, manual_reset_event=true }; enum initial_event_state @@ -229,13 +310,13 @@ namespace boost inline void release_semaphore(handle semaphore,long count) { BOOST_VERIFY(ReleaseSemaphore(semaphore,count,0)!=0); } - class handle_manager + class BOOST_THREAD_DECL handle_manager { private: handle handle_to_manage; handle_manager(handle_manager&); handle_manager& operator=(handle_manager&); |