updated boost on windows

This commit is contained in:
Bassem Girgis
2019-08-13 21:48:48 -05:00
parent 7d77d485fd
commit b40a3bee82
5162 changed files with 473027 additions and 116452 deletions

View File

@@ -4,7 +4,7 @@
// basic_recursive_mutex.hpp
//
// (C) Copyright 2006-8 Anthony Williams
// (C) Copyright 2011-2012 Vicente J. Botet Escriba
// (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
@@ -44,13 +44,13 @@ namespace boost
bool try_lock() BOOST_NOEXCEPT
{
long const current_thread_id=win32::GetCurrentThreadId();
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=win32::GetCurrentThreadId();
long const current_thread_id=boost::winapi::GetCurrentThreadId();
if(!try_recursive_lock(current_thread_id))
{
mutex.lock();
@@ -61,29 +61,30 @@ namespace boost
#if defined BOOST_THREAD_USES_DATETIME
bool timed_lock(::boost::system_time const& target)
{
long const current_thread_id=win32::GetCurrentThreadId();
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& timeout)
bool timed_lock(Duration const& target)
{
return timed_lock(get_system_time()+timeout);
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=win32::GetCurrentThreadId();
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=win32::GetCurrentThreadId();
}
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()
{
@@ -127,6 +128,17 @@ namespace boost
}
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)

View File

@@ -22,6 +22,8 @@
#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
@@ -55,11 +57,11 @@ namespace boost
#endif
if(old_event)
{
win32::CloseHandle(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);
@@ -76,21 +78,21 @@ namespace boost
if(old_count&lock_flag_value)
{
bool lock_acquired=false;
void* const sem=get_event();
do
{
unsigned const retval(win32::WaitForSingleObjectEx(sem, ::boost::detail::win32::infinite,0));
BOOST_VERIFY(0 == retval || ::boost::detail::win32::wait_abandoned == retval);
// BOOST_VERIFY(win32::WaitForSingleObject(
// sem,::boost::detail::win32::infinite)==0);
clear_waiting_and_try_lock(old_count);
lock_acquired=!(old_count&lock_flag_value);
if(winapi::WaitForSingleObjectEx(sem,::boost::detail::win32::infinite,0)==0)
{
clear_waiting_and_try_lock(old_count);
}
}
while(!lock_acquired);
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(;;)
@@ -102,12 +104,19 @@ namespace boost
{
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;
@@ -118,126 +127,135 @@ namespace boost
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());
}
#if defined BOOST_THREAD_USES_DATETIME
bool timed_lock(::boost::system_time const& wait_until)
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)
{
bool lock_acquired=false;
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
{
if(win32::WaitForSingleObjectEx(sem,::boost::detail::get_milliseconds_until(wait_until),0)!=0)
Duration d(t - Clock::now());
if(d <= Duration::zero()) // timeout occurred
{
BOOST_INTERLOCKED_DECREMENT(&active_count);
return false;
}
clear_waiting_and_try_lock(old_count);
lock_acquired=!(old_count&lock_flag_value);
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(!lock_acquired);
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)
{
return timed_lock(get_system_time()+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(system_time(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)
{
return try_lock_until(chrono::steady_clock::now() + 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)
{
using namespace chrono;
system_clock::time_point s_now = system_clock::now();
typename Clock::time_point c_now = Clock::now();
return try_lock_until(s_now + ceil<system_clock::duration>(t - c_now));
}
template <class Duration>
bool try_lock_until(const chrono::time_point<chrono::system_clock, Duration>& t)
{
using namespace chrono;
typedef time_point<chrono::system_clock, chrono::system_clock::duration> sys_tmpt;
return try_lock_until(sys_tmpt(chrono::ceil<chrono::system_clock::duration>(t.time_since_epoch())));
}
bool try_lock_until(const chrono::time_point<chrono::system_clock, chrono::system_clock::duration>& tp)
{
if(try_lock())
{
return true;
}
long old_count=active_count;
mark_waiting_and_try_lock(old_count);
if(old_count&lock_flag_value)
{
bool lock_acquired=false;
void* const sem=get_event();
do
{
chrono::time_point<chrono::system_clock, chrono::system_clock::duration> now = chrono::system_clock::now();
if (tp<=now) {
BOOST_INTERLOCKED_DECREMENT(&active_count);
return false;
}
chrono::milliseconds rel_time= chrono::ceil<chrono::milliseconds>(tp-now);
if(win32::WaitForSingleObjectEx(sem,static_cast<unsigned long>(rel_time.count()),0)!=0)
{
BOOST_INTERLOCKED_DECREMENT(&active_count);
return false;
}
clear_waiting_and_try_lock(old_count);
lock_acquired=!(old_count&lock_flag_value);
}
while(!lock_acquired);
}
return true;
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()
{
long const offset=lock_flag_value;
// 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(!(old_count&event_set_flag_value) && (old_count>offset))
// 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))
{
win32::SetEvent(get_event());
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);
@@ -256,7 +274,7 @@ namespace boost
#endif
if(old_event!=0)
{
win32::CloseHandle(new_event);
winapi::CloseHandle(new_event);
return old_event;
}
else

View File

@@ -18,6 +18,7 @@
#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>
@@ -76,7 +77,7 @@ namespace boost
void release(unsigned count_to_release)
{
notified=true;
detail::win32::ReleaseSemaphore(semaphore,count_to_release,0);
winapi::ReleaseSemaphore(semaphore,count_to_release,0);
}
void release_waiters()
@@ -89,14 +90,14 @@ namespace boost
return notified;
}
bool wait(timeout abs_time)
bool interruptible_wait(detail::internal_platform_timepoint const &timeout)
{
return this_thread::interruptible_wait(semaphore,abs_time);
return this_thread::interruptible_wait(semaphore, timeout);
}
bool woken()
{
unsigned long const woken_result=detail::win32::WaitForSingleObjectEx(wake_sem,0,0);
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;
}
@@ -135,39 +136,45 @@ namespace boost
void wake_waiters(long count_to_wake)
{
detail::interlocked_write_release(&total_count,total_count-count_to_wake);
detail::win32::ReleaseSemaphore(wake_sem,count_to_wake,0);
winapi::ReleaseSemaphore(wake_sem,count_to_wake,0);
}
template<typename lock_type>
struct relocker
{
BOOST_THREAD_NO_COPYABLE(relocker)
lock_type& lock;
bool unlocked;
lock_type& _lock;
bool _unlocked;
relocker(lock_type& lock_):
lock(lock_),unlocked(false)
_lock(lock_), _unlocked(false)
{}
void unlock()
{
lock.unlock();
unlocked=true;
if ( ! _unlocked )
{
_lock.unlock();
_unlocked=true;
}
}
~relocker()
void lock()
{
if(unlocked)
{
lock.lock();
}
if ( _unlocked )
{
_lock.lock();
_unlocked=false;
}
}
~relocker() BOOST_NOEXCEPT_IF(false)
{
lock();
}
};
entry_ptr get_wait_entry()
{
boost::lock_guard<boost::mutex> internal_lock(internal_mutex);
boost::lock_guard<boost::mutex> lk(internal_mutex);
if(!wake_sem)
{
wake_sem=detail::win32::create_anonymous_semaphore(0,LONG_MAX);
@@ -190,18 +197,32 @@ namespace boost
struct entry_manager
{
entry_ptr const entry;
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
~entry_manager()
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->()
@@ -210,41 +231,7 @@ namespace boost
}
};
protected:
template<typename lock_type>
bool do_wait(lock_type& lock,timeout abs_time)
{
relocker<lock_type> locker(lock);
entry_manager entry(get_wait_entry(), internal_mutex);
locker.unlock();
bool woken=false;
while(!woken)
{
if(!entry->wait(abs_time))
{
return false;
}
woken=entry->woken();
}
return woken;
}
template<typename lock_type,typename predicate_type>
bool do_wait(lock_type& m,timeout const& abs_time,predicate_type pred)
{
while (!pred())
{
if(!do_wait(m, abs_time))
return pred();
}
return true;
}
basic_condition_variable(const basic_condition_variable& other);
basic_condition_variable& operator=(const basic_condition_variable& other);
@@ -256,6 +243,38 @@ namespace boost
~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))
@@ -309,75 +328,115 @@ namespace boost
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(m,detail::timeout::sentinel());
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);
while (!pred())
{
wait(m);
}
}
#if defined BOOST_THREAD_USES_DATETIME
bool timed_wait(unique_lock<mutex>& m,boost::system_time const& abs_time)
{
return do_wait(m,abs_time);
// 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 do_wait(m,system_time(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); // or do_wait(m,detail::timeout::sentinel());
return true;
}
if (wait_duration.is_special())
{
return true;
}
return do_wait(m,wait_duration.total_milliseconds());
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)
{
return do_wait(m,abs_time,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 do_wait(m,system_time(abs_time),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); // or do_wait(m,detail::timeout::sentinel());
}
return true;
while (!pred())
{
wait(m);
}
return true;
}
if (wait_duration.is_special())
{
return pred();
return pred();
}
return do_wait(m,wait_duration.total_milliseconds(),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
@@ -385,14 +444,18 @@ namespace boost
unique_lock<mutex>& lock,
const chrono::time_point<Clock, Duration>& t)
{
using namespace chrono;
chrono::time_point<Clock, Duration> now = Clock::now();
if (t<=now) {
return cv_status::timeout;
}
do_wait(lock, ceil<milliseconds>(t-now).count());
return Clock::now() < t ? cv_status::no_timeout :
cv_status::timeout;
// 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>
@@ -401,15 +464,22 @@ namespace boost
unique_lock<mutex>& lock,
const chrono::duration<Rep, Period>& d)
{
using namespace chrono;
if (d<=chrono::duration<Rep, Period>::zero()) {
return cv_status::timeout;
}
return wait_until(lock, chrono::steady_clock::now() + d);
}
steady_clock::time_point c_now = steady_clock::now();
do_wait(lock, ceil<milliseconds>(d).count());
return steady_clock::now() - c_now < d ? cv_status::no_timeout :
cv_status::timeout;
template <class 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>
@@ -419,13 +489,20 @@ namespace boost
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())
{
if (wait_until(lock, t) == cv_status::timeout)
return 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 true;
return pred();
}
template <class Rep, class Period, class Predicate>
bool
wait_for(
@@ -446,59 +523,122 @@ namespace boost
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(m,detail::timeout::sentinel());
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);
while (!pred())
{
wait(m);
}
}
#if defined BOOST_THREAD_USES_DATETIME
template<typename lock_type>
bool timed_wait(lock_type& m,boost::system_time const& abs_time)
{
return do_wait(m,abs_time);
// 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 do_wait(m,system_time(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)
{
return do_wait(m,wait_duration.total_milliseconds());
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)
{
return do_wait(m,abs_time,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 do_wait(m,system_time(abs_time),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)
{
return do_wait(m,wait_duration.total_milliseconds(),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
@@ -506,14 +646,18 @@ namespace boost
lock_type& lock,
const chrono::time_point<Clock, Duration>& t)
{
using namespace chrono;
chrono::time_point<Clock, Duration> now = Clock::now();
if (t<=now) {
return cv_status::timeout;
}
do_wait(lock, ceil<milliseconds>(t-now).count());
return Clock::now() < t ? cv_status::no_timeout :
cv_status::timeout;
// 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>
@@ -522,14 +666,22 @@ namespace boost
lock_type& lock,
const chrono::duration<Rep, Period>& d)
{
using namespace chrono;
if (d<=chrono::duration<Rep, Period>::zero()) {
return cv_status::timeout;
}
steady_clock::time_point c_now = steady_clock::now();
do_wait(lock, ceil<milliseconds>(d).count());
return steady_clock::now() - c_now < d ? cv_status::no_timeout :
cv_status::timeout;
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>
@@ -539,12 +691,18 @@ namespace boost
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())
{
if (wait_until(lock, t) == cv_status::timeout)
return 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 true;
return pred();
}
template <class lock_type, class Rep, class Period, class Predicate>

View File

@@ -87,9 +87,9 @@ namespace boost
{
void* const res=
#if defined(_M_ARM64)
__iso_volatile_load64((const volatile __int64*)x);
(void*)__iso_volatile_load64((const volatile __int64*)x);
#else
__iso_volatile_load32((const volatile __int32*)x);
(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

View File

@@ -27,12 +27,12 @@ inline BOOL WINAPI ExtRawDllMain(HINSTANCE, DWORD dwReason, LPVOID)
return TRUE; // ok
}
extern "C" __declspec(selectany) BOOL (WINAPI * const _pRawDllMainOrig)(HANDLE, DWORD, LPVOID) = &ExtRawDllMain;
extern "C" __declspec(selectany) BOOL (WINAPI * const _pRawDllMainOrig)(HINSTANCE, DWORD, LPVOID) = &ExtRawDllMain;
# elif defined(_USRDLL)
extern "C" BOOL WINAPI RawDllMain(HANDLE, DWORD dwReason, LPVOID);
extern "C" __declspec(selectany) BOOL (WINAPI * const _pRawDllMainOrig)(HANDLE, DWORD, LPVOID) = &RawDllMain;
extern "C" BOOL WINAPI RawDllMain(HINSTANCE, DWORD dwReason, LPVOID);
extern "C" __declspec(selectany) BOOL (WINAPI * const _pRawDllMainOrig)(HINSTANCE, DWORD, LPVOID) = &RawDllMain;
# endif
#endif

View File

@@ -124,7 +124,7 @@ namespace boost
std::memcpy(mutex_name,fixed_mutex_name,sizeof(fixed_mutex_name));
detail::int_to_string(reinterpret_cast<std::ptrdiff_t>(flag_address),
mutex_name + once_mutex_name_fixed_length);
detail::int_to_string(win32::GetCurrentProcessId(),
detail::int_to_string(winapi::GetCurrentProcessId(),
mutex_name + once_mutex_name_fixed_length + sizeof(void*)*2);
}
@@ -136,9 +136,9 @@ namespace boost
}
#ifdef BOOST_NO_ANSI_APIS
return ::boost::detail::win32::OpenEventW(
return ::boost::winapi::OpenEventW(
#else
return ::boost::detail::win32::OpenEventA(
return ::boost::winapi::OpenEventA(
#endif
::boost::detail::win32::synchronize |
::boost::detail::win32::event_modify_state,
@@ -186,7 +186,7 @@ namespace boost
}
if(ctx.event_handle)
{
::boost::detail::win32::ResetEvent(ctx.event_handle);
::boost::winapi::ResetEvent(ctx.event_handle);
}
return true;
}
@@ -207,7 +207,7 @@ namespace boost
}
if(ctx.event_handle)
{
::boost::detail::win32::SetEvent(ctx.event_handle);
::boost::winapi::SetEvent(ctx.event_handle);
}
}
inline void rollback_once_region(once_flag& flag, once_context& ctx) BOOST_NOEXCEPT
@@ -219,13 +219,13 @@ namespace boost
}
if(ctx.event_handle)
{
::boost::detail::win32::SetEvent(ctx.event_handle);
::boost::winapi::SetEvent(ctx.event_handle);
}
}
}
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
//#if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR)
//#if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNCTION_PTR)
inline void call_once(once_flag& flag, void (*f)())
{
// Try for a quick win: if the procedure has already been called
@@ -264,7 +264,7 @@ namespace boost
continue;
}
}
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
BOOST_VERIFY(!::boost::winapi::WaitForSingleObjectEx(
ctx.event_handle,::boost::detail::win32::infinite, 0));
}
}
@@ -308,7 +308,7 @@ namespace boost
continue;
}
}
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
BOOST_VERIFY(!::boost::winapi::WaitForSingleObjectEx(
ctx.event_handle,::boost::detail::win32::infinite,0));
}
}
@@ -355,7 +355,7 @@ namespace boost
continue;
}
}
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
BOOST_VERIFY(!::boost::winapi::WaitForSingleObjectEx(
ctx.event_handle,::boost::detail::win32::infinite,0));
}
}
@@ -400,7 +400,7 @@ namespace boost
continue;
}
}
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
BOOST_VERIFY(!::boost::winapi::WaitForSingleObjectEx(
ctx.event_handle,::boost::detail::win32::infinite,0));
}
}
@@ -443,7 +443,7 @@ namespace boost
continue;
}
}
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
BOOST_VERIFY(!::boost::winapi::WaitForSingleObjectEx(
ctx.event_handle,::boost::detail::win32::infinite,0));
}
}
@@ -486,7 +486,7 @@ namespace boost
continue;
}
}
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
BOOST_VERIFY(!::boost::winapi::WaitForSingleObjectEx(
ctx.event_handle,::boost::detail::win32::infinite,0));
}
}
@@ -529,7 +529,7 @@ namespace boost
continue;
}
}
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
BOOST_VERIFY(!::boost::winapi::WaitForSingleObjectEx(
ctx.event_handle,::boost::detail::win32::infinite,0));
}
}
@@ -574,7 +574,7 @@ namespace boost
continue;
}
}
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
BOOST_VERIFY(!::boost::winapi::WaitForSingleObjectEx(
ctx.event_handle,::boost::detail::win32::infinite,0));
}
}
@@ -617,7 +617,7 @@ namespace boost
continue;
}
}
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
BOOST_VERIFY(!::boost::winapi::WaitForSingleObjectEx(
ctx.event_handle,::boost::detail::win32::infinite,0));
}
}
@@ -660,7 +660,7 @@ namespace boost
continue;
}
}
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
BOOST_VERIFY(!::boost::winapi::WaitForSingleObjectEx(
ctx.event_handle,::boost::detail::win32::infinite,0));
}
}
@@ -703,13 +703,13 @@ namespace boost
continue;
}
}
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
BOOST_VERIFY(!::boost::winapi::WaitForSingleObjectEx(
ctx.event_handle,::boost::detail::win32::infinite,0));
}
}
#endif
#if 1
#if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR)
#if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNCTION_PTR)
inline void call_once(once_flag& flag, void (*f)())
{
// Try for a quick win: if the procedure has already been called
@@ -748,7 +748,7 @@ namespace boost
continue;
}
}
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
BOOST_VERIFY(!::boost::winapi::WaitForSingleObjectEx(
ctx.event_handle,::boost::detail::win32::infinite,0));
}
}
@@ -793,7 +793,7 @@ namespace boost
continue;
}
}
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
BOOST_VERIFY(!::boost::winapi::WaitForSingleObjectEx(
ctx.event_handle,::boost::detail::win32::infinite,0));
}
}
@@ -839,7 +839,7 @@ namespace boost
continue;
}
}
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
BOOST_VERIFY(!::boost::winapi::WaitForSingleObjectEx(
ctx.event_handle,::boost::detail::win32::infinite,0));
}
}
@@ -886,7 +886,7 @@ namespace boost
continue;
}
}
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
BOOST_VERIFY(!::boost::winapi::WaitForSingleObjectEx(
ctx.event_handle,::boost::detail::win32::infinite,0));
}
}
@@ -930,7 +930,7 @@ namespace boost
continue;
}
}
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
BOOST_VERIFY(!::boost::winapi::WaitForSingleObjectEx(
ctx.event_handle,::boost::detail::win32::infinite,0));
}
}
@@ -977,7 +977,7 @@ namespace boost
continue;
}
}
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
BOOST_VERIFY(!::boost::winapi::WaitForSingleObjectEx(
ctx.event_handle,::boost::detail::win32::infinite,0));
}
}
@@ -1024,7 +1024,7 @@ namespace boost
continue;
}
}
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
BOOST_VERIFY(!::boost::winapi::WaitForSingleObjectEx(
ctx.event_handle,::boost::detail::win32::infinite,0));
}
}
@@ -1073,7 +1073,7 @@ namespace boost
continue;
}
}
BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx(
BOOST_VERIFY(!::boost::winapi::WaitForSingleObjectEx(
ctx.event_handle,::boost::detail::win32::infinite,0));
}
}

