diff options
Diffstat (limited to 'src/third_party/boost-1.56.0/boost/thread/win32')
12 files changed, 4484 insertions, 0 deletions
diff --git a/src/third_party/boost-1.56.0/boost/thread/win32/basic_recursive_mutex.hpp b/src/third_party/boost-1.56.0/boost/thread/win32/basic_recursive_mutex.hpp new file mode 100644 index 00000000000..cfdfa043a3b --- /dev/null +++ b/src/third_party/boost-1.56.0/boost/thread/win32/basic_recursive_mutex.hpp @@ -0,0 +1,164 @@ +#ifndef BOOST_BASIC_RECURSIVE_MUTEX_WIN32_HPP +#define BOOST_BASIC_RECURSIVE_MUTEX_WIN32_HPP + +// basic_recursive_mutex.hpp +// +// (C) Copyright 2006-8 Anthony Williams +// (C) Copyright 2011-2012 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include <boost/thread/win32/thread_primitives.hpp> +#include <boost/thread/win32/basic_timed_mutex.hpp> +#ifdef BOOST_THREAD_USES_CHRONO +#include <boost/chrono/system_clocks.hpp> +#include <boost/chrono/ceil.hpp> +#endif + +#include <boost/config/abi_prefix.hpp> + +namespace boost +{ + namespace detail + { + template<typename underlying_mutex_type> + struct basic_recursive_mutex_impl + { + long recursion_count; + long locking_thread_id; + underlying_mutex_type mutex; + + void initialize() + { + recursion_count=0; + locking_thread_id=0; + mutex.initialize(); + } + + void destroy() + { + mutex.destroy(); + } + + bool try_lock() BOOST_NOEXCEPT + { + long const current_thread_id=win32::GetCurrentThreadId(); + return try_recursive_lock(current_thread_id) || try_basic_lock(current_thread_id); + } + + void lock() + { + long const current_thread_id=win32::GetCurrentThreadId(); + if(!try_recursive_lock(current_thread_id)) + { + 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(); + return try_recursive_lock(current_thread_id) || try_timed_lock_for(current_thread_id,rel_time); + } + template <class Clock, class Duration> + bool try_lock_until(const chrono::time_point<Clock, Duration>& t) + { + long const current_thread_id=win32::GetCurrentThreadId(); + return try_recursive_lock(current_thread_id) || try_timed_lock_until(current_thread_id,t); + } +#endif + void unlock() + { + if(!--recursion_count) + { + BOOST_INTERLOCKED_EXCHANGE(&locking_thread_id,0); + mutex.unlock(); + } + } + + private: + bool try_recursive_lock(long current_thread_id) BOOST_NOEXCEPT + { + if(::boost::detail::interlocked_read_acquire(&locking_thread_id)==current_thread_id) + { + ++recursion_count; + return true; + } + return false; + } + + bool try_basic_lock(long current_thread_id) BOOST_NOEXCEPT + { + if(mutex.try_lock()) + { + BOOST_INTERLOCKED_EXCHANGE(&locking_thread_id,current_thread_id); + 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); + recursion_count=1; + return true; + } + return false; + } + template <typename D> + bool try_timed_lock_for(long current_thread_id,D const& target) + { + if(mutex.try_lock_for(target)) + { + BOOST_INTERLOCKED_EXCHANGE(&locking_thread_id,current_thread_id); + recursion_count=1; + return true; + } + return false; + } + }; + + typedef basic_recursive_mutex_impl<basic_timed_mutex> basic_recursive_mutex; + typedef basic_recursive_mutex_impl<basic_timed_mutex> basic_recursive_timed_mutex; + } +} + +#define BOOST_BASIC_RECURSIVE_MUTEX_INITIALIZER {0} + +#include <boost/config/abi_suffix.hpp> + +#endif diff --git a/src/third_party/boost-1.56.0/boost/thread/win32/basic_timed_mutex.hpp b/src/third_party/boost-1.56.0/boost/thread/win32/basic_timed_mutex.hpp new file mode 100644 index 00000000000..01db03363cf --- /dev/null +++ b/src/third_party/boost-1.56.0/boost/thread/win32/basic_timed_mutex.hpp @@ -0,0 +1,274 @@ +#ifndef BOOST_BASIC_TIMED_MUTEX_WIN32_HPP +#define BOOST_BASIC_TIMED_MUTEX_WIN32_HPP + +// basic_timed_mutex_win32.hpp +// +// (C) Copyright 2006-8 Anthony Williams +// (C) Copyright 2011-2012 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include <boost/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> + +namespace boost +{ + namespace detail + { + struct basic_timed_mutex + { + BOOST_STATIC_CONSTANT(unsigned char,lock_flag_bit=31); + BOOST_STATIC_CONSTANT(unsigned char,event_set_flag_bit=30); + BOOST_STATIC_CONSTANT(long,lock_flag_value=1<<lock_flag_bit); + BOOST_STATIC_CONSTANT(long,event_set_flag_value=1<<event_set_flag_bit); + long active_count; + void* event; + + void initialize() + { + active_count=0; + event=0; + } + + void destroy() + { +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4312) +#endif + void* const old_event=BOOST_INTERLOCKED_EXCHANGE_POINTER(&event,0); +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + if(old_event) + { + win32::CloseHandle(old_event); + } + } + + + bool try_lock() BOOST_NOEXCEPT + { + return !win32::interlocked_bit_test_and_set(&active_count,lock_flag_bit); + } + + void lock() + { + if(try_lock()) + { + return; + } + long old_count=active_count; + mark_waiting_and_try_lock(old_count); + + if(old_count&lock_flag_value) + { + bool lock_acquired=false; + void* const sem=get_event(); + + do + { + 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(;;) + { + 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; + } + } + + void clear_waiting_and_try_lock(long& old_count) + { + old_count&=~lock_flag_value; + old_count|=event_set_flag_value; + for(;;) + { + long const new_count=((old_count&lock_flag_value)?old_count:((old_count-1)|lock_flag_value))&~event_set_flag_value; + long const current=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&active_count,new_count,old_count); + if(current==old_count) + { + break; + } + old_count=current; + } + } + + +#if defined BOOST_THREAD_USES_DATETIME + bool timed_lock(::boost::system_time const& wait_until) + { + if(try_lock()) + { + return true; + } + long old_count=active_count; + mark_waiting_and_try_lock(old_count); + + if(old_count&lock_flag_value) + { + bool lock_acquired=false; + void* const sem=get_event(); + + do + { + if(win32::WaitForSingleObject(sem,::boost::detail::get_milliseconds_until(wait_until))!=0) + { + BOOST_INTERLOCKED_DECREMENT(&active_count); + return false; + } + clear_waiting_and_try_lock(old_count); + lock_acquired=!(old_count&lock_flag_value); + } + 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); + } + template <class Clock, class Duration> + bool try_lock_until(const chrono::time_point<Clock, Duration>& t) + { + using namespace chrono; + system_clock::time_point s_now = system_clock::now(); + typename Clock::time_point c_now = Clock::now(); + return try_lock_until(s_now + ceil<system_clock::duration>(t - c_now)); + } + template <class Duration> + bool try_lock_until(const chrono::time_point<chrono::system_clock, Duration>& t) + { + using namespace chrono; + typedef time_point<chrono::system_clock, chrono::system_clock::duration> sys_tmpt; + return try_lock_until(sys_tmpt(chrono::ceil<chrono::system_clock::duration>(t.time_since_epoch()))); + } + bool try_lock_until(const chrono::time_point<chrono::system_clock, chrono::system_clock::duration>& tp) + { + if(try_lock()) + { + return true; + } + long old_count=active_count; + mark_waiting_and_try_lock(old_count); + + if(old_count&lock_flag_value) + { + bool lock_acquired=false; + void* const sem=get_event(); + + do + { + chrono::milliseconds rel_time= chrono::ceil<chrono::milliseconds>(tp-chrono::system_clock::now()); + + if(win32::WaitForSingleObject(sem,static_cast<unsigned long>(rel_time.count()))!=0) + { + BOOST_INTERLOCKED_DECREMENT(&active_count); + return false; + } + clear_waiting_and_try_lock(old_count); + lock_acquired=!(old_count&lock_flag_value); + } + while(!lock_acquired); + } + return true; + } +#endif + + void unlock() + { + long const offset=lock_flag_value; + long const old_count=BOOST_INTERLOCKED_EXCHANGE_ADD(&active_count,lock_flag_value); + if(!(old_count&event_set_flag_value) && (old_count>offset)) + { + if(!win32::interlocked_bit_test_and_set(&active_count,event_set_flag_bit)) + { + win32::SetEvent(get_event()); + } + } + } + + private: + void* get_event() + { + void* current_event=::boost::detail::interlocked_read_acquire(&event); + + if(!current_event) + { + void* const new_event=win32::create_anonymous_event(win32::auto_reset_event,win32::event_initially_reset); +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4311) +#pragma warning(disable:4312) +#endif + void* const old_event=BOOST_INTERLOCKED_COMPARE_EXCHANGE_POINTER(&event,new_event,0); +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + if(old_event!=0) + { + win32::CloseHandle(new_event); + return old_event; + } + else + { + return new_event; + } + } + return current_event; + } + + }; + + } +} + +#define BOOST_BASIC_TIMED_MUTEX_INITIALIZER {0} + +#include <boost/config/abi_suffix.hpp> + +#endif diff --git a/src/third_party/boost-1.56.0/boost/thread/win32/condition_variable.hpp b/src/third_party/boost-1.56.0/boost/thread/win32/condition_variable.hpp new file mode 100644 index 00000000000..57aaf8c5349 --- /dev/null +++ b/src/third_party/boost-1.56.0/boost/thread/win32/condition_variable.hpp @@ -0,0 +1,555 @@ +#ifndef BOOST_THREAD_CONDITION_VARIABLE_WIN32_HPP +#define BOOST_THREAD_CONDITION_VARIABLE_WIN32_HPP +// 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) +// (C) Copyright 2007-8 Anthony Williams +// (C) Copyright 2011-2012 Vicente J. Botet Escriba + +#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> +#include <boost/chrono/ceil.hpp> +#endif + +#include <limits.h> +#include <algorithm> +#include <vector> + +#include <boost/config/abi_prefix.hpp> + +namespace boost +{ + namespace detail + { + class basic_cv_list_entry; + void intrusive_ptr_add_ref(basic_cv_list_entry * p); + void intrusive_ptr_release(basic_cv_list_entry * p); + + class basic_cv_list_entry + { + private: + detail::win32::handle_manager semaphore; + detail::win32::handle_manager wake_sem; + long waiters; + bool notified; + long references; + + public: + BOOST_THREAD_NO_COPYABLE(basic_cv_list_entry) + explicit basic_cv_list_entry(detail::win32::handle_manager const& wake_sem_): + semaphore(detail::win32::create_anonymous_semaphore(0,LONG_MAX)), + wake_sem(wake_sem_.duplicate()), + waiters(1),notified(false),references(0) + {} + + static bool no_waiters(boost::intrusive_ptr<basic_cv_list_entry> const& entry) + { + return !detail::interlocked_read_acquire(&entry->waiters); + } + + void add_waiter() + { + BOOST_INTERLOCKED_INCREMENT(&waiters); + } + + void remove_waiter() + { + BOOST_INTERLOCKED_DECREMENT(&waiters); + } + + void release(unsigned count_to_release) + { + notified=true; + detail::win32::ReleaseSemaphore(semaphore,count_to_release,0); + } + + void release_waiters() + { + release(detail::interlocked_read_acquire(&waiters)); + } + + bool is_notified() const + { + return notified; + } + + bool wait(timeout abs_time) + { + return this_thread::interruptible_wait(semaphore,abs_time); + } + + bool woken() + { + unsigned long const woken_result=detail::win32::WaitForSingleObject(wake_sem,0); + BOOST_ASSERT((woken_result==detail::win32::timeout) || (woken_result==0)); + return woken_result==0; + } + + friend void intrusive_ptr_add_ref(basic_cv_list_entry * p); + friend void intrusive_ptr_release(basic_cv_list_entry * p); + }; + + inline void intrusive_ptr_add_ref(basic_cv_list_entry * p) + { + BOOST_INTERLOCKED_INCREMENT(&p->references); + } + + inline void intrusive_ptr_release(basic_cv_list_entry * p) + { + if(!BOOST_INTERLOCKED_DECREMENT(&p->references)) + { + delete p; + } + } + + class basic_condition_variable + { + boost::mutex internal_mutex; + long total_count; + unsigned active_generation_count; + + typedef basic_cv_list_entry list_entry; + + typedef boost::intrusive_ptr<list_entry> entry_ptr; + typedef std::vector<entry_ptr> generation_list; + + generation_list generations; + detail::win32::handle_manager wake_sem; + + void wake_waiters(long count_to_wake) + { + detail::interlocked_write_release(&total_count,total_count-count_to_wake); + detail::win32::ReleaseSemaphore(wake_sem,count_to_wake,0); + } + + template<typename lock_type> + struct relocker + { + BOOST_THREAD_NO_COPYABLE(relocker) + lock_type& lock; + bool unlocked; + + relocker(lock_type& lock_): + lock(lock_),unlocked(false) + {} + void unlock() + { + lock.unlock(); + unlocked=true; + } + ~relocker() + { + if(unlocked) + { + lock.lock(); + } + + } + }; + + + entry_ptr get_wait_entry() + { + boost::lock_guard<boost::mutex> internal_lock(internal_mutex); + + if(!wake_sem) + { + wake_sem=detail::win32::create_anonymous_semaphore(0,LONG_MAX); + BOOST_ASSERT(wake_sem); + } + + detail::interlocked_write_release(&total_count,total_count+1); + if(generations.empty() || generations.back()->is_notified()) + { + entry_ptr new_entry(new list_entry(wake_sem)); + generations.push_back(new_entry); + return new_entry; + } + else + { + generations.back()->add_waiter(); + return generations.back(); + } + } + + struct entry_manager + { + entry_ptr const entry; + boost::mutex& internal_mutex; + + BOOST_THREAD_NO_COPYABLE(entry_manager) + entry_manager(entry_ptr const& entry_, boost::mutex& mutex_): + entry(entry_), internal_mutex(mutex_) + {} + + ~entry_manager() + { + boost::lock_guard<boost::mutex> internal_lock(internal_mutex); + entry->remove_waiter(); + } + + list_entry* operator->() + { + return entry.get(); + } + }; + + + 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(), internal_mutex); + + locker.unlock(); + + bool woken=false; + while(!woken) + { + if(!entry->wait(abs_time)) + { + return false; + } + + woken=entry->woken(); + } + return woken; + } + + template<typename lock_type,typename predicate_type> + bool do_wait(lock_type& m,timeout const& abs_time,predicate_type pred) + { + while (!pred()) + { + if(!do_wait(m, abs_time)) + return pred(); + } + return true; + } + + basic_condition_variable(const basic_condition_variable& other); + basic_condition_variable& operator=(const basic_condition_variable& other); + + public: + basic_condition_variable(): + total_count(0),active_generation_count(0),wake_sem(0) + {} + + ~basic_condition_variable() + {} + + void notify_one() BOOST_NOEXCEPT + { + if(detail::interlocked_read_acquire(&total_count)) + { + boost::lock_guard<boost::mutex> internal_lock(internal_mutex); + if(!total_count) + { + return; + } + wake_waiters(1); + + for(generation_list::iterator it=generations.begin(), + end=generations.end(); + it!=end;++it) + { + (*it)->release(1); + } + generations.erase(std::remove_if(generations.begin(),generations.end(),&basic_cv_list_entry::no_waiters),generations.end()); + } + } + + void notify_all() BOOST_NOEXCEPT + { + if(detail::interlocked_read_acquire(&total_count)) + { + boost::lock_guard<boost::mutex> internal_lock(internal_mutex); + if(!total_count) + { + return; + } + wake_waiters(total_count); + for(generation_list::iterator it=generations.begin(), + end=generations.end(); + it!=end;++it) + { + (*it)->release_waiters(); + } + generations.clear(); + wake_sem=detail::win32::handle(0); + } + } + + }; + } + + class condition_variable: + private detail::basic_condition_variable + { + public: + BOOST_THREAD_NO_COPYABLE(condition_variable) + condition_variable() + {} + + using detail::basic_condition_variable::notify_one; + using detail::basic_condition_variable::notify_all; + + void wait(unique_lock<mutex>& m) + { + do_wait(m,detail::timeout::sentinel()); + } + + template<typename predicate_type> + 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) + { + 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); + } + template<typename predicate_type> + bool timed_wait(unique_lock<mutex>& m,boost::xtime const& abs_time,predicate_type pred) + { + return do_wait(m,system_time(abs_time),pred); + } + 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; + 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; + } + + template <class Clock, class Duration, class Predicate> + bool + wait_until( + unique_lock<mutex>& lock, + const chrono::time_point<Clock, Duration>& t, + Predicate pred) + { + while (!pred()) + { + if (wait_until(lock, t) == cv_status::timeout) + return pred(); + } + return true; + } + template <class Rep, class Period, class Predicate> + bool + wait_for( + unique_lock<mutex>& lock, + const chrono::duration<Rep, Period>& d, + Predicate pred) + { + return wait_until(lock, chrono::steady_clock::now() + d, boost::move(pred)); + } +#endif + }; + + class condition_variable_any: + private detail::basic_condition_variable + { + public: + BOOST_THREAD_NO_COPYABLE(condition_variable_any) + condition_variable_any() + {} + + using detail::basic_condition_variable::notify_one; + using detail::basic_condition_variable::notify_all; + + template<typename lock_type> + void wait(lock_type& m) + { + do_wait(m,detail::timeout::sentinel()); + } + + 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); + } + + template<typename lock_type> + bool timed_wait(lock_type& m,boost::xtime const& abs_time) + { + return do_wait(m,system_time(abs_time)); + } + + template<typename lock_type,typename duration_type> + bool timed_wait(lock_type& m,duration_type const& wait_duration) + { + return do_wait(m,wait_duration.total_milliseconds()); + } + + template<typename lock_type,typename predicate_type> + bool timed_wait(lock_type& m,boost::system_time const& abs_time,predicate_type pred) + { + return do_wait(m,abs_time,pred); + } + + template<typename lock_type,typename predicate_type> + bool timed_wait(lock_type& m,boost::xtime const& abs_time,predicate_type pred) + { + return do_wait(m,system_time(abs_time),pred); + } + + 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; + 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; + } + + template <class lock_type, class Clock, class Duration, class Predicate> + bool + wait_until( + lock_type& lock, + const chrono::time_point<Clock, Duration>& t, + Predicate pred) + { + while (!pred()) + { + if (wait_until(lock, t) == cv_status::timeout) + return pred(); + } + return true; + } + + template <class lock_type, class Rep, class Period, class Predicate> + bool + wait_for( + lock_type& lock, + const chrono::duration<Rep, Period>& d, + Predicate 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); +} + +#include <boost/config/abi_suffix.hpp> + +#endif diff --git a/src/third_party/boost-1.56.0/boost/thread/win32/interlocked_read.hpp b/src/third_party/boost-1.56.0/boost/thread/win32/interlocked_read.hpp new file mode 100644 index 00000000000..4a969985220 --- /dev/null +++ b/src/third_party/boost-1.56.0/boost/thread/win32/interlocked_read.hpp @@ -0,0 +1,82 @@ +#ifndef BOOST_THREAD_DETAIL_INTERLOCKED_READ_WIN32_HPP +#define BOOST_THREAD_DETAIL_INTERLOCKED_READ_WIN32_HPP + +// interlocked_read_win32.hpp +// +// (C) Copyright 2005-8 Anthony Williams +// (C) Copyright 2012 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include <boost/detail/interlocked.hpp> +#include <boost/thread/detail/config.hpp> + +#include <boost/config/abi_prefix.hpp> + +#ifdef BOOST_MSVC + +extern "C" void _ReadWriteBarrier(void); +#pragma intrinsic(_ReadWriteBarrier) + +namespace boost +{ + namespace detail + { + inline long interlocked_read_acquire(long volatile* x) BOOST_NOEXCEPT + { + long const res=*x; + _ReadWriteBarrier(); + return res; + } + inline void* interlocked_read_acquire(void* volatile* x) BOOST_NOEXCEPT + { + void* const res=*x; + _ReadWriteBarrier(); + return res; + } + + inline void interlocked_write_release(long volatile* x,long value) BOOST_NOEXCEPT + { + _ReadWriteBarrier(); + *x=value; + } + inline void interlocked_write_release(void* volatile* x,void* value) BOOST_NOEXCEPT + { + _ReadWriteBarrier(); + *x=value; + } + } +} + +#else + +namespace boost +{ + namespace detail + { + inline long interlocked_read_acquire(long volatile* x) BOOST_NOEXCEPT + { + return BOOST_INTERLOCKED_COMPARE_EXCHANGE(x,0,0); + } + inline void* interlocked_read_acquire(void* volatile* x) BOOST_NOEXCEPT + { + return BOOST_INTERLOCKED_COMPARE_EXCHANGE_POINTER(x,0,0); + } + inline void interlocked_write_release(long volatile* x,long value) BOOST_NOEXCEPT + { + BOOST_INTERLOCKED_EXCHANGE(x,value); + } + inline void interlocked_write_release(void* volatile* x,void* value) BOOST_NOEXCEPT + { + BOOST_INTERLOCKED_EXCHANGE_POINTER(x,value); + } + } +} + +#endif + +#include <boost/config/abi_suffix.hpp> + +#endif diff --git a/src/third_party/boost-1.56.0/boost/thread/win32/mfc_thread_init.hpp b/src/third_party/boost-1.56.0/boost/thread/win32/mfc_thread_init.hpp new file mode 100644 index 00000000000..e866f8949f5 --- /dev/null +++ b/src/third_party/boost-1.56.0/boost/thread/win32/mfc_thread_init.hpp @@ -0,0 +1,40 @@ +#ifndef BOOST_THREAD_WIN32_MFC_THREAD_INIT_HPP +#define BOOST_THREAD_WIN32_MFC_THREAD_INIT_HPP +// 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) +// (C) Copyright 2008 Anthony Williams +// (C) Copyright 2011-2012 Vicente J. Botet Escriba + + +// check if we use MFC +#ifdef _AFXDLL +# if defined(_AFXEXT) + +// can't use ExtRawDllMain from afxdllx.h as it also defines the symbol _pRawDllMain +extern "C" +inline BOOL WINAPI ExtRawDllMain(HINSTANCE, DWORD dwReason, LPVOID) +{ + if (dwReason == DLL_PROCESS_ATTACH) + { + // save critical data pointers before running the constructors + AFX_MODULE_STATE* pModuleState = AfxGetModuleState(); + pModuleState->m_pClassInit = pModuleState->m_classList; + pModuleState->m_pFactoryInit = pModuleState->m_factoryList; + pModuleState->m_classList.m_pHead = NULL; + pModuleState->m_factoryList.m_pHead = NULL; + } + return TRUE; // ok +} + +extern "C" __declspec(selectany) BOOL (WINAPI * const _pRawDllMainOrig)(HANDLE, DWORD, LPVOID) = &ExtRawDllMain; + +# elif defined(_USRDLL) + +extern "C" BOOL WINAPI RawDllMain(HANDLE, DWORD dwReason, LPVOID); +extern "C" __declspec(selectany) BOOL (WINAPI * const _pRawDllMainOrig)(HANDLE, DWORD, LPVOID) = &RawDllMain; + +# endif +#endif + +#endif diff --git a/src/third_party/boost-1.56.0/boost/thread/win32/mutex.hpp b/src/third_party/boost-1.56.0/boost/thread/win32/mutex.hpp new file mode 100644 index 00000000000..01544784b5b --- /dev/null +++ b/src/third_party/boost-1.56.0/boost/thread/win32/mutex.hpp @@ -0,0 +1,72 @@ +#ifndef BOOST_THREAD_WIN32_MUTEX_HPP +#define BOOST_THREAD_WIN32_MUTEX_HPP +// (C) Copyright 2005-7 Anthony Williams +// (C) Copyright 2011-2012 Vicente J. Botet Escriba +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include <boost/thread/win32/basic_timed_mutex.hpp> +#include <boost/thread/exceptions.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 + { + typedef ::boost::detail::basic_timed_mutex underlying_mutex; + } + + class mutex: + public ::boost::detail::underlying_mutex + { + public: + BOOST_THREAD_NO_COPYABLE(mutex) + mutex() + { + initialize(); + } + ~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 + { + public: + BOOST_THREAD_NO_COPYABLE(timed_mutex) + timed_mutex() + { + initialize(); + } + + ~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/src/third_party/boost-1.56.0/boost/thread/win32/once.hpp b/src/third_party/boost-1.56.0/boost/thread/win32/once.hpp new file mode 100644 index 00000000000..0ed56a57168 --- /dev/null +++ b/src/third_party/boost-1.56.0/boost/thread/win32/once.hpp @@ -0,0 +1,1090 @@ +#ifndef BOOST_THREAD_WIN32_ONCE_HPP +#define BOOST_THREAD_WIN32_ONCE_HPP + +// once.hpp +// +// (C) Copyright 2005-7 Anthony Williams +// (C) Copyright 2005 John Maddock +// (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 +{ + using ::memcpy; + 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) + {} + long status; + long count; + 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 + { + long status; + 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; +#endif + unsigned const once_mutex_name_fixed_length=54; + unsigned const once_mutex_name_length=once_mutex_name_fixed_length+ + sizeof(void*)*2+sizeof(unsigned long)*2+1; + + template <class I> + void int_to_string(I p, once_char_type* buf) + { + for(unsigned i=0; i < sizeof(I)*2; ++i,++buf) + { +#ifdef BOOST_NO_ANSI_APIS + once_char_type const a=L'A'; +#else + once_char_type const a='A'; +#endif + *buf = a + static_cast<once_char_type>((p >> (i*4)) & 0x0f); + } + *buf = 0; + } + + inline void name_once_mutex(once_char_type* mutex_name,void* flag_address) + { +#ifdef BOOST_NO_ANSI_APIS + static const once_char_type fixed_mutex_name[]=L"Local\\{C15730E2-145C-4c5e-B005-3BC753F42475}-once-flag"; +#else + static const once_char_type fixed_mutex_name[]="Local\\{C15730E2-145C-4c5e-B005-3BC753F42475}-once-flag"; +#endif + BOOST_STATIC_ASSERT(sizeof(fixed_mutex_name) == + (sizeof(once_char_type)*(once_mutex_name_fixed_length+1))); + + std::memcpy(mutex_name,fixed_mutex_name,sizeof(fixed_mutex_name)); + detail::int_to_string(reinterpret_cast<std::ptrdiff_t>(flag_address), + mutex_name + once_mutex_name_fixed_length); + detail::int_to_string(win32::GetCurrentProcessId(), + mutex_name + once_mutex_name_fixed_length + sizeof(void*)*2); + } + + inline void* open_once_event(once_char_type* mutex_name,void* flag_address) + { + if(!*mutex_name) + { + name_once_mutex(mutex_name,flag_address); + } + +#ifdef BOOST_NO_ANSI_APIS + return ::boost::detail::win32::OpenEventW( +#else + return ::boost::detail::win32::OpenEventA( +#endif + ::boost::detail::win32::synchronize | + ::boost::detail::win32::event_modify_state, + false, + mutex_name); + } + + inline void* create_once_event(once_char_type* mutex_name,void* flag_address) + { + if(!*mutex_name) + { + name_once_mutex(mutex_name,flag_address); + } +#ifdef BOOST_NO_ANSI_APIS + return ::boost::detail::win32::CreateEventW( +#else + 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: + 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 + + 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) + { + 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 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)) + { + 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 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 + { + f( + thread_detail::decay_copy(boost::forward<T1>(p1)), + thread_detail::decay_copy(boost::forward<T2>(p2)) + ); + } + 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,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; + } + 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> + 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, 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); + 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,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/src/third_party/boost-1.56.0/boost/thread/win32/recursive_mutex.hpp b/src/third_party/boost-1.56.0/boost/thread/win32/recursive_mutex.hpp new file mode 100644 index 00000000000..1f0f7f5e5fd --- /dev/null +++ b/src/third_party/boost-1.56.0/boost/thread/win32/recursive_mutex.hpp @@ -0,0 +1,70 @@ +#ifndef BOOST_RECURSIVE_MUTEX_WIN32_HPP +#define BOOST_RECURSIVE_MUTEX_WIN32_HPP + +// recursive_mutex.hpp +// +// (C) Copyright 2006-7 Anthony Williams +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + + +#include <boost/thread/win32/basic_recursive_mutex.hpp> +#include <boost/thread/exceptions.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: + public ::boost::detail::basic_recursive_mutex + { + public: + BOOST_THREAD_NO_COPYABLE(recursive_mutex) + recursive_mutex() + { + ::boost::detail::basic_recursive_mutex::initialize(); + } + ~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 + { + public: + BOOST_THREAD_NO_COPYABLE(recursive_timed_mutex) + recursive_timed_mutex() + { + ::boost::detail::basic_recursive_timed_mutex::initialize(); + } + ~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/src/third_party/boost-1.56.0/boost/thread/win32/shared_mutex.hpp b/src/third_party/boost-1.56.0/boost/thread/win32/shared_mutex.hpp new file mode 100644 index 00000000000..252174f69e6 --- /dev/null +++ b/src/third_party/boost-1.56.0/boost/thread/win32/shared_mutex.hpp @@ -0,0 +1,892 @@ +#ifndef BOOST_THREAD_WIN32_SHARED_MUTEX_HPP +#define BOOST_THREAD_WIN32_SHARED_MUTEX_HPP + +// (C) Copyright 2006-8 Anthony Williams +// (C) Copyright 2011-2012 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include <boost/assert.hpp> +#include <boost/detail/interlocked.hpp> +#include <boost/thread/win32/thread_primitives.hpp> +#include <boost/static_assert.hpp> +#include <limits.h> +#include <boost/thread/thread_time.hpp> +#ifdef BOOST_THREAD_USES_CHRONO +#include <boost/chrono/system_clocks.hpp> +#include <boost/chrono/ceil.hpp> +#endif +#include <boost/thread/detail/delete.hpp> + +#include <boost/config/abi_prefix.hpp> + +namespace boost +{ + class shared_mutex + { + private: + struct state_data + { + unsigned shared_count:11, + shared_waiting:11, + exclusive:1, + upgrade:1, + exclusive_waiting:7, + exclusive_waiting_blocked:1; + + friend bool operator==(state_data const& lhs,state_data const& rhs) + { + return *reinterpret_cast<unsigned const*>(&lhs)==*reinterpret_cast<unsigned const*>(&rhs); + } + }; + + + template<typename T> + T interlocked_compare_exchange(T* target,T new_value,T comparand) + { + BOOST_STATIC_ASSERT(sizeof(T)==sizeof(long)); + long const res=BOOST_INTERLOCKED_COMPARE_EXCHANGE(reinterpret_cast<long*>(target), + *reinterpret_cast<long*>(&new_value), + *reinterpret_cast<long*>(&comparand)); + return *reinterpret_cast<T const*>(&res); + } + + enum + { + unlock_sem = 0, + exclusive_sem = 1 + }; + + state_data state; + detail::win32::handle semaphores[2]; + detail::win32::handle upgrade_sem; + + void release_waiters(state_data old_state) + { + if(old_state.exclusive_waiting) + { + BOOST_VERIFY(detail::win32::ReleaseSemaphore(semaphores[exclusive_sem],1,0)!=0); + } + + if(old_state.shared_waiting || old_state.exclusive_waiting) + { + BOOST_VERIFY(detail::win32::ReleaseSemaphore(semaphores[unlock_sem],old_state.shared_waiting + (old_state.exclusive_waiting?1:0),0)!=0); + } + } + + + public: + BOOST_THREAD_NO_COPYABLE(shared_mutex) + shared_mutex() + { + semaphores[unlock_sem]=detail::win32::create_anonymous_semaphore(0,LONG_MAX); + semaphores[exclusive_sem]=detail::win32::create_anonymous_semaphore_nothrow(0,LONG_MAX); + if (!semaphores[exclusive_sem]) + { + detail::win32::release_semaphore(semaphores[unlock_sem],LONG_MAX); + boost::throw_exception(thread_resource_error()); + } + upgrade_sem=detail::win32::create_anonymous_semaphore_nothrow(0,LONG_MAX); + 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,0,0,0,0,0}; + state=state_; + } + + ~shared_mutex() + { + detail::win32::CloseHandle(upgrade_sem); + detail::win32::CloseHandle(semaphores[unlock_sem]); + detail::win32::CloseHandle(semaphores[exclusive_sem]); + } + + bool try_lock_shared() + { + state_data old_state=state; + for(;;) + { + state_data new_state=old_state; + if(!new_state.exclusive && !new_state.exclusive_waiting_blocked) + { + ++new_state.shared_count; + if(!new_state.shared_count) + { + return false; + } + } + + state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); + if(current_state==old_state) + { + break; + } + old_state=current_state; + } + 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(;;) + { + state_data new_state=old_state; + if(new_state.exclusive || new_state.exclusive_waiting_blocked) + { + ++new_state.shared_waiting; + if(!new_state.shared_waiting) + { + boost::throw_exception(boost::lock_error()); + } + } + else + { + ++new_state.shared_count; + if(!new_state.shared_count) + { + boost::throw_exception(boost::lock_error()); + } + } + + state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); + if(current_state==old_state) + { + break; + } + old_state=current_state; + } + + if(!(old_state.exclusive| old_state.exclusive_waiting_blocked)) + { + return true; + } + + unsigned long const res=detail::win32::WaitForSingleObject(semaphores[unlock_sem],::boost::detail::get_milliseconds_until(wait_until)); + if(res==detail::win32::timeout) + { + for(;;) + { + state_data new_state=old_state; + if(new_state.exclusive || new_state.exclusive_waiting_blocked) + { + if(new_state.shared_waiting) + { + --new_state.shared_waiting; + } + } + else + { + ++new_state.shared_count; + if(!new_state.shared_count) + { + return false; + } + } + + state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); + if(current_state==old_state) + { + break; + } + old_state=current_state; + } + + if(!(old_state.exclusive| old_state.exclusive_waiting_blocked)) + { + return true; + } + 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); + } + template <class Clock, class Duration> + bool try_lock_shared_until(const chrono::time_point<Clock, Duration>& t) + { + using namespace chrono; + system_clock::time_point s_now = system_clock::now(); + typename Clock::time_point c_now = Clock::now(); + return try_lock_shared_until(s_now + ceil<system_clock::duration>(t - c_now)); + } + template <class Duration> + bool try_lock_shared_until(const chrono::time_point<chrono::system_clock, Duration>& t) + { + using namespace chrono; + typedef time_point<chrono::system_clock, chrono::system_clock::duration> sys_tmpt; + return try_lock_shared_until(sys_tmpt(chrono::ceil<chrono::system_clock::duration>(t.time_since_epoch()))); + } + bool try_lock_shared_until(const chrono::time_point<chrono::system_clock, chrono::system_clock::duration>& tp) + { + for(;;) + { + state_data old_state=state; + for(;;) + { + state_data new_state=old_state; + if(new_state.exclusive || new_state.exclusive_waiting_blocked) + { + ++new_state.shared_waiting; + if(!new_state.shared_waiting) + { + boost::throw_exception(boost::lock_error()); + } + } + else + { + ++new_state.shared_count; + if(!new_state.shared_count) + { + boost::throw_exception(boost::lock_error()); + } + } + + state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); + if(current_state==old_state) + { + break; + } + old_state=current_state; + } + + if(!(old_state.exclusive| old_state.exclusive_waiting_blocked)) + { + return true; + } + + chrono::system_clock::time_point n = chrono::system_clock::now(); + unsigned long res; + if (tp>n) { + chrono::milliseconds rel_time= chrono::ceil<chrono::milliseconds>(tp-n); + res=detail::win32::WaitForSingleObject(semaphores[unlock_sem], + static_cast<unsigned long>(rel_time.count())); + } else { + res=detail::win32::timeout; + } + if(res==detail::win32::timeout) + { + for(;;) + { + state_data new_state=old_state; + if(new_state.exclusive || new_state.exclusive_waiting_blocked) + { + if(new_state.shared_waiting) + { + --new_state.shared_waiting; + } + } + else + { + ++new_state.shared_count; + if(!new_state.shared_count) + { + return false; + } + } + + state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); + if(current_state==old_state) + { + break; + } + old_state=current_state; + } + + if(!(old_state.exclusive| old_state.exclusive_waiting_blocked)) + { + return true; + } + return false; + } + + BOOST_ASSERT(res==0); + } + } +#endif + + void unlock_shared() + { + state_data old_state=state; + for(;;) + { + state_data new_state=old_state; + bool const last_reader=!--new_state.shared_count; + + if(last_reader) + { + if(new_state.upgrade) + { + new_state.upgrade=false; + new_state.exclusive=true; + } + else + { + if(new_state.exclusive_waiting) + { + --new_state.exclusive_waiting; + new_state.exclusive_waiting_blocked=false; + } + new_state.shared_waiting=0; + } + } + + state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); + if(current_state==old_state) + { + if(last_reader) + { + if(old_state.upgrade) + { + BOOST_VERIFY(detail::win32::ReleaseSemaphore(upgrade_sem,1,0)!=0); + } + else + { + release_waiters(old_state); + } + } + break; + } + 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(;;) + { + state_data new_state=old_state; + if(new_state.shared_count || new_state.exclusive) + { + return false; + } + else + { + new_state.exclusive=true; + } + + state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); + if(current_state==old_state) + { + break; + } + 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; + + for(;;) + { + state_data new_state=old_state; + if(new_state.shared_count || new_state.exclusive) + { + ++new_state.exclusive_waiting; + if(!new_state.exclusive_waiting) + { + boost::throw_exception(boost::lock_error()); + } + + new_state.exclusive_waiting_blocked=true; + } + else + { + new_state.exclusive=true; + } + + state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); + if(current_state==old_state) + { + break; + } + old_state=current_state; + } + + if(!old_state.shared_count && !old_state.exclusive) + { + return true; + } + #ifndef UNDER_CE + const bool wait_all = true; + #else + const bool wait_all = false; + #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; + } + if(!old_state.shared_count && !old_state.exclusive) + { + return true; + } + 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); + } + template <class Clock, class Duration> + bool try_lock_until(const chrono::time_point<Clock, Duration>& t) + { + using namespace chrono; + system_clock::time_point s_now = system_clock::now(); + typename Clock::time_point c_now = Clock::now(); + return try_lock_until(s_now + ceil<system_clock::duration>(t - c_now)); + } + template <class Duration> + bool try_lock_until(const chrono::time_point<chrono::system_clock, Duration>& t) + { + using namespace chrono; + typedef time_point<chrono::system_clock, chrono::system_clock::duration> sys_tmpt; + return try_lock_until(sys_tmpt(chrono::ceil<chrono::system_clock::duration>(t.time_since_epoch()))); + } + bool try_lock_until(const chrono::time_point<chrono::system_clock, chrono::system_clock::duration>& tp) + { + for(;;) + { + state_data old_state=state; + + for(;;) + { + state_data new_state=old_state; + if(new_state.shared_count || new_state.exclusive) + { + ++new_state.exclusive_waiting; + if(!new_state.exclusive_waiting) + { + boost::throw_exception(boost::lock_error()); + } + + new_state.exclusive_waiting_blocked=true; + } + else + { + new_state.exclusive=true; + } + + state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); + if(current_state==old_state) + { + break; + } + old_state=current_state; + } + + if(!old_state.shared_count && !old_state.exclusive) + { + return true; + } + #ifndef UNDER_CE + const bool wait_all = true; + #else + const bool wait_all = false; + #endif + + chrono::system_clock::time_point n = chrono::system_clock::now(); + unsigned long wait_res; + if (tp>n) { + chrono::milliseconds rel_time= chrono::ceil<chrono::milliseconds>(tp-chrono::system_clock::now()); + wait_res=detail::win32::WaitForMultipleObjects(2,semaphores,wait_all, + static_cast<unsigned long>(rel_time.count())); + } else { + 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; + } + if(!old_state.shared_count && !old_state.exclusive) + { + return true; + } + return false; + } + BOOST_ASSERT(wait_res<2); + } + } +#endif + + void unlock() + { + state_data old_state=state; + for(;;) + { + state_data new_state=old_state; + new_state.exclusive=false; + if(new_state.exclusive_waiting) + { + --new_state.exclusive_waiting; + new_state.exclusive_waiting_blocked=false; + } + new_state.shared_waiting=0; + + state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); + if(current_state==old_state) + { + break; + } + old_state=current_state; + } + release_waiters(old_state); + } + + void lock_upgrade() + { + for(;;) + { + state_data old_state=state; + for(;;) + { + state_data new_state=old_state; + if(new_state.exclusive || new_state.exclusive_waiting_blocked || new_state.upgrade) + { + ++new_state.shared_waiting; + if(!new_state.shared_waiting) + { + boost::throw_exception(boost::lock_error()); + } + } + else + { + ++new_state.shared_count; + if(!new_state.shared_count) + { + boost::throw_exception(boost::lock_error()); + } + new_state.upgrade=true; + } + + state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); + if(current_state==old_state) + { + break; + } + old_state=current_state; + } + + if(!(old_state.exclusive|| old_state.exclusive_waiting_blocked|| old_state.upgrade)) + { + return; + } + + BOOST_VERIFY(!detail::win32::WaitForSingleObject(semaphores[unlock_sem],detail::win32::infinite)); + } + } + + bool try_lock_upgrade() + { + state_data old_state=state; + for(;;) + { + state_data new_state=old_state; + if(new_state.exclusive || new_state.exclusive_waiting_blocked || new_state.upgrade) + { + return false; + } + else + { + ++new_state.shared_count; + if(!new_state.shared_count) + { + return false; + } + new_state.upgrade=true; + } + + state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); + if(current_state==old_state) + { + break; + } + old_state=current_state; + } + return true; + } + + void unlock_upgrade() + { + state_data old_state=state; + for(;;) + { + state_data new_state=old_state; + new_state.upgrade=false; + bool const last_reader=!--new_state.shared_count; + + if(last_reader) + { + if(new_state.exclusive_waiting) + { + --new_state.exclusive_waiting; + new_state.exclusive_waiting_blocked=false; + } + new_state.shared_waiting=0; + } + + 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); + } + // #7720 + //else { + // release_waiters(old_state); + //} + break; + } + old_state=current_state; + } + } + + void unlock_upgrade_and_lock() + { + state_data old_state=state; + for(;;) + { + state_data new_state=old_state; + bool const last_reader=!--new_state.shared_count; + + if(last_reader) + { + new_state.upgrade=false; + new_state.exclusive=true; + } + + state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); + if(current_state==old_state) + { + if(!last_reader) + { + BOOST_VERIFY(!detail::win32::WaitForSingleObject(upgrade_sem,detail::win32::infinite)); + } + break; + } + old_state=current_state; + } + } + + void unlock_and_lock_upgrade() + { + state_data old_state=state; + for(;;) + { + state_data new_state=old_state; + new_state.exclusive=false; + new_state.upgrade=true; + ++new_state.shared_count; + if(new_state.exclusive_waiting) + { + --new_state.exclusive_waiting; + new_state.exclusive_waiting_blocked=false; + } + new_state.shared_waiting=0; + + state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); + if(current_state==old_state) + { + break; + } + old_state=current_state; + } + release_waiters(old_state); + } +// bool try_unlock_upgrade_and_lock() +// { +// return false; +// } +//#ifdef BOOST_THREAD_USES_CHRONO +// template <class Rep, class Period> +// bool +// try_unlock_upgrade_and_lock_for( +// const chrono::duration<Rep, Period>& rel_time) +// { +// return try_unlock_upgrade_and_lock_until( +// chrono::steady_clock::now() + rel_time); +// } +// template <class Clock, class Duration> +// bool +// try_unlock_upgrade_and_lock_until( +// const chrono::time_point<Clock, Duration>& abs_time) +// { +// return false; +// } +//#endif + + void unlock_and_lock_shared() + { + state_data old_state=state; + for(;;) + { + state_data new_state=old_state; + new_state.exclusive=false; + ++new_state.shared_count; + if(new_state.exclusive_waiting) + { + --new_state.exclusive_waiting; + new_state.exclusive_waiting_blocked=false; + } + new_state.shared_waiting=0; + + state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); + if(current_state==old_state) + { + break; + } + old_state=current_state; + } + release_waiters(old_state); + } + void unlock_upgrade_and_lock_shared() + { + state_data old_state=state; + for(;;) + { + state_data new_state=old_state; + new_state.upgrade=false; + if(new_state.exclusive_waiting) + { + --new_state.exclusive_waiting; + new_state.exclusive_waiting_blocked=false; + } + new_state.shared_waiting=0; + + state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); + if(current_state==old_state) + { + break; + } + old_state=current_state; + } + release_waiters(old_state); + } + + }; + typedef shared_mutex upgrade_mutex; + +} + +#include <boost/config/abi_suffix.hpp> + +#endif diff --git a/src/third_party/boost-1.56.0/boost/thread/win32/thread_data.hpp b/src/third_party/boost-1.56.0/boost/thread/win32/thread_data.hpp new file mode 100644 index 00000000000..1d4f57278d8 --- /dev/null +++ b/src/third_party/boost-1.56.0/boost/thread/win32/thread_data.hpp @@ -0,0 +1,313 @@ +#ifndef BOOST_THREAD_PTHREAD_THREAD_DATA_HPP +#define BOOST_THREAD_PTHREAD_THREAD_DATA_HPP +// 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) +// (C) Copyright 2008 Anthony Williams +// (C) Copyright 2011-2012 Vicente J. Botet Escriba + +#include <boost/thread/detail/config.hpp> +#include <boost/thread/thread_time.hpp> +#include <boost/thread/win32/thread_primitives.hpp> +#include <boost/thread/win32/thread_heap_alloc.hpp> + +#include <boost/intrusive_ptr.hpp> +#ifdef BOOST_THREAD_USES_CHRONO +#include <boost/chrono/system_clocks.hpp> +#endif + +#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 { + public: + thread_attributes() BOOST_NOEXCEPT { + val_.stack_size = 0; + //val_.lpThreadAttributes=0; + } + ~thread_attributes() { + } + // stack size + void set_stack_size(std::size_t size) BOOST_NOEXCEPT { + val_.stack_size = size; + } + + std::size_t get_stack_size() const BOOST_NOEXCEPT { + return val_.stack_size; + } + + //void set_security(LPSECURITY_ATTRIBUTES lpThreadAttributes) + //{ + // val_.lpThreadAttributes=lpThreadAttributes; + //} + //LPSECURITY_ATTRIBUTES get_security() + //{ + // return val_.lpThreadAttributes; + //} + + struct win_attrs { + std::size_t stack_size; + //LPSECURITY_ATTRIBUTES lpThreadAttributes; + }; + typedef win_attrs native_handle_type; + native_handle_type* native_handle() {return &val_;} + const native_handle_type* native_handle() const {return &val_;} + + 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; + + tss_data_node(boost::shared_ptr<boost::detail::tss_cleanup_function> func_, + void* value_): + func(func_),value(value_) + {} + }; + + struct thread_data_base; + void intrusive_ptr_add_ref(thread_data_base * p); + void intrusive_ptr_release(thread_data_base * p); + + struct BOOST_THREAD_DECL thread_data_base + { + long count; + detail::win32::handle_manager thread_handle; + boost::detail::thread_exit_callback_node* thread_exit_callbacks; + std::map<void const*,boost::detail::tss_data_node> tss_data; + 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), + thread_exit_callbacks(0),tss_data(), + id(0), + 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); + } + + friend void intrusive_ptr_release(thread_data_base * p) + { + 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; + + 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 + { + 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::GetTickCount64()()), + milliseconds(milliseconds_), + relative(true), + abs_time(boost::get_system_time()) + {} + + timeout(boost::system_time const& abs_time_): + start(win32::GetTickCount64()()), + milliseconds(0), + relative(false), + abs_time(abs_time_) + {} + + struct BOOST_SYMBOL_VISIBLE remaining_time + { + bool more; + unsigned long milliseconds; + + remaining_time(uintmax_t remaining): + more(remaining>max_non_infinite_wait), + milliseconds(more?max_non_infinite_wait:(unsigned long)remaining) + {} + }; + + remaining_time remaining_milliseconds() const + { + if(is_sentinel()) + { + return remaining_time(win32::infinite); + } + else if(relative) + { + 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) + { + return remaining_time(0); + } + return remaining_time((abs_time-now).total_milliseconds()+1); + } + } + + bool is_sentinel() const + { + return milliseconds==~uintmax_t(0); + } + + + static timeout sentinel() + { + return timeout(sentinel_type()); + } + private: + struct sentinel_type + {}; + + explicit timeout(sentinel_type): + start(0),milliseconds(~uintmax_t(0)),relative(true) + {} + }; + + inline uintmax_t pin_to_zero(intmax_t value) + { + return (value<0)?0u:(uintmax_t)value; + } + } + + namespace this_thread + { + void BOOST_THREAD_DECL yield() BOOST_NOEXCEPT; + + bool BOOST_THREAD_DECL interruptible_wait(detail::win32::handle handle_to_wait_for,detail::timeout target_time); + inline void interruptible_wait(uintmax_t milliseconds) + { + 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) + { + interruptible_wait(abs_time); + } +#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/src/third_party/boost-1.56.0/boost/thread/win32/thread_heap_alloc.hpp b/src/third_party/boost-1.56.0/boost/thread/win32/thread_heap_alloc.hpp new file mode 100644 index 00000000000..610fe3263e1 --- /dev/null +++ b/src/third_party/boost-1.56.0/boost/thread/win32/thread_heap_alloc.hpp @@ -0,0 +1,409 @@ +// 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) +// (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 +{ + namespace detail + { + namespace win32 + { + using ::GetProcessHeap; + using ::HeapAlloc; + using ::HeapFree; + } + } +} + +#else + +# ifdef HeapAlloc +# undef HeapAlloc +# endif + +namespace boost +{ + namespace detail + { + namespace win32 + { + extern "C" + { + __declspec(dllimport) handle __stdcall GetProcessHeap(); + __declspec(dllimport) void* __stdcall HeapAlloc(handle,unsigned long,ulong_ptr); + __declspec(dllimport) int __stdcall HeapFree(handle,unsigned long,void*); + } + } + } +} + +#endif + +#include <boost/config/abi_prefix.hpp> + +namespace boost +{ + namespace detail + { + inline void* allocate_raw_heap_memory(unsigned size) + { + void* const heap_memory=detail::win32::HeapAlloc(detail::win32::GetProcessHeap(),0,size); + if(!heap_memory) + { + boost::throw_exception(std::bad_alloc()); + } + return heap_memory; + } + + inline void free_raw_heap_memory(void* heap_memory) + { + BOOST_VERIFY(detail::win32::HeapFree(detail::win32::GetProcessHeap(),0,heap_memory)!=0); + } + + template<typename T> + inline T* heap_new() + { + void* const heap_memory=allocate_raw_heap_memory(sizeof(T)); + BOOST_TRY + { + T* const data=new (heap_memory) T(); + return data; + } + BOOST_CATCH(...) + { + free_raw_heap_memory(heap_memory); + BOOST_RETHROW + } + 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)); + BOOST_TRY + { + T* const data=new (heap_memory) T(static_cast<A1&&>(a1)); + return data; + } + BOOST_CATCH(...) + { + free_raw_heap_memory(heap_memory); + BOOST_RETHROW + } + 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)); + BOOST_TRY + { + T* const data=new (heap_memory) T(static_cast<A1&&>(a1),static_cast<A2&&>(a2)); + return data; + } + BOOST_CATCH(...) + { + free_raw_heap_memory(heap_memory); + BOOST_RETHROW + } + 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)); + BOOST_TRY + { + T* const data=new (heap_memory) T(static_cast<A1&&>(a1),static_cast<A2&&>(a2), + static_cast<A3&&>(a3)); + return data; + } + BOOST_CATCH(...) + { + free_raw_heap_memory(heap_memory); + BOOST_RETHROW + } + 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)); + 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; + } + BOOST_CATCH(...) + { + free_raw_heap_memory(heap_memory); + BOOST_RETHROW + } + 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)); + BOOST_TRY + { + T* const data=new (heap_memory) T(a1); + return data; + } + BOOST_CATCH(...) + { + free_raw_heap_memory(heap_memory); + BOOST_RETHROW + } + 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)); + BOOST_TRY + { + T* const data=new (heap_memory) T(a1,a2); + return data; + } + BOOST_CATCH(...) + { + free_raw_heap_memory(heap_memory); + BOOST_RETHROW + } + 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)); + BOOST_TRY + { + T* const data=new (heap_memory) T(a1,a2,a3); + return data; + } + BOOST_CATCH(...) + { + free_raw_heap_memory(heap_memory); + BOOST_RETHROW + } + 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)); + BOOST_TRY + { + T* const data=new (heap_memory) T(a1,a2,a3,a4); + return data; + } + BOOST_CATCH(...) + { + free_raw_heap_memory(heap_memory); + BOOST_RETHROW + } + BOOST_CATCH_END + } + + + template<typename T,typename A1> + inline T* heap_new(A1 const& a1) + { + return heap_new_impl<T,A1 const&>(a1); + } + template<typename T,typename A1> + inline T* heap_new(A1& a1) + { + return heap_new_impl<T,A1&>(a1); + } + + template<typename T,typename A1,typename A2> + inline T* heap_new(A1 const& a1,A2 const& a2) + { + return heap_new_impl<T,A1 const&,A2 const&>(a1,a2); + } + template<typename T,typename A1,typename A2> + inline T* heap_new(A1& a1,A2 const& a2) + { + return heap_new_impl<T,A1&,A2 const&>(a1,a2); + } + template<typename T,typename A1,typename A2> + inline T* heap_new(A1 const& a1,A2& a2) + { + return heap_new_impl<T,A1 const&,A2&>(a1,a2); + } + template<typename T,typename A1,typename A2> + inline T* heap_new(A1& a1,A2& a2) + { + return heap_new_impl<T,A1&,A2&>(a1,a2); + } + + template<typename T,typename A1,typename A2,typename A3> + inline T* heap_new(A1 const& a1,A2 const& a2,A3 const& a3) + { + return heap_new_impl<T,A1 const&,A2 const&,A3 const&>(a1,a2,a3); + } + template<typename T,typename A1,typename A2,typename A3> + inline T* heap_new(A1& a1,A2 const& a2,A3 const& a3) + { + return heap_new_impl<T,A1&,A2 const&,A3 const&>(a1,a2,a3); + } + template<typename T,typename A1,typename A2,typename A3> + inline T* heap_new(A1 const& a1,A2& a2,A3 const& a3) + { + return heap_new_impl<T,A1 const&,A2&,A3 const&>(a1,a2,a3); + } + template<typename T,typename A1,typename A2,typename A3> + inline T* heap_new(A1& a1,A2& a2,A3 const& a3) + { + return heap_new_impl<T,A1&,A2&,A3 const&>(a1,a2,a3); + } + + template<typename T,typename A1,typename A2,typename A3> + inline T* heap_new(A1 const& a1,A2 const& a2,A3& a3) + { + return heap_new_impl<T,A1 const&,A2 const&,A3&>(a1,a2,a3); + } + template<typename T,typename A1,typename A2,typename A3> + inline T* heap_new(A1& a1,A2 const& a2,A3& a3) + { + return heap_new_impl<T,A1&,A2 const&,A3&>(a1,a2,a3); + } + template<typename T,typename A1,typename A2,typename A3> + inline T* heap_new(A1 const& a1,A2& a2,A3& a3) + { + return heap_new_impl<T,A1 const&,A2&,A3&>(a1,a2,a3); + } + template<typename T,typename A1,typename A2,typename A3> + inline T* heap_new(A1& a1,A2& a2,A3& a3) + { + return heap_new_impl<T,A1&,A2&,A3&>(a1,a2,a3); + } + + template<typename T,typename A1,typename A2,typename A3,typename A4> + inline T* heap_new(A1 const& a1,A2 const& a2,A3 const& a3,A4 const& a4) + { + return heap_new_impl<T,A1 const&,A2 const&,A3 const&,A4 const&>(a1,a2,a3,a4); + } + template<typename T,typename A1,typename A2,typename A3,typename A4> + inline T* heap_new(A1& a1,A2 const& a2,A3 const& a3,A4 const& a4) + { + return heap_new_impl<T,A1&,A2 const&,A3 const&,A4 const&>(a1,a2,a3,a4); + } + template<typename T,typename A1,typename A2,typename A3,typename A4> + inline T* heap_new(A1 const& a1,A2& a2,A3 const& a3,A4 const& a4) + { + return heap_new_impl<T,A1 const&,A2&,A3 const&,A4 const&>(a1,a2,a3,a4); + } + template<typename T,typename A1,typename A2,typename A3,typename A4> + inline T* heap_new(A1& a1,A2& a2,A3 const& a3,A4 const& a4) + { + return heap_new_impl<T,A1&,A2&,A3 const&,A4 const&>(a1,a2,a3,a4); + } + + template<typename T,typename A1,typename A2,typename A3,typename A4> + inline T* heap_new(A1 const& a1,A2 const& a2,A3& a3,A4 const& a4) + { + return heap_new_impl<T,A1 const&,A2 const&,A3&,A4 const&>(a1,a2,a3,a4); + } + template<typename T,typename A1,typename A2,typename A3,typename A4> + inline T* heap_new(A1& a1,A2 const& a2,A3& a3,A4 const& a4) + { + return heap_new_impl<T,A1&,A2 const&,A3&,A4 const&>(a1,a2,a3,a4); + } + template<typename T,typename A1,typename A2,typename A3,typename A4> + inline T* heap_new(A1 const& a1,A2& a2,A3& a3,A4 const& a4) + { + return heap_new_impl<T,A1 const&,A2&,A3&,A4 const&>(a1,a2,a3,a4); + } + template<typename T,typename A1,typename A2,typename A3,typename A4> + inline T* heap_new(A1& a1,A2& a2,A3& a3,A4 const& a4) + { + return heap_new_impl<T,A1&,A2&,A3&,A4 const&>(a1,a2,a3,a4); + } + template<typename T,typename A1,typename A2,typename A3,typename A4> + inline T* heap_new(A1 const& a1,A2 const& a2,A3 const& a3,A4& a4) + { + return heap_new_impl<T,A1 const&,A2 const&,A3 const&,A4&>(a1,a2,a3,a4); + } + template<typename T,typename A1,typename A2,typename A3,typename A4> + inline T* heap_new(A1& a1,A2 const& a2,A3 const& a3,A4& a4) + { + return heap_new_impl<T,A1&,A2 const&,A3 const&,A4&>(a1,a2,a3,a4); + } + template<typename T,typename A1,typename A2,typename A3,typename A4> + inline T* heap_new(A1 const& a1,A2& a2,A3 const& a3,A4& a4) + { + return heap_new_impl<T,A1 const&,A2&,A3 const&,A4&>(a1,a2,a3,a4); + } + template<typename T,typename A1,typename A2,typename A3,typename A4> + inline T* heap_new(A1& a1,A2& a2,A3 const& a3,A4& a4) + { + return heap_new_impl<T,A1&,A2&,A3 const&,A4&>(a1,a2,a3,a4); + } + + template<typename T,typename A1,typename A2,typename A3,typename A4> + inline T* heap_new(A1 const& a1,A2 const& a2,A3& a3,A4& a4) + { + return heap_new_impl<T,A1 const&,A2 const&,A3&,A4&>(a1,a2,a3,a4); + } + template<typename T,typename A1,typename A2,typename A3,typename A4> + inline T* heap_new(A1& a1,A2 const& a2,A3& a3,A4& a4) + { + return heap_new_impl<T,A1&,A2 const&,A3&,A4&>(a1,a2,a3,a4); + } + template<typename T,typename A1,typename A2,typename A3,typename A4> + inline T* heap_new(A1 const& a1,A2& a2,A3& a3,A4& a4) + { + return heap_new_impl<T,A1 const&,A2&,A3&,A4&>(a1,a2,a3,a4); + } + template<typename T,typename A1,typename A2,typename A3,typename A4> + inline T* heap_new(A1& a1,A2& a2,A3& a3,A4& a4) + { + return heap_new_impl<T,A1&,A2&,A3&,A4&>(a1,a2,a3,a4); + } + +#endif + template<typename T> + inline void heap_delete(T* data) + { + data->~T(); + free_raw_heap_memory(data); + } + + template<typename T> + struct do_heap_delete + { + void operator()(T* data) const + { + detail::heap_delete(data); + } + }; + } +} + +#include <boost/config/abi_suffix.hpp> + + +#endif diff --git a/src/third_party/boost-1.56.0/boost/thread/win32/thread_primitives.hpp b/src/third_party/boost-1.56.0/boost/thread/win32/thread_primitives.hpp new file mode 100644 index 00000000000..fcf59b30752 --- /dev/null +++ b/src/third_party/boost-1.56.0/boost/thread/win32/thread_primitives.hpp @@ -0,0 +1,523 @@ +#ifndef BOOST_WIN32_THREAD_PRIMITIVES_HPP +#define BOOST_WIN32_THREAD_PRIMITIVES_HPP + +// win32_thread_primitives.hpp +// +// (C) Copyright 2005-7 Anthony Williams +// (C) Copyright 2007 David Deakins +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include <boost/thread/detail/config.hpp> +#include <boost/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 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; +# else + using ::CreateMutexA; + using ::CreateEventA; + using ::OpenEventA; + using ::CreateSemaphoreA; +# endif + using ::CloseHandle; + using ::ReleaseMutex; + using ::ReleaseSemaphore; + using ::SetEvent; + using ::ResetEvent; + using ::WaitForMultipleObjects; + using ::WaitForSingleObject; + using ::GetCurrentProcessId; + using ::GetCurrentThreadId; + using ::GetCurrentThread; + using ::GetCurrentProcess; + using ::DuplicateHandle; + using ::SleepEx; + using ::Sleep; + using ::QueueUserAPC; + } + } +} +#elif defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) + +# ifdef UNDER_CE +# ifndef WINAPI +# ifndef _WIN32_WCE_EMULATION +# define WINAPI __cdecl // Note this doesn't match the desktop definition +# else +# define WINAPI __stdcall +# endif +# endif + +# ifdef __cplusplus +extern "C" { +# endif +typedef int BOOL; +typedef unsigned long DWORD; +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*); + __declspec(dllimport) void* __stdcall CreateSemaphoreW(_SECURITY_ATTRIBUTES*,long,long,wchar_t const*); + __declspec(dllimport) void* __stdcall CreateEventW(_SECURITY_ATTRIBUTES*,int,int,wchar_t const*); + __declspec(dllimport) void* __stdcall OpenEventW(unsigned long,int,wchar_t const*); +# else + __declspec(dllimport) void* __stdcall CreateMutexA(_SECURITY_ATTRIBUTES*,int,char const*); + __declspec(dllimport) void* __stdcall CreateSemaphoreA(_SECURITY_ATTRIBUTES*,long,long,char const*); + __declspec(dllimport) void* __stdcall CreateEventA(_SECURITY_ATTRIBUTES*,int,int,char const*); + __declspec(dllimport) void* __stdcall OpenEventA(unsigned long,int,char const*); +# endif + __declspec(dllimport) int __stdcall CloseHandle(void*); + __declspec(dllimport) int __stdcall ReleaseMutex(void*); + __declspec(dllimport) unsigned long __stdcall WaitForSingleObject(void*,unsigned long); + __declspec(dllimport) unsigned long __stdcall WaitForMultipleObjects(unsigned long nCount,void* const * lpHandles,int bWaitAll,unsigned long dwMilliseconds); + __declspec(dllimport) int __stdcall ReleaseSemaphore(void*,long,long*); + __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); + +# 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*); + __declspec(dllimport) int __stdcall ResetEvent(void*); +# else + using ::GetCurrentProcessId; + using ::GetCurrentThreadId; + using ::GetCurrentThread; + using ::GetCurrentProcess; + using ::SetEvent; + using ::ResetEvent; +# endif + } + } + } +} +#else +# error "Win32 functions not available" +#endif + +#include <boost/config/abi_prefix.hpp> + +namespace boost +{ + namespace detail + { + namespace win32 + { + 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 + { + event_initially_reset=false, + event_initially_set=true + }; + + inline handle create_anonymous_event(event_type type,initial_event_state state) + { +#if !defined(BOOST_NO_ANSI_APIS) + handle const res=win32::CreateEventA(0,type,state,0); +#else + handle const res=win32::CreateEventW(0,type,state,0); +#endif + if(!res) + { + boost::throw_exception(thread_resource_error()); + } + return res; + } + + inline handle create_anonymous_semaphore(long initial_count,long max_count) + { +#if !defined(BOOST_NO_ANSI_APIS) + handle const res=CreateSemaphoreA(0,initial_count,max_count,0); +#else + handle const res=CreateSemaphoreW(0,initial_count,max_count,0); +#endif + if(!res) + { + boost::throw_exception(thread_resource_error()); + } + return res; + } + inline handle create_anonymous_semaphore_nothrow(long initial_count,long max_count) + { +#if !defined(BOOST_NO_ANSI_APIS) + handle const res=CreateSemaphoreA(0,initial_count,max_count,0); +#else + handle const res=CreateSemaphoreW(0,initial_count,max_count,0); +#endif + return res; + } + + inline handle duplicate_handle(handle source) + { + handle const current_process=GetCurrentProcess(); + long const same_access_flag=2; + handle new_handle=0; + bool const success=DuplicateHandle(current_process,source,current_process,&new_handle,0,false,same_access_flag)!=0; + if(!success) + { + boost::throw_exception(thread_resource_error()); + } + return new_handle; + } + + inline void release_semaphore(handle semaphore,long count) + { + BOOST_VERIFY(ReleaseSemaphore(semaphore,count,0)!=0); + } + + class BOOST_THREAD_DECL handle_manager + { + private: + handle handle_to_manage; + handle_manager(handle_manager&); + handle_manager& operator=(handle_manager&); + + void cleanup() + { + if(handle_to_manage && handle_to_manage!=invalid_handle_value) + { + BOOST_VERIFY(CloseHandle(handle_to_manage)); + } + } + + public: + explicit handle_manager(handle handle_to_manage_): + handle_to_manage(handle_to_manage_) + {} + handle_manager(): + handle_to_manage(0) + {} + + handle_manager& operator=(handle new_handle) + { + cleanup(); + handle_to_manage=new_handle; + return *this; + } + + operator handle() const + { + return handle_to_manage; + } + + handle duplicate() const + { + return duplicate_handle(handle_to_manage); + } + + void swap(handle_manager& other) + { + std::swap(handle_to_manage,other.handle_to_manage); + } + + handle release() + { + handle const res=handle_to_manage; + handle_to_manage=0; + return res; + } + + bool operator!() const + { + return !handle_to_manage; + } + + ~handle_manager() + { + cleanup(); + } + }; + + } + } +} + +#if defined(BOOST_MSVC) && (_MSC_VER>=1400) && !defined(UNDER_CE) + +namespace boost +{ + namespace detail + { + namespace win32 + { +#if _MSC_VER==1400 + extern "C" unsigned char _interlockedbittestandset(long *a,long b); + extern "C" unsigned char _interlockedbittestandreset(long *a,long b); +#else + extern "C" unsigned char _interlockedbittestandset(volatile long *a,long b); + extern "C" unsigned char _interlockedbittestandreset(volatile long *a,long b); +#endif + +#pragma intrinsic(_interlockedbittestandset) +#pragma intrinsic(_interlockedbittestandreset) + + inline bool interlocked_bit_test_and_set(long* x,long bit) + { + return _interlockedbittestandset(x,bit)!=0; + } + + inline bool interlocked_bit_test_and_reset(long* x,long bit) + { + return _interlockedbittestandreset(x,bit)!=0; + } + + } + } +} +#define BOOST_THREAD_BTS_DEFINED +#elif (defined(BOOST_MSVC) || defined(BOOST_INTEL_WIN)) && defined(_M_IX86) +namespace boost +{ + namespace detail + { + namespace win32 + { + inline bool interlocked_bit_test_and_set(long* x,long bit) + { +#ifndef BOOST_INTEL_CXX_VERSION + __asm { + mov eax,bit; + mov edx,x; + lock bts [edx],eax; + setc al; + }; +#else + bool ret; + __asm { + mov eax,bit + mov edx,x + lock bts [edx],eax + setc al + mov ret, al + }; + return ret; + +#endif + } + + inline bool interlocked_bit_test_and_reset(long* x,long bit) + { +#ifndef BOOST_INTEL_CXX_VERSION + __asm { + mov eax,bit; + mov edx,x; + lock btr [edx],eax; + setc al; + }; +#else + bool ret; + __asm { + mov eax,bit + mov edx,x + lock btr [edx],eax + setc al + mov ret, al + }; + return ret; + +#endif + } + + } + } +} +#define BOOST_THREAD_BTS_DEFINED +#endif + +#ifndef BOOST_THREAD_BTS_DEFINED + +namespace boost +{ + namespace detail + { + namespace win32 + { + inline bool interlocked_bit_test_and_set(long* x,long bit) + { + long const value=1<<bit; + long old=*x; + do + { + long const current=BOOST_INTERLOCKED_COMPARE_EXCHANGE(x,old|value,old); + if(current==old) + { + break; + } + old=current; + } + while(true); + return (old&value)!=0; + } + + inline bool interlocked_bit_test_and_reset(long* x,long bit) + { + long const value=1<<bit; + long old=*x; + do + { + long const current=BOOST_INTERLOCKED_COMPARE_EXCHANGE(x,old&~value,old); + if(current==old) + { + break; + } + old=current; + } + while(true); + return (old&value)!=0; + } + } + } +} +#endif + +#include <boost/config/abi_suffix.hpp> + +#endif |