feat():initial version
This commit is contained in:
@@ -0,0 +1,176 @@
|
||||
#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,2017-2018 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=boost::winapi::GetCurrentThreadId();
|
||||
return try_recursive_lock(current_thread_id) || try_basic_lock(current_thread_id);
|
||||
}
|
||||
|
||||
void lock()
|
||||
{
|
||||
long const current_thread_id=boost::winapi::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=boost::winapi::GetCurrentThreadId();
|
||||
return try_recursive_lock(current_thread_id) || try_timed_lock(current_thread_id,target);
|
||||
}
|
||||
template<typename Duration>
|
||||
bool timed_lock(Duration const& target)
|
||||
{
|
||||
long const current_thread_id=boost::winapi::GetCurrentThreadId();
|
||||
return try_recursive_lock(current_thread_id) || try_timed_lock(current_thread_id,target);
|
||||
}
|
||||
#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=boost::winapi::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=boost::winapi::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;
|
||||
}
|
||||
template<typename Duration>
|
||||
bool try_timed_lock(long current_thread_id,Duration 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
|
||||
@@ -0,0 +1,297 @@
|
||||
#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/thread/detail/platform_time.hpp>
|
||||
|
||||
#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)
|
||||
{
|
||||
winapi::CloseHandle(old_event);
|
||||
}
|
||||
}
|
||||
|
||||
// Take the lock flag if it's available
|
||||
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)
|
||||
{
|
||||
void* const sem=get_event();
|
||||
|
||||
do
|
||||
{
|
||||
if(winapi::WaitForSingleObjectEx(sem,::boost::detail::win32::infinite,0)==0)
|
||||
{
|
||||
clear_waiting_and_try_lock(old_count);
|
||||
}
|
||||
}
|
||||
while(old_count&lock_flag_value);
|
||||
}
|
||||
}
|
||||
|
||||
// Loop until the number of waiters has been incremented or we've taken the lock flag
|
||||
// The loop is necessary since this function may be called by multiple threads simultaneously
|
||||
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;
|
||||
// else we've taken the lock flag
|
||||
// don't update old_count so that the calling function can see that
|
||||
// the old lock flag was 0 and know that we've taken the lock flag
|
||||
break;
|
||||
}
|
||||
old_count=current;
|
||||
}
|
||||
}
|
||||
|
||||
// Loop until someone else has taken the lock flag and cleared the event set flag or
|
||||
// until we've taken the lock flag and cleared the event set flag and decremented the
|
||||
// number of waiters
|
||||
// The loop is necessary since this function may be called by multiple threads simultaneously
|
||||
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)
|
||||
{
|
||||
// if someone else has taken the lock flag
|
||||
// no need to update old_count since old_count == new_count (ignoring
|
||||
// event_set_flag_value which the calling function doesn't care about)
|
||||
// else we've taken the lock flag
|
||||
// don't update old_count so that the calling function can see that
|
||||
// the old lock flag was 0 and know that we've taken the lock flag
|
||||
break;
|
||||
}
|
||||
old_count=current;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned long getMs(detail::platform_duration const& d)
|
||||
{
|
||||
return static_cast<unsigned long>(d.getMs());
|
||||
}
|
||||
|
||||
template <typename Duration>
|
||||
unsigned long getMs(Duration const& d)
|
||||
{
|
||||
return static_cast<unsigned long>(chrono::ceil<chrono::milliseconds>(d).count());
|
||||
}
|
||||
|
||||
template <typename Clock, typename Timepoint, typename Duration>
|
||||
bool do_lock_until(Timepoint const& t, Duration const& max)
|
||||
{
|
||||
if(try_lock())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
long old_count=active_count;
|
||||
mark_waiting_and_try_lock(old_count);
|
||||
|
||||
if(old_count&lock_flag_value)
|
||||
{
|
||||
void* const sem=get_event();
|
||||
|
||||
// If the clock is the system clock, it may jump while this function
|
||||
// is waiting. To compensate for this and time out near the correct
|
||||
// time, we call WaitForSingleObjectEx() in a loop with a short
|
||||
// timeout and recheck the time remaining each time through the loop.
|
||||
do
|
||||
{
|
||||
Duration d(t - Clock::now());
|
||||
if(d <= Duration::zero()) // timeout occurred
|
||||
{
|
||||
BOOST_INTERLOCKED_DECREMENT(&active_count);
|
||||
return false;
|
||||
}
|
||||
if(max != Duration::zero())
|
||||
{
|
||||
d = (std::min)(d, max);
|
||||
}
|
||||
if(winapi::WaitForSingleObjectEx(sem,getMs(d),0)==0)
|
||||
{
|
||||
clear_waiting_and_try_lock(old_count);
|
||||
}
|
||||
}
|
||||
while(old_count&lock_flag_value);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
public:
|
||||
|
||||
#if defined BOOST_THREAD_USES_DATETIME
|
||||
bool timed_lock(::boost::system_time const& wait_until)
|
||||
{
|
||||
const detail::real_platform_timepoint t(wait_until);
|
||||
return do_lock_until<detail::real_platform_clock>(t, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
|
||||
}
|
||||
|
||||
template<typename Duration>
|
||||
bool timed_lock(Duration const& timeout)
|
||||
{
|
||||
const detail::mono_platform_timepoint t(detail::mono_platform_clock::now() + detail::platform_duration(timeout));
|
||||
// The reference clock is steady and so no need to poll periodically, thus 0 ms max (i.e. no max)
|
||||
return do_lock_until<detail::mono_platform_clock>(t, detail::platform_duration::zero());
|
||||
}
|
||||
|
||||
bool timed_lock(boost::xtime const& timeout)
|
||||
{
|
||||
return timed_lock(boost::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)
|
||||
{
|
||||
const chrono::steady_clock::time_point t(chrono::steady_clock::now() + rel_time);
|
||||
typedef typename chrono::duration<Rep, Period> Duration;
|
||||
typedef typename common_type<Duration, typename chrono::steady_clock::duration>::type common_duration;
|
||||
// The reference clock is steady and so no need to poll periodically, thus 0 ms max (i.e. no max)
|
||||
return do_lock_until<chrono::steady_clock>(t, common_duration::zero());
|
||||
}
|
||||
template <class Duration>
|
||||
bool try_lock_until(const chrono::time_point<chrono::steady_clock, Duration>& t)
|
||||
{
|
||||
typedef typename common_type<Duration, typename chrono::steady_clock::duration>::type common_duration;
|
||||
// The reference clock is steady and so no need to poll periodically, thus 0 ms max (i.e. no max)
|
||||
return do_lock_until<chrono::steady_clock>(t, common_duration::zero());
|
||||
}
|
||||
template <class Clock, class Duration>
|
||||
bool try_lock_until(const chrono::time_point<Clock, Duration>& t)
|
||||
{
|
||||
typedef typename common_type<Duration, typename Clock::duration>::type common_duration;
|
||||
return do_lock_until<Clock>(t, common_duration(chrono::milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS)));
|
||||
}
|
||||
#endif
|
||||
|
||||
void unlock()
|
||||
{
|
||||
// Clear the lock flag using atomic addition (works since long is always 32 bits on Windows)
|
||||
long const old_count=BOOST_INTERLOCKED_EXCHANGE_ADD(&active_count,lock_flag_value);
|
||||
// If someone is waiting to take the lock, set the event set flag and, if
|
||||
// the event set flag hadn't already been set, send an event.
|
||||
if(!(old_count&event_set_flag_value) && (old_count>lock_flag_value))
|
||||
{
|
||||
if(!win32::interlocked_bit_test_and_set(&active_count,event_set_flag_bit))
|
||||
{
|
||||
winapi::SetEvent(get_event());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
// Create an event in a thread-safe way
|
||||
// The first thread to create the event wins and all other thread will use that event
|
||||
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)
|
||||
{
|
||||
winapi::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
|
||||
@@ -0,0 +1,725 @@
|
||||
#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/thread/detail/platform_time.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;
|
||||
winapi::ReleaseSemaphore(semaphore,count_to_release,0);
|
||||
}
|
||||
|
||||
void release_waiters()
|
||||
{
|
||||
release(detail::interlocked_read_acquire(&waiters));
|
||||
}
|
||||
|
||||
bool is_notified() const
|
||||
{
|
||||
return notified;
|
||||
}
|
||||
|
||||
bool interruptible_wait(detail::internal_platform_timepoint const &timeout)
|
||||
{
|
||||
return this_thread::interruptible_wait(semaphore, timeout);
|
||||
}
|
||||
|
||||
bool woken()
|
||||
{
|
||||
unsigned long const woken_result=winapi::WaitForSingleObjectEx(wake_sem,0,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);
|
||||
winapi::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()
|
||||
{
|
||||
if ( ! _unlocked )
|
||||
{
|
||||
_lock.unlock();
|
||||
_unlocked=true;
|
||||
}
|
||||
}
|
||||
void lock()
|
||||
{
|
||||
if ( _unlocked )
|
||||
{
|
||||
_lock.lock();
|
||||
_unlocked=false;
|
||||
}
|
||||
}
|
||||
~relocker() BOOST_NOEXCEPT_IF(false)
|
||||
{
|
||||
lock();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
entry_ptr get_wait_entry()
|
||||
{
|
||||
boost::lock_guard<boost::mutex> lk(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 entry;
|
||||
boost::mutex& internal_mutex;
|
||||
|
||||
|
||||
BOOST_THREAD_NO_COPYABLE(entry_manager)
|
||||
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
entry_manager(entry_ptr&& entry_, boost::mutex& mutex_):
|
||||
entry(static_cast< entry_ptr&& >(entry_)), internal_mutex(mutex_)
|
||||
{}
|
||||
#else
|
||||
entry_manager(entry_ptr const& entry_, boost::mutex& mutex_):
|
||||
entry(entry_), internal_mutex(mutex_)
|
||||
{}
|
||||
#endif
|
||||
|
||||
void remove_waiter_and_reset()
|
||||
{
|
||||
if (entry) {
|
||||
boost::lock_guard<boost::mutex> internal_lock(internal_mutex);
|
||||
entry->remove_waiter();
|
||||
entry.reset();
|
||||
}
|
||||
}
|
||||
~entry_manager() BOOST_NOEXCEPT_IF(false)
|
||||
{
|
||||
remove_waiter_and_reset();
|
||||
}
|
||||
|
||||
list_entry* operator->()
|
||||
{
|
||||
return entry.get();
|
||||
}
|
||||
};
|
||||
|
||||
protected:
|
||||
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()
|
||||
{}
|
||||
|
||||
// When this function returns true:
|
||||
// * A notification (or sometimes a spurious OS signal) has been received
|
||||
// * Do not assume that the timeout has not been reached
|
||||
// * Do not assume that the predicate has been changed
|
||||
//
|
||||
// When this function returns false:
|
||||
// * The timeout has been reached
|
||||
// * Do not assume that a notification has not been received
|
||||
// * Do not assume that the predicate has not been changed
|
||||
template<typename lock_type>
|
||||
bool do_wait_until(lock_type& lock, detail::internal_platform_timepoint const &timeout)
|
||||
{
|
||||
relocker<lock_type> locker(lock);
|
||||
entry_manager entry(get_wait_entry(), internal_mutex);
|
||||
locker.unlock();
|
||||
|
||||
bool woken=false;
|
||||
while(!woken)
|
||||
{
|
||||
if(!entry->interruptible_wait(timeout))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
woken=entry->woken();
|
||||
}
|
||||
// do it here to avoid throwing on the destructor
|
||||
entry.remove_waiter_and_reset();
|
||||
locker.lock();
|
||||
return true;
|
||||
}
|
||||
|
||||
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::do_wait_until;
|
||||
using detail::basic_condition_variable::notify_one;
|
||||
using detail::basic_condition_variable::notify_all;
|
||||
|
||||
void wait(unique_lock<mutex>& m)
|
||||
{
|
||||
do_wait_until(m, detail::internal_platform_timepoint::getMax());
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
// The system time may jump while this function is waiting. To compensate for this and time
|
||||
// out near the correct time, we could call do_wait_until() in a loop with a short timeout
|
||||
// and recheck the time remaining each time through the loop. However, because we can't
|
||||
// check the predicate each time do_wait_until() completes, this introduces the possibility
|
||||
// of not exiting the function when a notification occurs, since do_wait_until() may report
|
||||
// that it timed out even though a notification was received. The best this function can do
|
||||
// is report correctly whether or not it reached the timeout time.
|
||||
const detail::real_platform_timepoint ts(abs_time);
|
||||
const detail::platform_duration d(ts - detail::real_platform_clock::now());
|
||||
do_wait_until(m, detail::internal_platform_clock::now() + d);
|
||||
return ts > detail::real_platform_clock::now();
|
||||
}
|
||||
bool timed_wait(unique_lock<mutex>& m,boost::xtime const& abs_time)
|
||||
{
|
||||
return timed_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);
|
||||
return true;
|
||||
}
|
||||
if (wait_duration.is_special())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
const detail::platform_duration d(wait_duration);
|
||||
return do_wait_until(m, detail::internal_platform_clock::now() + d);
|
||||
}
|
||||
|
||||
template<typename predicate_type>
|
||||
bool timed_wait(unique_lock<mutex>& m,boost::system_time const& abs_time,predicate_type pred)
|
||||
{
|
||||
// The system time may jump while this function is waiting. To compensate for this
|
||||
// and time out near the correct time, we call do_wait_until() in a loop with a
|
||||
// short timeout and recheck the time remaining each time through the loop.
|
||||
const detail::real_platform_timepoint ts(abs_time);
|
||||
while (!pred())
|
||||
{
|
||||
detail::platform_duration d(ts - detail::real_platform_clock::now());
|
||||
if (d <= detail::platform_duration::zero()) break; // timeout occurred
|
||||
d = (std::min)(d, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
|
||||
do_wait_until(m, detail::internal_platform_clock::now() + d);
|
||||
}
|
||||
return pred();
|
||||
}
|
||||
template<typename predicate_type>
|
||||
bool timed_wait(unique_lock<mutex>& m,boost::xtime const& abs_time,predicate_type pred)
|
||||
{
|
||||
return timed_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)
|
||||
{
|
||||
if (wait_duration.is_pos_infinity())
|
||||
{
|
||||
while (!pred())
|
||||
{
|
||||
wait(m);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (wait_duration.is_special())
|
||||
{
|
||||
return pred();
|
||||
}
|
||||
const detail::platform_duration d(wait_duration);
|
||||
const detail::internal_platform_timepoint ts(detail::internal_platform_clock::now() + d);
|
||||
while (!pred())
|
||||
{
|
||||
if (!do_wait_until(m, ts)) break; // timeout occurred
|
||||
}
|
||||
return pred();
|
||||
}
|
||||
#endif
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
template <class Duration>
|
||||
cv_status
|
||||
wait_until(
|
||||
unique_lock<mutex>& lock,
|
||||
const chrono::time_point<detail::internal_chrono_clock, Duration>& t)
|
||||
{
|
||||
const detail::internal_platform_timepoint ts(t);
|
||||
if (do_wait_until(lock, ts)) return cv_status::no_timeout;
|
||||
else return cv_status::timeout;
|
||||
}
|
||||
|
||||
template <class Clock, class Duration>
|
||||
cv_status
|
||||
wait_until(
|
||||
unique_lock<mutex>& lock,
|
||||
const chrono::time_point<Clock, Duration>& t)
|
||||
{
|
||||
// The system time may jump while this function is waiting. To compensate for this and time
|
||||
// out near the correct time, we could call do_wait_until() in a loop with a short timeout
|
||||
// and recheck the time remaining each time through the loop. However, because we can't
|
||||
// check the predicate each time do_wait_until() completes, this introduces the possibility
|
||||
// of not exiting the function when a notification occurs, since do_wait_until() may report
|
||||
// that it timed out even though a notification was received. The best this function can do
|
||||
// is report correctly whether or not it reached the timeout time.
|
||||
typedef typename common_type<Duration, typename Clock::duration>::type common_duration;
|
||||
common_duration d(t - Clock::now());
|
||||
do_wait_until(lock, detail::internal_chrono_clock::now() + d);
|
||||
if (t > Clock::now()) return cv_status::no_timeout;
|
||||
else return cv_status::timeout;
|
||||
}
|
||||
|
||||
template <class Rep, class Period>
|
||||
cv_status
|
||||
wait_for(
|
||||
unique_lock<mutex>& lock,
|
||||
const chrono::duration<Rep, Period>& d)
|
||||
{
|
||||
return wait_until(lock, chrono::steady_clock::now() + d);
|
||||
}
|
||||
|
||||
template <class Duration, class Predicate>
|
||||
bool
|
||||
wait_until(
|
||||
unique_lock<mutex>& lock,
|
||||
const chrono::time_point<detail::internal_chrono_clock, Duration>& t,
|
||||
Predicate pred)
|
||||
{
|
||||
const detail::internal_platform_timepoint ts(t);
|
||||
while (!pred())
|
||||
{
|
||||
if (!do_wait_until(lock, ts)) break; // timeout occurred
|
||||
}
|
||||
return pred();
|
||||
}
|
||||
|
||||
template <class Clock, class Duration, class Predicate>
|
||||
bool
|
||||
wait_until(
|
||||
unique_lock<mutex>& lock,
|
||||
const chrono::time_point<Clock, Duration>& t,
|
||||
Predicate pred)
|
||||
{
|
||||
// The system time may jump while this function is waiting. To compensate for this
|
||||
// and time out near the correct time, we call do_wait_until() in a loop with a
|
||||
// short timeout and recheck the time remaining each time through the loop.
|
||||
typedef typename common_type<Duration, typename Clock::duration>::type common_duration;
|
||||
while (!pred())
|
||||
{
|
||||
common_duration d(t - Clock::now());
|
||||
if (d <= common_duration::zero()) break; // timeout occurred
|
||||
d = (std::min)(d, common_duration(chrono::milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS)));
|
||||
do_wait_until(lock, detail::internal_platform_clock::now() + detail::platform_duration(d));
|
||||
}
|
||||
return pred();
|
||||
}
|
||||
|
||||
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::do_wait_until;
|
||||
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_until(m, detail::internal_platform_timepoint::getMax());
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
// The system time may jump while this function is waiting. To compensate for this and time
|
||||
// out near the correct time, we could call do_wait_until() in a loop with a short timeout
|
||||
// and recheck the time remaining each time through the loop. However, because we can't
|
||||
// check the predicate each time do_wait_until() completes, this introduces the possibility
|
||||
// of not exiting the function when a notification occurs, since do_wait_until() may report
|
||||
// that it timed out even though a notification was received. The best this function can do
|
||||
// is report correctly whether or not it reached the timeout time.
|
||||
const detail::real_platform_timepoint ts(abs_time);
|
||||
const detail::platform_duration d(ts - detail::real_platform_clock::now());
|
||||
do_wait_until(m, detail::internal_platform_clock::now() + d);
|
||||
return ts > detail::real_platform_clock::now();
|
||||
}
|
||||
|
||||
template<typename lock_type>
|
||||
bool timed_wait(lock_type& m,boost::xtime const& abs_time)
|
||||
{
|
||||
return timed_wait(m, system_time(abs_time));
|
||||
}
|
||||
|
||||
template<typename lock_type,typename duration_type>
|
||||
bool timed_wait(lock_type& m,duration_type const& wait_duration)
|
||||
{
|
||||
if (wait_duration.is_pos_infinity())
|
||||
{
|
||||
wait(m);
|
||||
return true;
|
||||
}
|
||||
if (wait_duration.is_special())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
const detail::platform_duration d(wait_duration);
|
||||
return do_wait_until(m, detail::internal_platform_clock::now() + d);
|
||||
}
|
||||
|
||||
template<typename lock_type,typename predicate_type>
|
||||
bool timed_wait(lock_type& m,boost::system_time const& abs_time,predicate_type pred)
|
||||
{
|
||||
// The system time may jump while this function is waiting. To compensate for this
|
||||
// and time out near the correct time, we call do_wait_until() in a loop with a
|
||||
// short timeout and recheck the time remaining each time through the loop.
|
||||
const detail::real_platform_timepoint ts(abs_time);
|
||||
while (!pred())
|
||||
{
|
||||
detail::platform_duration d(ts - detail::real_platform_clock::now());
|
||||
if (d <= detail::platform_duration::zero()) break; // timeout occurred
|
||||
d = (std::min)(d, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
|
||||
do_wait_until(m, detail::internal_platform_clock::now() + d);
|
||||
}
|
||||
return pred();
|
||||
}
|
||||
|
||||
template<typename lock_type,typename predicate_type>
|
||||
bool timed_wait(lock_type& m,boost::xtime const& abs_time,predicate_type pred)
|
||||
{
|
||||
return timed_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)
|
||||
{
|
||||
if (wait_duration.is_pos_infinity())
|
||||
{
|
||||
while (!pred())
|
||||
{
|
||||
wait(m);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (wait_duration.is_special())
|
||||
{
|
||||
return pred();
|
||||
}
|
||||
const detail::platform_duration d(wait_duration);
|
||||
const detail::internal_platform_timepoint ts(detail::internal_platform_clock::now() + d);
|
||||
while (!pred())
|
||||
{
|
||||
if (!do_wait_until(m, ts)) break; // timeout occurred
|
||||
}
|
||||
return pred();
|
||||
}
|
||||
#endif
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
template <class lock_type,class Duration>
|
||||
cv_status
|
||||
wait_until(
|
||||
lock_type& lock,
|
||||
const chrono::time_point<detail::internal_chrono_clock, Duration>& t)
|
||||
{
|
||||
const detail::internal_platform_timepoint ts(t);
|
||||
if (do_wait_until(lock, ts)) return cv_status::no_timeout;
|
||||
else return cv_status::timeout;
|
||||
}
|
||||
|
||||
template <class lock_type, class Clock, class Duration>
|
||||
cv_status
|
||||
wait_until(
|
||||
lock_type& lock,
|
||||
const chrono::time_point<Clock, Duration>& t)
|
||||
{
|
||||
// The system time may jump while this function is waiting. To compensate for this and time
|
||||
// out near the correct time, we could call do_wait_until() in a loop with a short timeout
|
||||
// and recheck the time remaining each time through the loop. However, because we can't
|
||||
// check the predicate each time do_wait_until() completes, this introduces the possibility
|
||||
// of not exiting the function when a notification occurs, since do_wait_until() may report
|
||||
// that it timed out even though a notification was received. The best this function can do
|
||||
// is report correctly whether or not it reached the timeout time.
|
||||
typedef typename common_type<Duration, typename Clock::duration>::type common_duration;
|
||||
common_duration d(t - Clock::now());
|
||||
do_wait_until(lock, detail::internal_chrono_clock::now() + d);
|
||||
if (t > Clock::now()) return cv_status::no_timeout;
|
||||
else return cv_status::timeout;
|
||||
}
|
||||
|
||||
template <class lock_type, class Rep, class Period>
|
||||
cv_status
|
||||
wait_for(
|
||||
lock_type& lock,
|
||||
const chrono::duration<Rep, Period>& d)
|
||||
{
|
||||
return wait_until(lock, chrono::steady_clock::now() + d);
|
||||
}
|
||||
|
||||
template <class lock_type, class Clock, class Duration, class Predicate>
|
||||
bool
|
||||
wait_until(
|
||||
lock_type& lock,
|
||||
const chrono::time_point<detail::internal_chrono_clock, Duration>& t,
|
||||
Predicate pred)
|
||||
{
|
||||
const detail::internal_platform_timepoint ts(t);
|
||||
while (!pred())
|
||||
{
|
||||
if (!do_wait_until(lock, ts)) break; // timeout occurred
|
||||
}
|
||||
return pred();
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
// The system time may jump while this function is waiting. To compensate for this
|
||||
// and time out near the correct time, we call do_wait_until() in a loop with a
|
||||
// short timeout and recheck the time remaining each time through the loop.
|
||||
typedef typename common_type<Duration, typename Clock::duration>::type common_duration;
|
||||
while (!pred())
|
||||
{
|
||||
common_duration d(t - Clock::now());
|
||||
if (d <= common_duration::zero()) break; // timeout occurred
|
||||
d = (std::min)(d, common_duration(chrono::milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS)));
|
||||
do_wait_until(lock, detail::internal_platform_clock::now() + detail::platform_duration(d));
|
||||
}
|
||||
return pred();
|
||||
}
|
||||
|
||||
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
|
||||
@@ -0,0 +1,216 @@
|
||||
#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
|
||||
// (C) Copyright 2017 Andrey Semashev
|
||||
//
|
||||
// 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>
|
||||
|
||||
// Define compiler barriers
|
||||
#if defined(__INTEL_COMPILER)
|
||||
#define BOOST_THREAD_DETAIL_COMPILER_BARRIER() __memory_barrier()
|
||||
#elif defined(__clang__)
|
||||
#define BOOST_THREAD_DETAIL_COMPILER_BARRIER() __atomic_signal_fence(__ATOMIC_SEQ_CST)
|
||||
#elif defined(_MSC_VER) && !defined(_WIN32_WCE)
|
||||
extern "C" void _ReadWriteBarrier(void);
|
||||
#pragma intrinsic(_ReadWriteBarrier)
|
||||
#define BOOST_THREAD_DETAIL_COMPILER_BARRIER() _ReadWriteBarrier()
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_THREAD_DETAIL_COMPILER_BARRIER
|
||||
#define BOOST_THREAD_DETAIL_COMPILER_BARRIER()
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))
|
||||
|
||||
// Since VS2005 and until VS2012 volatile reads always acquire and volatile writes are always release.
|
||||
// But VS2012 adds a compiler switch that can change behavior to the standard. On x86 though
|
||||
// the compiler generates a single instruction for the load/store, which is enough synchronization
|
||||
// as far as uarch is concerned. To prevent compiler reordering code around the load/store we add
|
||||
// compiler barriers.
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
inline long interlocked_read_acquire(long volatile* x) BOOST_NOEXCEPT
|
||||
{
|
||||
long const res=*x;
|
||||
BOOST_THREAD_DETAIL_COMPILER_BARRIER();
|
||||
return res;
|
||||
}
|
||||
inline void* interlocked_read_acquire(void* volatile* x) BOOST_NOEXCEPT
|
||||
{
|
||||
void* const res=*x;
|
||||
BOOST_THREAD_DETAIL_COMPILER_BARRIER();
|
||||
return res;
|
||||
}
|
||||
|
||||
inline void interlocked_write_release(long volatile* x,long value) BOOST_NOEXCEPT
|
||||
{
|
||||
BOOST_THREAD_DETAIL_COMPILER_BARRIER();
|
||||
*x=value;
|
||||
}
|
||||
inline void interlocked_write_release(void* volatile* x,void* value) BOOST_NOEXCEPT
|
||||
{
|
||||
BOOST_THREAD_DETAIL_COMPILER_BARRIER();
|
||||
*x=value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined(_MSC_VER) && _MSC_VER >= 1700 && (defined(_M_ARM) || defined(_M_ARM64))
|
||||
|
||||
#include <intrin.h>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
inline long interlocked_read_acquire(long volatile* x) BOOST_NOEXCEPT
|
||||
{
|
||||
long const res=__iso_volatile_load32((const volatile __int32*)x);
|
||||
BOOST_THREAD_DETAIL_COMPILER_BARRIER();
|
||||
__dmb(0xB); // _ARM_BARRIER_ISH, see armintr.h from MSVC 11 and later
|
||||
BOOST_THREAD_DETAIL_COMPILER_BARRIER();
|
||||
return res;
|
||||
}
|
||||
inline void* interlocked_read_acquire(void* volatile* x) BOOST_NOEXCEPT
|
||||
{
|
||||
void* const res=
|
||||
#if defined(_M_ARM64)
|
||||
(void*)__iso_volatile_load64((const volatile __int64*)x);
|
||||
#else
|
||||
(void*)__iso_volatile_load32((const volatile __int32*)x);
|
||||
#endif
|
||||
BOOST_THREAD_DETAIL_COMPILER_BARRIER();
|
||||
__dmb(0xB); // _ARM_BARRIER_ISH, see armintr.h from MSVC 11 and later
|
||||
BOOST_THREAD_DETAIL_COMPILER_BARRIER();
|
||||
return res;
|
||||
}
|
||||
|
||||
inline void interlocked_write_release(long volatile* x,long value) BOOST_NOEXCEPT
|
||||
{
|
||||
BOOST_THREAD_DETAIL_COMPILER_BARRIER();
|
||||
__dmb(0xB); // _ARM_BARRIER_ISH, see armintr.h from MSVC 11 and later
|
||||
BOOST_THREAD_DETAIL_COMPILER_BARRIER();
|
||||
__iso_volatile_store32((volatile __int32*)x, (__int32)value);
|
||||
}
|
||||
inline void interlocked_write_release(void* volatile* x,void* value) BOOST_NOEXCEPT
|
||||
{
|
||||
BOOST_THREAD_DETAIL_COMPILER_BARRIER();
|
||||
__dmb(0xB); // _ARM_BARRIER_ISH, see armintr.h from MSVC 11 and later
|
||||
BOOST_THREAD_DETAIL_COMPILER_BARRIER();
|
||||
#if defined(_M_ARM64)
|
||||
__iso_volatile_store64((volatile __int64*)x, (__int64)value);
|
||||
#else
|
||||
__iso_volatile_store32((volatile __int32*)x, (__int32)value);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined(__GNUC__) && (((__GNUC__ * 100 + __GNUC_MINOR__) >= 407) || (defined(__clang__) && (__clang_major__ * 100 + __clang_minor__) >= 302))
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
inline long interlocked_read_acquire(long volatile* x) BOOST_NOEXCEPT
|
||||
{
|
||||
return __atomic_load_n((long*)x, __ATOMIC_ACQUIRE);
|
||||
}
|
||||
inline void* interlocked_read_acquire(void* volatile* x) BOOST_NOEXCEPT
|
||||
{
|
||||
return __atomic_load_n((void**)x, __ATOMIC_ACQUIRE);
|
||||
}
|
||||
|
||||
inline void interlocked_write_release(long volatile* x,long value) BOOST_NOEXCEPT
|
||||
{
|
||||
__atomic_store_n((long*)x, value, __ATOMIC_RELEASE);
|
||||
}
|
||||
inline void interlocked_write_release(void* volatile* x,void* value) BOOST_NOEXCEPT
|
||||
{
|
||||
__atomic_store_n((void**)x, value, __ATOMIC_RELEASE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
inline long interlocked_read_acquire(long volatile* x) BOOST_NOEXCEPT
|
||||
{
|
||||
long res;
|
||||
__asm__ __volatile__ ("movl %1, %0" : "=r" (res) : "m" (*x) : "memory");
|
||||
return res;
|
||||
}
|
||||
inline void* interlocked_read_acquire(void* volatile* x) BOOST_NOEXCEPT
|
||||
{
|
||||
void* res;
|
||||
#if defined(__x86_64__)
|
||||
__asm__ __volatile__ ("movq %1, %0" : "=r" (res) : "m" (*x) : "memory");
|
||||
#else
|
||||
__asm__ __volatile__ ("movl %1, %0" : "=r" (res) : "m" (*x) : "memory");
|
||||
#endif
|
||||
return res;
|
||||
}
|
||||
|
||||
inline void interlocked_write_release(long volatile* x,long value) BOOST_NOEXCEPT
|
||||
{
|
||||
__asm__ __volatile__ ("movl %1, %0" : "=m" (*x) : "r" (value) : "memory");
|
||||
}
|
||||
inline void interlocked_write_release(void* volatile* x,void* value) BOOST_NOEXCEPT
|
||||
{
|
||||
#if defined(__x86_64__)
|
||||
__asm__ __volatile__ ("movq %1, %0" : "=m" (*x) : "r" (value) : "memory");
|
||||
#else
|
||||
__asm__ __volatile__ ("movl %1, %0" : "=m" (*x) : "r" (value) : "memory");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
inline long interlocked_read_acquire(long volatile* x) BOOST_NOEXCEPT
|
||||
{
|
||||
return BOOST_INTERLOCKED_COMPARE_EXCHANGE((long*)x,0,0);
|
||||
}
|
||||
inline void* interlocked_read_acquire(void* volatile* x) BOOST_NOEXCEPT
|
||||
{
|
||||
return BOOST_INTERLOCKED_COMPARE_EXCHANGE_POINTER((void**)x,0,0);
|
||||
}
|
||||
inline void interlocked_write_release(long volatile* x,long value) BOOST_NOEXCEPT
|
||||
{
|
||||
BOOST_INTERLOCKED_EXCHANGE((long*)x,value);
|
||||
}
|
||||
inline void interlocked_write_release(void* volatile* x,void* value) BOOST_NOEXCEPT
|
||||
{
|
||||
BOOST_INTERLOCKED_EXCHANGE_POINTER((void**)x,value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#include <boost/config/abi_suffix.hpp>
|
||||
|
||||
#endif
|
||||
@@ -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)(HINSTANCE, DWORD, LPVOID) = &ExtRawDllMain;
|
||||
|
||||
# elif defined(_USRDLL)
|
||||
|
||||
extern "C" BOOL WINAPI RawDllMain(HINSTANCE, DWORD dwReason, LPVOID);
|
||||
extern "C" __declspec(selectany) BOOL (WINAPI * const _pRawDllMainOrig)(HINSTANCE, DWORD, LPVOID) = &RawDllMain;
|
||||
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
72
install/boost_1_75_0/include/boost/thread/win32/mutex.hpp
Normal file
72
install/boost_1_75_0/include/boost/thread/win32/mutex.hpp
Normal file
@@ -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
|
||||
1087
install/boost_1_75_0/include/boost/thread/win32/once.hpp
Normal file
1087
install/boost_1_75_0/include/boost/thread/win32/once.hpp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
856
install/boost_1_75_0/include/boost/thread/win32/shared_mutex.hpp
Normal file
856
install/boost_1_75_0/include/boost/thread/win32/shared_mutex.hpp
Normal file
@@ -0,0 +1,856 @@
|
||||
#ifndef BOOST_THREAD_WIN32_SHARED_MUTEX_HPP
|
||||
#define BOOST_THREAD_WIN32_SHARED_MUTEX_HPP
|
||||
|
||||
// (C) Copyright 2006-8 Anthony Williams
|
||||
// (C) Copyright 2011-2012,2017-2018 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 <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/thread/detail/platform_time.hpp>
|
||||
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
class shared_mutex
|
||||
{
|
||||
private:
|
||||
struct state_data
|
||||
{
|
||||
unsigned long 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 std::memcmp(&lhs, &rhs, sizeof(lhs)) == 0;
|
||||
}
|
||||
};
|
||||
|
||||
static state_data interlocked_compare_exchange(state_data* target, state_data new_value, state_data comparand)
|
||||
{
|
||||
BOOST_STATIC_ASSERT(sizeof(state_data) == sizeof(long));
|
||||
long new_val, comp;
|
||||
std::memcpy(&new_val, &new_value, sizeof(new_value));
|
||||
std::memcpy(&comp, &comparand, sizeof(comparand));
|
||||
long const res=BOOST_INTERLOCKED_COMPARE_EXCHANGE(reinterpret_cast<long*>(target),
|
||||
new_val,
|
||||
comp);
|
||||
state_data result;
|
||||
std::memcpy(&result, &res, sizeof(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
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(winapi::ReleaseSemaphore(semaphores[exclusive_sem],1,0)!=0);
|
||||
}
|
||||
|
||||
if(old_state.shared_waiting || old_state.exclusive_waiting)
|
||||
{
|
||||
BOOST_VERIFY(winapi::ReleaseSemaphore(semaphores[unlock_sem],old_state.shared_waiting + (old_state.exclusive_waiting?1:0),0)!=0);
|
||||
}
|
||||
}
|
||||
void release_shared_waiters(state_data old_state)
|
||||
{
|
||||
if(old_state.shared_waiting || old_state.exclusive_waiting)
|
||||
{
|
||||
BOOST_VERIFY(winapi::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()
|
||||
{
|
||||
winapi::CloseHandle(upgrade_sem);
|
||||
winapi::CloseHandle(semaphores[unlock_sem]);
|
||||
winapi::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()
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
BOOST_VERIFY(winapi::WaitForSingleObjectEx(semaphores[unlock_sem],::boost::detail::win32::infinite,0)==0);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned long getMs(detail::platform_duration const& d)
|
||||
{
|
||||
return static_cast<unsigned long>(d.getMs());
|
||||
}
|
||||
|
||||
template <typename Duration>
|
||||
unsigned long getMs(Duration const& d)
|
||||
{
|
||||
return static_cast<unsigned long>(chrono::ceil<chrono::milliseconds>(d).count());
|
||||
}
|
||||
|
||||
template <typename Clock, typename Timepoint, typename Duration>
|
||||
bool do_lock_shared_until(Timepoint const& t, Duration const& max)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
// If the clock is the system clock, it may jump while this function
|
||||
// is waiting. To compensate for this and time out near the correct
|
||||
// time, we call WaitForSingleObjectEx() in a loop with a short
|
||||
// timeout and recheck the time remaining each time through the loop.
|
||||
unsigned long res=0;
|
||||
for(;;)
|
||||
{
|
||||
Duration d(t - Clock::now());
|
||||
if(d <= Duration::zero()) // timeout occurred
|
||||
{
|
||||
res=detail::win32::timeout;
|
||||
break;
|
||||
}
|
||||
if(max != Duration::zero())
|
||||
{
|
||||
d = (std::min)(d, max);
|
||||
}
|
||||
res=winapi::WaitForSingleObjectEx(semaphores[unlock_sem],getMs(d),0);
|
||||
if(res!=detail::win32::timeout) // semaphore released
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
public:
|
||||
|
||||
#if defined BOOST_THREAD_USES_DATETIME
|
||||
template<typename TimeDuration>
|
||||
bool timed_lock_shared(TimeDuration const & relative_time)
|
||||
{
|
||||
const detail::mono_platform_timepoint t(detail::mono_platform_clock::now() + detail::platform_duration(relative_time));
|
||||
// The reference clock is steady and so no need to poll periodically, thus 0 ms max (i.e. no max)
|
||||
return do_lock_shared_until<detail::mono_platform_clock>(t, detail::platform_duration::zero());
|
||||
}
|
||||
bool timed_lock_shared(boost::system_time const& wait_until)
|
||||
{
|
||||
const detail::real_platform_timepoint t(wait_until);
|
||||
return do_lock_shared_until<detail::real_platform_clock>(t, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
template <class Rep, class Period>
|
||||
bool try_lock_shared_for(const chrono::duration<Rep, Period>& rel_time)
|
||||
{
|
||||
const chrono::steady_clock::time_point t(chrono::steady_clock::now() + rel_time);
|
||||
typedef typename chrono::duration<Rep, Period> Duration;
|
||||
typedef typename common_type<Duration, typename chrono::steady_clock::duration>::type common_duration;
|
||||
// The reference clock is steady and so no need to poll periodically, thus 0 ms max (i.e. no max)
|
||||
return do_lock_shared_until<chrono::steady_clock>(t, common_duration::zero());
|
||||
}
|
||||
template <class Duration>
|
||||
bool try_lock_shared_until(const chrono::time_point<chrono::steady_clock, Duration>& t)
|
||||
{
|
||||
typedef typename common_type<Duration, typename chrono::steady_clock::duration>::type common_duration;
|
||||
// The reference clock is steady and so no need to poll periodically, thus 0 ms max (i.e. no max)
|
||||
return do_lock_shared_until<chrono::steady_clock>(t, common_duration::zero());
|
||||
}
|
||||
template <class Clock, class Duration>
|
||||
bool try_lock_shared_until(const chrono::time_point<Clock, Duration>& t)
|
||||
{
|
||||
typedef typename common_type<Duration, typename Clock::duration>::type common_duration;
|
||||
return do_lock_shared_until<Clock>(t, common_duration(chrono::milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS)));
|
||||
}
|
||||
#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(winapi::ReleaseSemaphore(upgrade_sem,1,0)!=0);
|
||||
}
|
||||
else
|
||||
{
|
||||
release_waiters(old_state);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
old_state=current_state;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void lock()
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
#ifndef UNDER_CE
|
||||
const bool wait_all = true;
|
||||
#else
|
||||
const bool wait_all = false;
|
||||
#endif
|
||||
BOOST_VERIFY(winapi::WaitForMultipleObjectsEx(2,semaphores,wait_all,::boost::detail::win32::infinite,0)<2);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename Clock, typename Timepoint, typename Duration>
|
||||
bool do_lock_until(Timepoint const& t, Duration const& max)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
// If the clock is the system clock, it may jump while this function
|
||||
// is waiting. To compensate for this and time out near the correct
|
||||
// time, we call WaitForMultipleObjectsEx() in a loop with a short
|
||||
// timeout and recheck the time remaining each time through the loop.
|
||||
unsigned long wait_res=0;
|
||||
for(;;)
|
||||
{
|
||||
Duration d(t - Clock::now());
|
||||
if(d <= Duration::zero()) // timeout occurred
|
||||
{
|
||||
wait_res=detail::win32::timeout;
|
||||
break;
|
||||
}
|
||||
if(max != Duration::zero())
|
||||
{
|
||||
d = (std::min)(d, max);
|
||||
}
|
||||
#ifndef UNDER_CE
|
||||
wait_res=winapi::WaitForMultipleObjectsEx(2,semaphores,true,getMs(d),0);
|
||||
#else
|
||||
wait_res=winapi::WaitForMultipleObjectsEx(2,semaphores,false,getMs(d),0);
|
||||
#endif
|
||||
//wait_res=winapi::WaitForMultipleObjectsEx(2,semaphores,wait_all,getMs(d), 0);
|
||||
|
||||
if(wait_res!=detail::win32::timeout) // semaphore released
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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(winapi::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);
|
||||
}
|
||||
}
|
||||
public:
|
||||
|
||||
#if defined BOOST_THREAD_USES_DATETIME
|
||||
bool timed_lock(boost::system_time const& wait_until)
|
||||
{
|
||||
const detail::real_platform_timepoint t(wait_until);
|
||||
return do_lock_until<detail::real_platform_clock>(t, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
|
||||
}
|
||||
template<typename TimeDuration>
|
||||
bool timed_lock(TimeDuration const & relative_time)
|
||||
{
|
||||
const detail::mono_platform_timepoint t(detail::mono_platform_clock::now() + detail::platform_duration(relative_time));
|
||||
// The reference clock is steady and so no need to poll periodically, thus 0 ms max (i.e. no max)
|
||||
return do_lock_until<detail::mono_platform_clock>(t, detail::platform_duration::zero());
|
||||
}
|
||||
#endif
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
template <class Rep, class Period>
|
||||
bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)
|
||||
{
|
||||
const chrono::steady_clock::time_point t(chrono::steady_clock::now() + rel_time);
|
||||
typedef typename chrono::duration<Rep, Period> Duration;
|
||||
typedef typename common_type<Duration, typename chrono::steady_clock::duration>::type common_duration;
|
||||
// The reference clock is steady and so no need to poll periodically, thus 0 ms max (i.e. no max)
|
||||
return do_lock_until<chrono::steady_clock>(t, common_duration::zero());
|
||||
}
|
||||
template <class Duration>
|
||||
bool try_lock_until(const chrono::time_point<chrono::steady_clock, Duration>& t)
|
||||
{
|
||||
typedef typename common_type<Duration, typename chrono::steady_clock::duration>::type common_duration;
|
||||
// The reference clock is steady and so no need to poll periodically, thus 0 ms max (i.e. no max)
|
||||
return do_lock_until<chrono::steady_clock>(t, common_duration::zero());
|
||||
}
|
||||
template <class Clock, class Duration>
|
||||
bool try_lock_until(const chrono::time_point<Clock, Duration>& t)
|
||||
{
|
||||
typedef typename common_type<Duration, typename Clock::duration>::type common_duration;
|
||||
return do_lock_until<Clock>(t, common_duration(chrono::milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS)));
|
||||
}
|
||||
#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(winapi::WaitForSingleObjectEx(semaphores[unlock_sem],winapi::infinite,0)==0);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
new_state.shared_waiting=0;
|
||||
if(last_reader)
|
||||
{
|
||||
if(new_state.exclusive_waiting)
|
||||
{
|
||||
--new_state.exclusive_waiting;
|
||||
new_state.exclusive_waiting_blocked=false;
|
||||
}
|
||||
}
|
||||
|
||||
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
|
||||
if(current_state==old_state)
|
||||
{
|
||||
if(last_reader)
|
||||
{
|
||||
release_waiters(old_state);
|
||||
}
|
||||
else {
|
||||
release_shared_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(winapi::WaitForSingleObjectEx(upgrade_sem,detail::win32::infinite,0)==0);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
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
|
||||
329
install/boost_1_75_0/include/boost/thread/win32/thread_data.hpp
Normal file
329
install/boost_1_75_0/include/boost/thread/win32/thread_data.hpp
Normal file
@@ -0,0 +1,329 @@
|
||||
#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/thread/detail/platform_time.hpp>
|
||||
|
||||
#include <boost/predef/platform.h>
|
||||
|
||||
#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
|
||||
{
|
||||
typedef void(*cleanup_func_t)(void*);
|
||||
typedef void(*cleanup_caller_t)(cleanup_func_t, void*);
|
||||
|
||||
cleanup_caller_t caller;
|
||||
cleanup_func_t func;
|
||||
void* value;
|
||||
|
||||
tss_data_node(cleanup_caller_t caller_,cleanup_func_t func_,void* value_):
|
||||
caller(caller_),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;
|
||||
|
||||
// Win32 threading APIs are not available in store apps so
|
||||
// use abstraction on top of Windows::System::Threading.
|
||||
#if BOOST_PLAT_WINDOWS_RUNTIME
|
||||
detail::win32::scoped_winrt_thread thread_handle;
|
||||
#else
|
||||
detail::win32::handle_manager thread_handle;
|
||||
#endif
|
||||
|
||||
boost::detail::thread_exit_callback_node* thread_exit_callbacks;
|
||||
unsigned id;
|
||||
std::map<void const*,boost::detail::tss_data_node> tss_data;
|
||||
typedef std::vector<std::pair<condition_variable*, mutex*>
|
||||
//, hidden_allocator<std::pair<condition_variable*, mutex*> >
|
||||
> notify_list_t;
|
||||
notify_list_t notify;
|
||||
|
||||
//#ifndef BOOST_NO_EXCEPTIONS
|
||||
typedef std::vector<shared_ptr<shared_state_base> > async_states_t;
|
||||
async_states_t async_states_;
|
||||
//#endif
|
||||
//#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(),
|
||||
thread_exit_callbacks(0),
|
||||
id(0),
|
||||
tss_data(),
|
||||
notify()
|
||||
//#ifndef BOOST_NO_EXCEPTIONS
|
||||
, async_states_()
|
||||
//#endif
|
||||
//#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();
|
||||
|
||||
#if !defined(BOOST_EMBTC)
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
friend void intrusive_ptr_add_ref(thread_data_base * p);
|
||||
friend void intrusive_ptr_release(thread_data_base * p);
|
||||
|
||||
#endif
|
||||
|
||||
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
void interrupt()
|
||||
{
|
||||
BOOST_VERIFY(winapi::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));
|
||||
}
|
||||
|
||||
//#ifndef BOOST_NO_EXCEPTIONS
|
||||
void make_ready_at_thread_exit(shared_ptr<shared_state_base> as)
|
||||
{
|
||||
async_states_.push_back(as);
|
||||
}
|
||||
//#endif
|
||||
};
|
||||
|
||||
#if defined(BOOST_EMBTC)
|
||||
|
||||
inline void intrusive_ptr_add_ref(thread_data_base * p)
|
||||
{
|
||||
BOOST_INTERLOCKED_INCREMENT(&p->count);
|
||||
}
|
||||
|
||||
inline void intrusive_ptr_release(thread_data_base * p)
|
||||
{
|
||||
if(!BOOST_INTERLOCKED_DECREMENT(&p->count))
|
||||
{
|
||||
detail::heap_delete(p);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
BOOST_THREAD_DECL thread_data_base* get_current_thread_data();
|
||||
|
||||
typedef boost::intrusive_ptr<detail::thread_data_base> thread_data_ptr;
|
||||
}
|
||||
|
||||
namespace this_thread
|
||||
{
|
||||
void BOOST_THREAD_DECL yield() BOOST_NOEXCEPT;
|
||||
|
||||
bool BOOST_THREAD_DECL interruptible_wait(detail::win32::handle handle_to_wait_for, detail::internal_platform_timepoint const &timeout);
|
||||
|
||||
#if defined BOOST_THREAD_USES_DATETIME
|
||||
template<typename TimeDuration>
|
||||
BOOST_SYMBOL_VISIBLE void sleep(TimeDuration const& rel_time)
|
||||
{
|
||||
interruptible_wait(detail::win32::invalid_handle_value, detail::internal_platform_clock::now() + detail::platform_duration(rel_time));
|
||||
}
|
||||
|
||||
inline BOOST_SYMBOL_VISIBLE void sleep(system_time const& abs_time)
|
||||
{
|
||||
const detail::real_platform_timepoint ts(abs_time);
|
||||
detail::platform_duration d(ts - detail::real_platform_clock::now());
|
||||
while (d > detail::platform_duration::zero())
|
||||
{
|
||||
d = (std::min)(d, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
|
||||
interruptible_wait(detail::win32::invalid_handle_value, detail::internal_platform_clock::now() + d);
|
||||
d = ts - detail::real_platform_clock::now();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
template <class Rep, class Period>
|
||||
void sleep_for(const chrono::duration<Rep, Period>& d)
|
||||
{
|
||||
interruptible_wait(detail::win32::invalid_handle_value, detail::internal_platform_clock::now() + detail::platform_duration(d));
|
||||
}
|
||||
|
||||
template <class Duration>
|
||||
void sleep_until(const chrono::time_point<chrono::steady_clock, Duration>& t)
|
||||
{
|
||||
sleep_for(t - chrono::steady_clock::now());
|
||||
}
|
||||
|
||||
template <class Clock, class Duration>
|
||||
void sleep_until(const chrono::time_point<Clock, Duration>& t)
|
||||
{
|
||||
typedef typename common_type<Duration, typename Clock::duration>::type common_duration;
|
||||
common_duration d(t - Clock::now());
|
||||
while (d > common_duration::zero())
|
||||
{
|
||||
d = (std::min)(d, common_duration(chrono::milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS)));
|
||||
sleep_for(d);
|
||||
d = t - Clock::now();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace no_interruption_point
|
||||
{
|
||||
bool BOOST_THREAD_DECL non_interruptible_wait(detail::win32::handle handle_to_wait_for, detail::internal_platform_timepoint const &timeout);
|
||||
|
||||
#if defined BOOST_THREAD_USES_DATETIME
|
||||
template<typename TimeDuration>
|
||||
BOOST_SYMBOL_VISIBLE void sleep(TimeDuration const& rel_time)
|
||||
{
|
||||
non_interruptible_wait(detail::win32::invalid_handle_value, detail::internal_platform_clock::now() + detail::platform_duration(rel_time));
|
||||
}
|
||||
|
||||
inline BOOST_SYMBOL_VISIBLE void sleep(system_time const& abs_time)
|
||||
{
|
||||
const detail::real_platform_timepoint ts(abs_time);
|
||||
detail::platform_duration d(ts - detail::real_platform_clock::now());
|
||||
while (d > detail::platform_duration::zero())
|
||||
{
|
||||
d = (std::min)(d, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
|
||||
non_interruptible_wait(detail::win32::invalid_handle_value, detail::internal_platform_clock::now() + d);
|
||||
d = ts - detail::real_platform_clock::now();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
template <class Rep, class Period>
|
||||
void sleep_for(const chrono::duration<Rep, Period>& d)
|
||||
{
|
||||
non_interruptible_wait(detail::win32::invalid_handle_value, detail::internal_platform_clock::now() + detail::platform_duration(d));
|
||||
}
|
||||
|
||||
template <class Duration>
|
||||
void sleep_until(const chrono::time_point<chrono::steady_clock, Duration>& t)
|
||||
{
|
||||
sleep_for(t - chrono::steady_clock::now());
|
||||
}
|
||||
|
||||
template <class Clock, class Duration>
|
||||
void sleep_until(const chrono::time_point<Clock, Duration>& t)
|
||||
{
|
||||
typedef typename common_type<Duration, typename Clock::duration>::type common_duration;
|
||||
common_duration d(t - Clock::now());
|
||||
while (d > common_duration::zero())
|
||||
{
|
||||
d = (std::min)(d, common_duration(chrono::milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS)));
|
||||
sleep_for(d);
|
||||
d = t - Clock::now();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#include <boost/config/abi_suffix.hpp>
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,469 @@
|
||||
// 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>
|
||||
|
||||
#include <boost/winapi/heap_memory.hpp>
|
||||
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
inline void* allocate_raw_heap_memory(unsigned size)
|
||||
{
|
||||
void* const heap_memory=winapi::HeapAlloc(winapi::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(winapi::HeapFree(winapi::GetProcessHeap(),0,heap_memory)!=0);
|
||||
}
|
||||
#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) && ! defined (BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
template<typename T,typename... Args>
|
||||
inline T* heap_new(Args&&... args)
|
||||
{
|
||||
void* const heap_memory=allocate_raw_heap_memory(sizeof(T));
|
||||
BOOST_TRY
|
||||
{
|
||||
T* const data=new (heap_memory) T(static_cast<Args&&>(args)...);
|
||||
return data;
|
||||
}
|
||||
BOOST_CATCH(...)
|
||||
{
|
||||
free_raw_heap_memory(heap_memory);
|
||||
BOOST_RETHROW
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
}
|
||||
#else
|
||||
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,typename A2,typename A3,typename A4,typename A5>
|
||||
inline T* heap_new_impl(A1 a1,A2 a2,A3 a3,A4 a4,A5 a5)
|
||||
{
|
||||
void* const heap_memory=allocate_raw_heap_memory(sizeof(T));
|
||||
BOOST_TRY
|
||||
{
|
||||
T* const data=new (heap_memory) T(a1,a2,a3,a4,a5);
|
||||
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,typename A5,typename A6>
|
||||
inline T* heap_new_impl(A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6)
|
||||
{
|
||||
void* const heap_memory=allocate_raw_heap_memory(sizeof(T));
|
||||
BOOST_TRY
|
||||
{
|
||||
T* const data=new (heap_memory) T(a1,a2,a3,a4,a5,a6);
|
||||
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,typename A5,typename A6,typename A7>
|
||||
inline T* heap_new_impl(A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6,A7 a7)
|
||||
{
|
||||
void* const heap_memory=allocate_raw_heap_memory(sizeof(T));
|
||||
BOOST_TRY
|
||||
{
|
||||
T* const data=new (heap_memory) T(a1,a2,a3,a4,a5,a6,a7);
|
||||
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,typename A5,typename A6,typename A7,typename A8>
|
||||
inline T* heap_new_impl(A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6,A7 a7,A8 a8)
|
||||
{
|
||||
void* const heap_memory=allocate_raw_heap_memory(sizeof(T));
|
||||
BOOST_TRY
|
||||
{
|
||||
T* const data=new (heap_memory) T(a1,a2,a3,a4,a5,a6,a7,a8);
|
||||
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,typename A5,typename A6,typename A7,typename A8,typename A9>
|
||||
inline T* heap_new_impl(A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6,A7 a7,A8 a8,A9 a9)
|
||||
{
|
||||
void* const heap_memory=allocate_raw_heap_memory(sizeof(T));
|
||||
BOOST_TRY
|
||||
{
|
||||
T* const data=new (heap_memory) T(a1,a2,a3,a4,a5,a6,a7,a8,a9);
|
||||
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
|
||||
#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
|
||||
@@ -0,0 +1,426 @@
|
||||
#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/predef/platform.h>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/thread/exceptions.hpp>
|
||||
#include <boost/detail/interlocked.hpp>
|
||||
|
||||
#include <boost/winapi/config.hpp>
|
||||
#include <boost/winapi/basic_types.hpp>
|
||||
#include <boost/winapi/semaphore.hpp>
|
||||
#include <boost/winapi/system.hpp>
|
||||
#include <boost/winapi/event.hpp>
|
||||
#include <boost/winapi/thread.hpp>
|
||||
#include <boost/winapi/get_current_thread.hpp>
|
||||
#include <boost/winapi/get_current_thread_id.hpp>
|
||||
#include <boost/winapi/get_current_process.hpp>
|
||||
#include <boost/winapi/get_current_process_id.hpp>
|
||||
#include <boost/winapi/wait.hpp>
|
||||
#include <boost/winapi/handles.hpp>
|
||||
#include <boost/winapi/access_rights.hpp>
|
||||
|
||||
//#include <boost/winapi/synchronization.hpp>
|
||||
#include <boost/thread/win32/interlocked_read.hpp>
|
||||
#include <algorithm>
|
||||
|
||||
#if BOOST_PLAT_WINDOWS_RUNTIME
|
||||
#include <thread>
|
||||
#endif
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
namespace win32
|
||||
{
|
||||
typedef ::boost::winapi::HANDLE_ handle;
|
||||
typedef ::boost::winapi::SYSTEM_INFO_ system_info;
|
||||
typedef ::boost::winapi::ULONGLONG_ ticks_type;
|
||||
unsigned const infinite=::boost::winapi::INFINITE_;
|
||||
unsigned const timeout=::boost::winapi::WAIT_TIMEOUT_;
|
||||
handle const invalid_handle_value=::boost::winapi::INVALID_HANDLE_VALUE_;
|
||||
unsigned const event_modify_state=::boost::winapi::EVENT_MODIFY_STATE_;
|
||||
unsigned const synchronize=::boost::winapi::SYNCHRONIZE_;
|
||||
unsigned const wait_abandoned=::boost::winapi::WAIT_ABANDONED_;
|
||||
unsigned const create_event_initial_set = 0x00000002;
|
||||
unsigned const create_event_manual_reset = 0x00000001;
|
||||
unsigned const event_all_access = ::boost::winapi::EVENT_ALL_ACCESS_;
|
||||
unsigned const semaphore_all_access = boost::winapi::SEMAPHORE_ALL_ACCESS_;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
namespace win32
|
||||
{
|
||||
namespace detail { typedef ticks_type (BOOST_WINAPI_WINAPI_CC *gettickcount64_t)(); }
|
||||
extern BOOST_THREAD_DECL boost::detail::win32::detail::gettickcount64_t gettickcount64;
|
||||
|
||||
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_event(
|
||||
#if !defined(BOOST_NO_ANSI_APIS)
|
||||
const char *mutex_name,
|
||||
#else
|
||||
const wchar_t *mutex_name,
|
||||
#endif
|
||||
event_type type,
|
||||
initial_event_state state)
|
||||
{
|
||||
#if !defined(BOOST_NO_ANSI_APIS)
|
||||
handle const res = ::boost::winapi::CreateEventA(0, type, state, mutex_name);
|
||||
#elif BOOST_USE_WINAPI_VERSION < BOOST_WINAPI_VERSION_VISTA
|
||||
handle const res = ::boost::winapi::CreateEventW(0, type, state, mutex_name);
|
||||
#else
|
||||
handle const res = ::boost::winapi::CreateEventExW(
|
||||
0,
|
||||
mutex_name,
|
||||
(type ? create_event_manual_reset : 0) | (state ? create_event_initial_set : 0),
|
||||
event_all_access);
|
||||
#endif
|
||||
return res;
|
||||
}
|
||||
|
||||
inline handle create_anonymous_event(event_type type,initial_event_state state)
|
||||
{
|
||||
handle const res = create_event(0, type, state);
|
||||
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=::boost::winapi::CreateSemaphoreA(0,initial_count,max_count,0);
|
||||
#else
|
||||
#if BOOST_USE_WINAPI_VERSION < BOOST_WINAPI_VERSION_VISTA
|
||||
handle const res=::boost::winapi::CreateSemaphoreEx(0,initial_count,max_count,0,0);
|
||||
#else
|
||||
handle const res=::boost::winapi::CreateSemaphoreExW(0,initial_count,max_count,0,0,semaphore_all_access);
|
||||
#endif
|
||||
#endif
|
||||
return res;
|
||||
}
|
||||
|
||||
inline handle create_anonymous_semaphore(long initial_count,long max_count)
|
||||
{
|
||||
handle const res=create_anonymous_semaphore_nothrow(initial_count,max_count);
|
||||
if(!res)
|
||||
{
|
||||
boost::throw_exception(thread_resource_error());
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
inline handle duplicate_handle(handle source)
|
||||
{
|
||||
handle const current_process=::boost::winapi::GetCurrentProcess();
|
||||
long const same_access_flag=2;
|
||||
handle new_handle=0;
|
||||
bool const success=::boost::winapi::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(::boost::winapi::ReleaseSemaphore(semaphore,count,0)!=0);
|
||||
}
|
||||
|
||||
inline void get_system_info(system_info *info)
|
||||
{
|
||||
#if BOOST_PLAT_WINDOWS_RUNTIME
|
||||
::boost::winapi::GetNativeSystemInfo(info);
|
||||
#else
|
||||
::boost::winapi::GetSystemInfo(info);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void sleep(unsigned long milliseconds)
|
||||
{
|
||||
if(milliseconds == 0)
|
||||
{
|
||||
#if BOOST_PLAT_WINDOWS_RUNTIME
|
||||
std::this_thread::yield();
|
||||
#else
|
||||
::boost::winapi::Sleep(0);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#if BOOST_PLAT_WINDOWS_RUNTIME
|
||||
::boost::winapi::WaitForSingleObjectEx(::boost::winapi::GetCurrentThread(), milliseconds, 0);
|
||||
#else
|
||||
::boost::winapi::Sleep(milliseconds);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#if BOOST_PLAT_WINDOWS_RUNTIME
|
||||
class BOOST_THREAD_DECL scoped_winrt_thread
|
||||
{
|
||||
public:
|
||||
scoped_winrt_thread() : m_completionHandle(invalid_handle_value)
|
||||
{}
|
||||
|
||||
~scoped_winrt_thread()
|
||||
{
|
||||
if (m_completionHandle != ::boost::detail::win32::invalid_handle_value)
|
||||
{
|
||||
::boost::winapi::CloseHandle(m_completionHandle);
|
||||
}
|
||||
}
|
||||
|
||||
typedef unsigned(__stdcall * thread_func)(void *);
|
||||
bool start(thread_func address, void *parameter, unsigned int *thrdId);
|
||||
|
||||
handle waitable_handle() const
|
||||
{
|
||||
BOOST_ASSERT(m_completionHandle != ::boost::detail::win32::invalid_handle_value);
|
||||
return m_completionHandle;
|
||||
}
|
||||
|
||||
private:
|
||||
handle m_completionHandle;
|
||||
};
|
||||
#endif
|
||||
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(::boost::winapi::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
|
||||
Reference in New Issue
Block a user