View File

@@ -2,12 +2,13 @@
#define BOOST_THREAD_WIN32_SHARED_MUTEX_HPP
// (C) Copyright 2006-8 Anthony Williams
// (C) Copyright 2011-2012 Vicente J. Botet Escriba
// (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>
@@ -19,6 +20,7 @@
#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>
@@ -29,7 +31,7 @@ namespace boost
private:
struct state_data
{
unsigned shared_count:11,
unsigned long shared_count:11,
shared_waiting:11,
exclusive:1,
upgrade:1,
@@ -38,19 +40,22 @@ namespace boost
friend bool operator==(state_data const& lhs,state_data const& rhs)
{
return *reinterpret_cast<unsigned const*>(&lhs)==*reinterpret_cast<unsigned const*>(&rhs);
return std::memcmp(&lhs, &rhs, sizeof(lhs)) == 0;
}
};
template<typename T>
T interlocked_compare_exchange(T* target,T new_value,T comparand)
static state_data interlocked_compare_exchange(state_data* target, state_data new_value, state_data comparand)
{
BOOST_STATIC_ASSERT(sizeof(T)==sizeof(long));
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),
*reinterpret_cast<long*>(&new_value),
*reinterpret_cast<long*>(&comparand));
return *reinterpret_cast<T const*>(&res);
new_val,
comp);
state_data result;
std::memcpy(&result, &res, sizeof(result));
return result;
}
enum
@@ -67,19 +72,19 @@ namespace boost
{
if(old_state.exclusive_waiting)
{
BOOST_VERIFY(detail::win32::ReleaseSemaphore(semaphores[exclusive_sem],1,0)!=0);
BOOST_VERIFY(winapi::ReleaseSemaphore(semaphores[exclusive_sem],1,0)!=0);
}
if(old_state.shared_waiting || old_state.exclusive_waiting)
{
BOOST_VERIFY(detail::win32::ReleaseSemaphore(semaphores[unlock_sem],old_state.shared_waiting + (old_state.exclusive_waiting?1:0),0)!=0);
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(detail::win32::ReleaseSemaphore(semaphores[unlock_sem],old_state.shared_waiting + (old_state.exclusive_waiting?1:0),0)!=0);
BOOST_VERIFY(winapi::ReleaseSemaphore(semaphores[unlock_sem],old_state.shared_waiting + (old_state.exclusive_waiting?1:0),0)!=0);
}
}
@@ -107,9 +112,9 @@ namespace boost
~shared_mutex()
{
detail::win32::CloseHandle(upgrade_sem);
detail::win32::CloseHandle(semaphores[unlock_sem]);
detail::win32::CloseHandle(semaphores[exclusive_sem]);
winapi::CloseHandle(upgrade_sem);
winapi::CloseHandle(semaphores[unlock_sem]);
winapi::CloseHandle(semaphores[exclusive_sem]);
}
bool try_lock_shared()
@@ -139,21 +144,60 @@ namespace boost
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());
}
}
#if defined BOOST_THREAD_USES_DATETIME
BOOST_VERIFY(timed_lock_shared(::boost::detail::get_system_time_sentinel()));
#else
BOOST_VERIFY(try_lock_shared_until(chrono::steady_clock::now()));
#endif
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);
}
}
#if defined BOOST_THREAD_USES_DATETIME
template<typename TimeDuration>
bool timed_lock_shared(TimeDuration const & relative_time)
private:
unsigned long getMs(detail::platform_duration const& d)
{
return timed_lock_shared(get_system_time()+relative_time);
return static_cast<unsigned long>(d.getMs());
}
bool timed_lock_shared(boost::system_time const& wait_until)
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(;;)
{
@@ -191,7 +235,30 @@ namespace boost
return true;
}
unsigned long const res=detail::win32::WaitForSingleObjectEx(semaphores[unlock_sem],::boost::detail::get_milliseconds_until(wait_until), 0);
// 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(;;)
@@ -231,114 +298,45 @@ namespace boost
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)
{
return try_lock_shared_until(chrono::steady_clock::now() + 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)
{
using namespace chrono;
system_clock::time_point s_now = system_clock::now();
typename Clock::time_point c_now = Clock::now();
return try_lock_shared_until(s_now + ceil<system_clock::duration>(t - c_now));
}
template <class Duration>
bool try_lock_shared_until(const chrono::time_point<chrono::system_clock, Duration>& t)
{
using namespace chrono;
typedef time_point<chrono::system_clock, chrono::system_clock::duration> sys_tmpt;
return try_lock_shared_until(sys_tmpt(chrono::ceil<chrono::system_clock::duration>(t.time_since_epoch())));
}
bool try_lock_shared_until(const chrono::time_point<chrono::system_clock, chrono::system_clock::duration>& tp)
{
for(;;)
{
state_data old_state=state;
for(;;)
{
state_data new_state=old_state;
if(new_state.exclusive || new_state.exclusive_waiting_blocked)
{
++new_state.shared_waiting;
if(!new_state.shared_waiting)
{
boost::throw_exception(boost::lock_error());
}
}
else
{
++new_state.shared_count;
if(!new_state.shared_count)
{
boost::throw_exception(boost::lock_error());
}
}
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
if(current_state==old_state)
{
break;
}
old_state=current_state;
}
if(!(old_state.exclusive| old_state.exclusive_waiting_blocked))
{
return true;
}
chrono::system_clock::time_point n = chrono::system_clock::now();
unsigned long res;
if (tp>n) {
chrono::milliseconds rel_time= chrono::ceil<chrono::milliseconds>(tp-n);
res=detail::win32::WaitForSingleObjectEx(semaphores[unlock_sem],
static_cast<unsigned long>(rel_time.count()), 0);
} else {
res=detail::win32::timeout;
}
if(res==detail::win32::timeout)
{
for(;;)
{
state_data new_state=old_state;
if(new_state.exclusive || new_state.exclusive_waiting_blocked)
{
if(new_state.shared_waiting)
{
--new_state.shared_waiting;
}
}
else
{
++new_state.shared_count;
if(!new_state.shared_count)
{
return false;
}
}
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
if(current_state==old_state)
{
break;
}
old_state=current_state;
}
if(!(old_state.exclusive| old_state.exclusive_waiting_blocked))
{
return true;
}
return false;
}
BOOST_ASSERT(res==0);
}
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
@@ -375,7 +373,7 @@ namespace boost
{
if(old_state.upgrade)
{
BOOST_VERIFY(detail::win32::ReleaseSemaphore(upgrade_sem,1,0)!=0);
BOOST_VERIFY(winapi::ReleaseSemaphore(upgrade_sem,1,0)!=0);
}
else
{
@@ -388,24 +386,6 @@ namespace boost
}
}
void lock()
{
#if defined BOOST_THREAD_USES_DATETIME
BOOST_VERIFY(timed_lock(::boost::detail::get_system_time_sentinel()));
#else
BOOST_VERIFY(try_lock_until(chrono::steady_clock::now()));
#endif
}
#if defined BOOST_THREAD_USES_DATETIME
template<typename TimeDuration>
bool timed_lock(TimeDuration const & relative_time)
{
return timed_lock(get_system_time()+relative_time);
}
#endif
bool try_lock()
{
state_data old_state=state;
@@ -431,14 +411,58 @@ namespace boost
return true;
}
#if defined BOOST_THREAD_USES_DATETIME
bool timed_lock(boost::system_time const& wait_until)
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;
@@ -469,12 +493,37 @@ namespace boost
{
return true;
}
#ifndef UNDER_CE
const bool wait_all = true;
#else
const bool wait_all = false;
#endif
unsigned long const wait_res=detail::win32::WaitForMultipleObjectsEx(2,semaphores,wait_all,::boost::detail::get_milliseconds_until(wait_until), 0);
// 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(;;)
@@ -500,7 +549,7 @@ namespace boost
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
if (must_notify)
{
BOOST_VERIFY(detail::win32::ReleaseSemaphore(semaphores[unlock_sem],1,0)!=0);
BOOST_VERIFY(winapi::ReleaseSemaphore(semaphores[unlock_sem],1,0)!=0);
}
if(current_state==old_state)
@@ -515,123 +564,48 @@ namespace boost
}
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)
{
return try_lock_until(chrono::steady_clock::now() + 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)
{
using namespace chrono;
system_clock::time_point s_now = system_clock::now();
typename Clock::time_point c_now = Clock::now();
return try_lock_until(s_now + ceil<system_clock::duration>(t - c_now));
}
template <class Duration>
bool try_lock_until(const chrono::time_point<chrono::system_clock, Duration>& t)
{
using namespace chrono;
typedef time_point<chrono::system_clock, chrono::system_clock::duration> sys_tmpt;
return try_lock_until(sys_tmpt(chrono::ceil<chrono::system_clock::duration>(t.time_since_epoch())));
}
bool try_lock_until(const chrono::time_point<chrono::system_clock, chrono::system_clock::duration>& tp)
{
for(;;)
{
state_data old_state=state;
for(;;)
{
state_data new_state=old_state;
if(new_state.shared_count || new_state.exclusive)
{
++new_state.exclusive_waiting;
if(!new_state.exclusive_waiting)
{
boost::throw_exception(boost::lock_error());
}
new_state.exclusive_waiting_blocked=true;
}
else
{
new_state.exclusive=true;
}
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
if(current_state==old_state)
{
break;
}
old_state=current_state;
}
if(!old_state.shared_count && !old_state.exclusive)
{
return true;
}
#ifndef UNDER_CE
const bool wait_all = true;
#else
const bool wait_all = false;
#endif
chrono::system_clock::time_point n = chrono::system_clock::now();
unsigned long wait_res;
if (tp>n) {
chrono::milliseconds rel_time= chrono::ceil<chrono::milliseconds>(tp-chrono::system_clock::now());
wait_res=detail::win32::WaitForMultipleObjectsEx(2,semaphores,wait_all,
static_cast<unsigned long>(rel_time.count()), 0);
} else {
wait_res=detail::win32::timeout;
}
if(wait_res==detail::win32::timeout)
{
for(;;)
{
bool must_notify = false;
state_data new_state=old_state;
if(new_state.shared_count || new_state.exclusive)
{
if(new_state.exclusive_waiting)
{
if(!--new_state.exclusive_waiting)
{
new_state.exclusive_waiting_blocked=false;
must_notify = true;
}
}
}
else
{
new_state.exclusive=true;
}
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
if (must_notify)
{
BOOST_VERIFY(detail::win32::ReleaseSemaphore(semaphores[unlock_sem],1,0)!=0);
}
if(current_state==old_state)
{
break;
}
old_state=current_state;
}
if(!old_state.shared_count && !old_state.exclusive)
{
return true;
}
return false;
}
BOOST_ASSERT(wait_res<2);
}
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
@@ -698,7 +672,7 @@ namespace boost
return;
}
BOOST_VERIFY(!detail::win32::WaitForSingleObjectEx(semaphores[unlock_sem],detail::win32::infinite, 0));
BOOST_VERIFY(winapi::WaitForSingleObjectEx(semaphores[unlock_sem],winapi::infinite,0)==0);
}
}
@@ -790,7 +764,7 @@ namespace boost
{
if(!last_reader)
{
BOOST_VERIFY(!detail::win32::WaitForSingleObjectEx(upgrade_sem,detail::win32::infinite, 0));
BOOST_VERIFY(winapi::WaitForSingleObjectEx(upgrade_sem,detail::win32::infinite,0)==0);
}
break;
}
@@ -823,27 +797,6 @@ namespace boost
}
release_waiters(old_state);
}
// bool try_unlock_upgrade_and_lock()
// {
// return false;
// }
//#ifdef BOOST_THREAD_USES_CHRONO
// template <class Rep, class Period>
// bool
// try_unlock_upgrade_and_lock_for(
// const chrono::duration<Rep, Period>& rel_time)
// {
// return try_unlock_upgrade_and_lock_until(
// chrono::steady_clock::now() + rel_time);
// }
// template <class Clock, class Duration>
// bool
// try_unlock_upgrade_and_lock_until(
// const chrono::time_point<Clock, Duration>& abs_time)
// {
// return false;
// }
//#endif
void unlock_and_lock_shared()
{

View File

@@ -10,6 +10,7 @@
#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>
@@ -79,12 +80,15 @@ namespace boost
struct thread_exit_callback_node;
struct tss_data_node
{
boost::shared_ptr<boost::detail::tss_cleanup_function> func;
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(boost::shared_ptr<boost::detail::tss_cleanup_function> func_,
void* value_):
func(func_),value(value_)
tss_data_node(cleanup_caller_t caller_,cleanup_func_t func_,void* value_):
caller(caller_),func(func_),value(value_)
{}
};
@@ -112,8 +116,10 @@ namespace boost
> 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
@@ -128,8 +134,10 @@ namespace boost
thread_exit_callbacks(0),
id(0),
tss_data(),
notify(),
async_states_()
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)
@@ -153,7 +161,7 @@ namespace boost
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
void interrupt()
{
BOOST_VERIFY(detail::win32::SetEvent(interruption_handle)!=0);
BOOST_VERIFY(winapi::SetEvent(interruption_handle)!=0);
}
#endif
typedef detail::win32::handle native_handle_type;
@@ -165,155 +173,121 @@ namespace boost
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
};
BOOST_THREAD_DECL thread_data_base* get_current_thread_data();
typedef boost::intrusive_ptr<detail::thread_data_base> thread_data_ptr;
struct BOOST_SYMBOL_VISIBLE timeout
{
win32::ticks_type start;
uintmax_t milliseconds;
bool relative;
boost::system_time abs_time;
static unsigned long const max_non_infinite_wait=0xfffffffe;
timeout(uintmax_t milliseconds_):
start(win32::GetTickCount64_()()),
milliseconds(milliseconds_),
relative(true)
//,
// abs_time(boost::get_system_time())
{}
timeout(boost::system_time const& abs_time_):
start(win32::GetTickCount64_()()),
milliseconds(0),
relative(false),
abs_time(abs_time_)
{}
struct BOOST_SYMBOL_VISIBLE remaining_time
{
bool more;
unsigned long milliseconds;
remaining_time(uintmax_t remaining):
more(remaining>max_non_infinite_wait),
milliseconds(more?max_non_infinite_wait:(unsigned long)remaining)
{}
};
remaining_time remaining_milliseconds() const
{
if(is_sentinel())
{
return remaining_time(win32::infinite);
}
else if(relative)
{
win32::ticks_type const now=win32::GetTickCount64_()();
win32::ticks_type const elapsed=now-start;
return remaining_time((elapsed<milliseconds)?(milliseconds-elapsed):0);
}
else
{
system_time const now=get_system_time();
if(abs_time<=now)
{
return remaining_time(0);
}
return remaining_time((abs_time-now).total_milliseconds()+1);
}
}
bool is_sentinel() const
{
return milliseconds==~uintmax_t(0);
}
static timeout sentinel()
{
return timeout(sentinel_type());
}
private:
struct sentinel_type
{};
explicit timeout(sentinel_type):
start(0),milliseconds(~uintmax_t(0)),relative(true)
{}
};
inline uintmax_t pin_to_zero(intmax_t value)
{
return (value<0)?0u:(uintmax_t)value;
}
}
namespace this_thread
{
void BOOST_THREAD_DECL yield() BOOST_NOEXCEPT;
bool BOOST_THREAD_DECL interruptible_wait(detail::win32::handle handle_to_wait_for,detail::timeout target_time);
inline void interruptible_wait(uintmax_t milliseconds)
{
interruptible_wait(detail::win32::invalid_handle_value,milliseconds);
}
inline BOOST_SYMBOL_VISIBLE void interruptible_wait(system_time const& abs_time)
{
interruptible_wait(detail::win32::invalid_handle_value,abs_time);
}
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>
inline BOOST_SYMBOL_VISIBLE void sleep(TimeDuration const& rel_time)
BOOST_SYMBOL_VISIBLE void sleep(TimeDuration const& rel_time)
{
interruptible_wait(detail::pin_to_zero(rel_time.total_milliseconds()));
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)
{
interruptible_wait(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();
}
}
// #11322 sleep_for() nanoseconds overload will always return too early on windows
//#ifdef BOOST_THREAD_USES_CHRONO
// inline void BOOST_SYMBOL_VISIBLE sleep_for(const chrono::nanoseconds& ns)
// {
// interruptible_wait(chrono::duration_cast<chrono::milliseconds>(ns).count());
// }
//#endif
#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::timeout target_time);
inline void non_interruptible_wait(uintmax_t milliseconds)
{
non_interruptible_wait(detail::win32::invalid_handle_value,milliseconds);
}
inline BOOST_SYMBOL_VISIBLE void non_interruptible_wait(system_time const& abs_time)
{
non_interruptible_wait(detail::win32::invalid_handle_value,abs_time);
}
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>
inline BOOST_SYMBOL_VISIBLE void sleep(TimeDuration const& rel_time)
BOOST_SYMBOL_VISIBLE void sleep(TimeDuration const& rel_time)
{
non_interruptible_wait(detail::pin_to_zero(rel_time.total_milliseconds()));
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)
{
non_interruptible_wait(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();
}
}
// #11322 sleep_for() nanoseconds overload will always return too early on windows
//#ifdef BOOST_THREAD_USES_CHRONO
// inline void BOOST_SYMBOL_VISIBLE sleep_for(const chrono::nanoseconds& ns)
// {
// non_interruptible_wait(chrono::duration_cast<chrono::milliseconds>(ns).count());
// }
//#endif
#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
}
}

View File

@@ -12,45 +12,7 @@
#include <boost/throw_exception.hpp>
#include <boost/core/no_exceptions_support.hpp>
#if defined( BOOST_USE_WINDOWS_H )
# include <windows.h>
namespace boost
{
namespace detail
{
namespace win32
{
using ::GetProcessHeap;
using ::HeapAlloc;
using ::HeapFree;
}
}
}
#else
# ifdef HeapAlloc
# undef HeapAlloc
# endif
namespace boost
{
namespace detail
{
namespace win32
{
extern "C"
{
__declspec(dllimport) handle __stdcall GetProcessHeap();
__declspec(dllimport) void* __stdcall HeapAlloc(handle,unsigned long,ulong_ptr);
__declspec(dllimport) int __stdcall HeapFree(handle,unsigned long,void*);
}
}
}
}
#endif
#include <boost/winapi/heap_memory.hpp>
#include <boost/config/abi_prefix.hpp>
@@ -60,7 +22,7 @@ namespace boost
{
inline void* allocate_raw_heap_memory(unsigned size)
{
void* const heap_memory=detail::win32::HeapAlloc(detail::win32::GetProcessHeap(),0,size);
void* const heap_memory=winapi::HeapAlloc(winapi::GetProcessHeap(),0,size);
if(!heap_memory)
{
boost::throw_exception(std::bad_alloc());
@@ -70,9 +32,26 @@ namespace boost
inline void free_raw_heap_memory(void* heap_memory)
{
BOOST_VERIFY(detail::win32::HeapFree(detail::win32::GetProcessHeap(),0,heap_memory)!=0);
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()
{
@@ -225,6 +204,86 @@ namespace boost
}
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>
@@ -384,6 +443,7 @@ namespace boost
return heap_new_impl<T,A1&,A2&,A3&,A4&>(a1,a2,a3,a4);
}
#endif
#endif
template<typename T>
inline void heap_delete(T* data)

View File

@@ -16,8 +16,22 @@
#include <boost/assert.hpp>
#include <boost/thread/exceptions.hpp>
#include <boost/detail/interlocked.hpp>
#include <boost/detail/winapi/config.hpp>
//#include <boost/detail/winapi/synchronization.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>
@@ -25,200 +39,28 @@
#include <thread>
#endif
#if defined( BOOST_USE_WINDOWS_H )
# include <windows.h>
namespace boost
{
namespace detail
{
namespace win32
{
typedef HANDLE handle;
typedef SYSTEM_INFO system_info;
typedef unsigned __int64 ticks_type;
typedef FARPROC farproc_t;
unsigned const infinite=INFINITE;
unsigned const timeout=WAIT_TIMEOUT;
handle const invalid_handle_value=INVALID_HANDLE_VALUE;
unsigned const event_modify_state=EVENT_MODIFY_STATE;
unsigned const synchronize=SYNCHRONIZE;
unsigned const wait_abandoned=WAIT_ABANDONED;
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 = EVENT_ALL_ACCESS;
unsigned const semaphore_all_access = SEMAPHORE_ALL_ACCESS;
# ifdef BOOST_NO_ANSI_APIS
# if BOOST_USE_WINAPI_VERSION < BOOST_WINAPI_VERSION_VISTA
using ::CreateMutexW;
using ::CreateEventW;
using ::CreateSemaphoreW;
# else
using ::CreateMutexExW;
using ::CreateEventExW;
using ::CreateSemaphoreExW;
# endif
using ::OpenEventW;
using ::GetModuleHandleW;
# else
using ::CreateMutexA;
using ::CreateEventA;
using ::OpenEventA;
using ::CreateSemaphoreA;
using ::GetModuleHandleA;
# endif
#if BOOST_PLAT_WINDOWS_RUNTIME
using ::GetNativeSystemInfo;
using ::GetTickCount64;
#else
using ::GetSystemInfo;
using ::GetTickCount;
#endif
using ::CloseHandle;
using ::ReleaseMutex;
using ::ReleaseSemaphore;
using ::SetEvent;
using ::ResetEvent;
using ::WaitForMultipleObjectsEx;
using ::WaitForSingleObjectEx;
using ::GetCurrentProcessId;
using ::GetCurrentThreadId;
using ::GetCurrentThread;
using ::GetCurrentProcess;
using ::DuplicateHandle;
#if !BOOST_PLAT_WINDOWS_RUNTIME
using ::SleepEx;
using ::Sleep;
using ::QueueUserAPC;
using ::GetProcAddress;
#endif
unsigned const event_all_access = ::boost::winapi::EVENT_ALL_ACCESS_;
unsigned const semaphore_all_access = boost::winapi::SEMAPHORE_ALL_ACCESS_;
}
}
}
#elif defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ )
# ifdef UNDER_CE
# ifndef WINAPI
# ifndef _WIN32_WCE_EMULATION
# define WINAPI __cdecl // Note this doesn't match the desktop definition
# else
# define WINAPI __stdcall
# endif
# endif
# ifdef __cplusplus
extern "C" {
# endif
typedef int BOOL;
typedef unsigned long DWORD;
typedef void* HANDLE;
# include <kfuncs.h>
# ifdef __cplusplus
}
# endif
# endif
# ifdef __cplusplus
extern "C" {
# endif
struct _SYSTEM_INFO;
# ifdef __cplusplus
}
#endif
namespace boost
{
namespace detail
{
namespace win32
{
# ifdef _WIN64
typedef unsigned __int64 ulong_ptr;
# else
typedef unsigned long ulong_ptr;
# endif
typedef void* handle;
typedef _SYSTEM_INFO system_info;
typedef unsigned __int64 ticks_type;
typedef int (__stdcall *farproc_t)();
unsigned const infinite=~0U;
unsigned const timeout=258U;
handle const invalid_handle_value=(handle)(-1);
unsigned const event_modify_state=2;
unsigned const synchronize=0x100000u;
unsigned const wait_abandoned=0x00000080u;
unsigned const create_event_initial_set = 0x00000002;
unsigned const create_event_manual_reset = 0x00000001;
unsigned const event_all_access = 0x1F0003;
unsigned const semaphore_all_access = 0x1F0003;
extern "C"
{
struct _SECURITY_ATTRIBUTES;
# ifdef BOOST_NO_ANSI_APIS
# if BOOST_USE_WINAPI_VERSION < BOOST_WINAPI_VERSION_VISTA
__declspec(dllimport) void* __stdcall CreateMutexW(_SECURITY_ATTRIBUTES*,int,wchar_t const*);
__declspec(dllimport) void* __stdcall CreateSemaphoreW(_SECURITY_ATTRIBUTES*,long,long,wchar_t const*);
__declspec(dllimport) void* __stdcall CreateEventW(_SECURITY_ATTRIBUTES*,int,int,wchar_t const*);
# else
__declspec(dllimport) void* __stdcall CreateMutexExW(_SECURITY_ATTRIBUTES*,wchar_t const*,unsigned long,unsigned long);
__declspec(dllimport) void* __stdcall CreateEventExW(_SECURITY_ATTRIBUTES*,wchar_t const*,unsigned long,unsigned long);
__declspec(dllimport) void* __stdcall CreateSemaphoreExW(_SECURITY_ATTRIBUTES*,long,long,wchar_t const*,unsigned long,unsigned long);
# endif
__declspec(dllimport) void* __stdcall OpenEventW(unsigned long,int,wchar_t const*);
__declspec(dllimport) void* __stdcall GetModuleHandleW(wchar_t const*);
# else
__declspec(dllimport) void* __stdcall CreateMutexA(_SECURITY_ATTRIBUTES*,int,char const*);
__declspec(dllimport) void* __stdcall CreateSemaphoreA(_SECURITY_ATTRIBUTES*,long,long,char const*);
__declspec(dllimport) void* __stdcall CreateEventA(_SECURITY_ATTRIBUTES*,int,int,char const*);
__declspec(dllimport) void* __stdcall OpenEventA(unsigned long,int,char const*);
__declspec(dllimport) void* __stdcall GetModuleHandleA(char const*);
# endif
#if BOOST_PLAT_WINDOWS_RUNTIME
__declspec(dllimport) void __stdcall GetNativeSystemInfo(_SYSTEM_INFO*);
__declspec(dllimport) ticks_type __stdcall GetTickCount64();
#else
__declspec(dllimport) void __stdcall GetSystemInfo(_SYSTEM_INFO*);
__declspec(dllimport) unsigned long __stdcall GetTickCount();
#endif
__declspec(dllimport) int __stdcall CloseHandle(void*);
__declspec(dllimport) int __stdcall ReleaseMutex(void*);
__declspec(dllimport) unsigned long __stdcall WaitForSingleObjectEx(void*,unsigned long,int);
__declspec(dllimport) unsigned long __stdcall WaitForMultipleObjectsEx(unsigned long nCount,void* const * lpHandles,int bWaitAll,unsigned long dwMilliseconds,int bAlertable);
__declspec(dllimport) int __stdcall ReleaseSemaphore(void*,long,long*);
__declspec(dllimport) int __stdcall DuplicateHandle(void*,void*,void*,void**,unsigned long,int,unsigned long);
#if !BOOST_PLAT_WINDOWS_RUNTIME
__declspec(dllimport) unsigned long __stdcall SleepEx(unsigned long,int);
__declspec(dllimport) void __stdcall Sleep(unsigned long);
typedef void (__stdcall *queue_user_apc_callback_function)(ulong_ptr);
__declspec(dllimport) unsigned long __stdcall QueueUserAPC(queue_user_apc_callback_function,void*,ulong_ptr);
__declspec(dllimport) farproc_t __stdcall GetProcAddress(void *, const char *);
#endif
# ifndef UNDER_CE
__declspec(dllimport) unsigned long __stdcall GetCurrentProcessId();
__declspec(dllimport) unsigned long __stdcall GetCurrentThreadId();
__declspec(dllimport) void* __stdcall GetCurrentThread();
__declspec(dllimport) void* __stdcall GetCurrentProcess();
__declspec(dllimport) int __stdcall SetEvent(void*);
__declspec(dllimport) int __stdcall ResetEvent(void*);
# else
using ::GetCurrentProcessId;
using ::GetCurrentThreadId;
using ::GetCurrentThread;
using ::GetCurrentProcess;
using ::SetEvent;
using ::ResetEvent;
# endif
}
}
}
}
#else
# error "Win32 functions not available"
#endif
#include <boost/config/abi_prefix.hpp>
@@ -228,96 +70,8 @@ namespace boost
{
namespace win32
{
namespace detail { typedef ticks_type (__stdcall *gettickcount64_t)(); }
#if !BOOST_PLAT_WINDOWS_RUNTIME
extern "C"
{
#ifdef _MSC_VER
long _InterlockedCompareExchange(long volatile *, long, long);
#pragma intrinsic(_InterlockedCompareExchange)
#elif defined(__MINGW64_VERSION_MAJOR)
long _InterlockedCompareExchange(long volatile *, long, long);
#else
// Mingw doesn't provide intrinsics
#define _InterlockedCompareExchange InterlockedCompareExchange
#endif
}
// Borrowed from https://stackoverflow.com/questions/8211820/userland-interrupt-timer-access-such-as-via-kequeryinterrupttime-or-similar
inline ticks_type __stdcall GetTickCount64emulation()
{
static long count = -1l;
unsigned long previous_count, current_tick32, previous_count_zone, current_tick32_zone;
ticks_type current_tick64;
previous_count = (unsigned long) boost::detail::interlocked_read_acquire(&count);
current_tick32 = GetTickCount();
if(previous_count == (unsigned long)-1l)
{
// count has never been written
unsigned long initial_count;
initial_count = current_tick32 >> 28;
previous_count = (unsigned long) _InterlockedCompareExchange(&count, (long)initial_count, -1l);
current_tick64 = initial_count;
current_tick64 <<= 28;
current_tick64 += current_tick32 & 0x0FFFFFFF;
return current_tick64;
}
previous_count_zone = previous_count & 15;
current_tick32_zone = current_tick32 >> 28;
if(current_tick32_zone == previous_count_zone)
{
// The top four bits of the 32-bit tick count haven't changed since count was last written.
current_tick64 = previous_count;
current_tick64 <<= 28;
current_tick64 += current_tick32 & 0x0FFFFFFF;
return current_tick64;
}
if(current_tick32_zone == previous_count_zone + 1 || (current_tick32_zone == 0 && previous_count_zone == 15))
{
// The top four bits of the 32-bit tick count have been incremented since count was last written.
unsigned long new_count = previous_count + 1;
_InterlockedCompareExchange(&count, (long)new_count, (long)previous_count);
current_tick64 = new_count;
current_tick64 <<= 28;
current_tick64 += current_tick32 & 0x0FFFFFFF;
return current_tick64;
}
// Oops, we weren't called often enough, we're stuck
return 0xFFFFFFFF;
}
#else
#endif
inline detail::gettickcount64_t GetTickCount64_()
{
static detail::gettickcount64_t gettickcount64impl;
if(gettickcount64impl)
return gettickcount64impl;
// GetTickCount and GetModuleHandle are not allowed in the Windows Runtime,
// and kernel32 isn't used in Windows Phone.
#if BOOST_PLAT_WINDOWS_RUNTIME
gettickcount64impl = &GetTickCount64;
#else
farproc_t addr=GetProcAddress(
#if !defined(BOOST_NO_ANSI_APIS)
GetModuleHandleA("KERNEL32.DLL"),
#else
GetModuleHandleW(L"KERNEL32.DLL"),
#endif
"GetTickCount64");
if(addr)
gettickcount64impl=(detail::gettickcount64_t) addr;
else
gettickcount64impl=&GetTickCount64emulation;
#endif
return gettickcount64impl;
}
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
{
@@ -341,11 +95,11 @@ namespace boost
initial_event_state state)
{
#if !defined(BOOST_NO_ANSI_APIS)
handle const res = win32::CreateEventA(0, type, state, mutex_name);
handle const res = ::boost::winapi::CreateEventA(0, type, state, mutex_name);
#elif BOOST_USE_WINAPI_VERSION < BOOST_WINAPI_VERSION_VISTA
handle const res = win32::CreateEventW(0, type, state, mutex_name);
handle const res = ::boost::winapi::CreateEventW(0, type, state, mutex_name);
#else
handle const res = win32::CreateEventExW(
handle const res = ::boost::winapi::CreateEventExW(
0,
mutex_name,
type ? create_event_manual_reset : 0 | state ? create_event_initial_set : 0,
@@ -367,12 +121,12 @@ namespace boost
inline handle create_anonymous_semaphore_nothrow(long initial_count,long max_count)
{
#if !defined(BOOST_NO_ANSI_APIS)
handle const res=win32::CreateSemaphoreA(0,initial_count,max_count,0);
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=win32::CreateSemaphoreEx(0,initial_count,max_count,0,0);
handle const res=::boost::winapi::CreateSemaphoreEx(0,initial_count,max_count,0,0);
#else
handle const res=win32::CreateSemaphoreExW(0,initial_count,max_count,0,0,semaphore_all_access);
handle const res=::boost::winapi::CreateSemaphoreExW(0,initial_count,max_count,0,0,semaphore_all_access);
#endif
#endif
return res;
@@ -390,10 +144,10 @@ namespace boost
inline handle duplicate_handle(handle source)
{
handle const current_process=GetCurrentProcess();
handle const current_process=::boost::winapi::GetCurrentProcess();
long const same_access_flag=2;
handle new_handle=0;
bool const success=DuplicateHandle(current_process,source,current_process,&new_handle,0,false,same_access_flag)!=0;
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());
@@ -403,15 +157,15 @@ namespace boost
inline void release_semaphore(handle semaphore,long count)
{
BOOST_VERIFY(ReleaseSemaphore(semaphore,count,0)!=0);
BOOST_VERIFY(::boost::winapi::ReleaseSemaphore(semaphore,count,0)!=0);
}
inline void get_system_info(system_info *info)
{
#if BOOST_PLAT_WINDOWS_RUNTIME
win32::GetNativeSystemInfo(info);
::boost::winapi::GetNativeSystemInfo(info);
#else
win32::GetSystemInfo(info);
::boost::winapi::GetSystemInfo(info);
#endif
}
@@ -422,15 +176,15 @@ namespace boost
#if BOOST_PLAT_WINDOWS_RUNTIME
std::this_thread::yield();
#else
::boost::detail::win32::Sleep(0);
::boost::winapi::Sleep(0);
#endif
}
else
{
#if BOOST_PLAT_WINDOWS_RUNTIME
::boost::detail::win32::WaitForSingleObjectEx(::boost::detail::win32::GetCurrentThread(), milliseconds, 0);
::boost::winapi::WaitForSingleObjectEx(::boost::winapi::GetCurrentThread(), milliseconds, 0);
#else
::boost::detail::win32::Sleep(milliseconds);
::boost::winapi::Sleep(milliseconds);
#endif
}
}
@@ -446,7 +200,7 @@ namespace boost
{
if (m_completionHandle != ::boost::detail::win32::invalid_handle_value)
{
CloseHandle(m_completionHandle);
::boost::winapi::CloseHandle(m_completionHandle);
}
}
@@ -474,7 +228,7 @@ namespace boost
{
if(handle_to_manage && handle_to_manage!=invalid_handle_value)
{
BOOST_VERIFY(CloseHandle(handle_to_manage));
BOOST_VERIFY(::boost::winapi::CloseHandle(handle_to_manage));
}
}