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

@@ -6,9 +6,12 @@
// (C) Copyright 2007-10 Anthony Williams
// (C) Copyright 2011-2012 Vicente J. Botet Escriba
#include <boost/thread/pthread/timespec.hpp>
#include <boost/thread/detail/platform_time.hpp>
#include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp>
#include <boost/thread/pthread/pthread_helpers.hpp>
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
#include <boost/thread/interruption.hpp>
#include <boost/thread/pthread/thread_data.hpp>
#endif
#include <boost/thread/pthread/condition_variable_fwd.hpp>
@@ -18,17 +21,12 @@
#endif
#include <boost/thread/detail/delete.hpp>
#include <algorithm>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
namespace this_thread
{
void BOOST_THREAD_DECL interruption_point();
}
#endif
namespace thread_cv_detail
{
template<typename MutexType>
@@ -45,9 +43,17 @@ namespace boost
m_.unlock();
m=&m_;
}
~lock_on_exit()
void deactivate()
{
if(m)
if (m)
{
m->lock();
}
m = 0;
}
~lock_on_exit() BOOST_NOEXCEPT_IF(false)
{
if (m)
{
m->lock();
}
@@ -70,10 +76,13 @@ namespace boost
detail::interruption_checker check_for_interruption(&internal_mutex,&cond);
pthread_mutex_t* the_mutex = &internal_mutex;
guard.activate(m);
res = pthread_cond_wait(&cond,the_mutex);
check_for_interruption.unlock_if_locked();
guard.deactivate();
#else
pthread_mutex_t* the_mutex = m.mutex()->native_handle();
#endif
res = pthread_cond_wait(&cond,the_mutex);
#endif
}
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
this_thread::interruption_point();
@@ -84,9 +93,18 @@ namespace boost
}
}
// 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
inline bool condition_variable::do_wait_until(
unique_lock<mutex>& m,
struct timespec const &timeout)
detail::internal_platform_timepoint const &timeout)
{
#if defined BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED
if (!m.owns_lock())
@@ -101,10 +119,13 @@ namespace boost
detail::interruption_checker check_for_interruption(&internal_mutex,&cond);
pthread_mutex_t* the_mutex = &internal_mutex;
guard.activate(m);
cond_res=pthread_cond_timedwait(&cond,the_mutex,&timeout.getTs());
check_for_interruption.unlock_if_locked();
guard.deactivate();
#else
pthread_mutex_t* the_mutex = m.mutex()->native_handle();
cond_res=pthread_cond_timedwait(&cond,the_mutex,&timeout.getTs());
#endif
cond_res=pthread_cond_timedwait(&cond,the_mutex,&timeout);
}
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
this_thread::interruption_point();
@@ -150,11 +171,11 @@ namespace boost
{
boost::throw_exception(thread_resource_error(res, "boost::condition_variable_any::condition_variable_any() failed in pthread_mutex_init"));
}
int const res2 = detail::monotonic_pthread_cond_init(cond);
int const res2 = pthread::cond_init(cond);
if(res2)
{
BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex));
boost::throw_exception(thread_resource_error(res2, "boost::condition_variable_any::condition_variable_any() failed in detail::monotonic_pthread_cond_init"));
boost::throw_exception(thread_resource_error(res2, "boost::condition_variable_any::condition_variable_any() failed in pthread::cond_init"));
}
}
~condition_variable_any()
@@ -176,6 +197,8 @@ namespace boost
#endif
guard.activate(m);
res=pthread_cond_wait(&cond,&internal_mutex);
check_for_interruption.unlock_if_locked();
guard.deactivate();
}
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
this_thread::interruption_point();
@@ -189,18 +212,38 @@ namespace boost
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)
{
struct timespec const timeout=detail::to_timespec(abs_time);
return do_wait_until(m, timeout);
#if defined BOOST_THREAD_WAIT_BUG
const detail::real_platform_timepoint ts(abs_time + BOOST_THREAD_WAIT_BUG);
#else
const detail::real_platform_timepoint ts(abs_time);
#endif
#if defined BOOST_THREAD_INTERNAL_CLOCK_IS_MONO
// 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::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();
#else
return do_wait_until(m, ts);
#endif
}
template<typename lock_type>
bool timed_wait(lock_type& m,xtime const& abs_time)
bool timed_wait(lock_type& m,::boost::xtime const& abs_time)
{
return timed_wait(m,system_time(abs_time));
}
@@ -208,22 +251,59 @@ namespace boost
template<typename lock_type,typename duration_type>
bool timed_wait(lock_type& m,duration_type const& wait_duration)
{
return timed_wait(m,get_system_time()+wait_duration);
if (wait_duration.is_pos_infinity())
{
wait(m);
return true;
}
if (wait_duration.is_special())
{
return true;
}
detail::platform_duration d(wait_duration);
#if defined(BOOST_THREAD_HAS_MONO_CLOCK) && !defined(BOOST_THREAD_INTERNAL_CLOCK_IS_MONO)
// 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::mono_platform_timepoint ts(detail::mono_platform_clock::now() + d);
do_wait_until(m, detail::internal_platform_clock::now() + d);
return ts > detail::mono_platform_clock::now();
#else
return do_wait_until(m, detail::internal_platform_clock::now() + d);
#endif
}
template<typename lock_type,typename predicate_type>
bool timed_wait(lock_type& m,boost::system_time const& abs_time, predicate_type pred)
{
#if defined BOOST_THREAD_WAIT_BUG
const detail::real_platform_timepoint ts(abs_time + BOOST_THREAD_WAIT_BUG);
#else
const detail::real_platform_timepoint ts(abs_time);
#endif
while (!pred())
{
if(!timed_wait(m, abs_time))
return pred();
#if defined BOOST_THREAD_INTERNAL_CLOCK_IS_MONO
// 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.
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);
#else
if (!do_wait_until(m, ts)) break; // timeout occurred
#endif
}
return true;
return pred();
}
template<typename lock_type,typename predicate_type>
bool timed_wait(lock_type& m,xtime const& abs_time, predicate_type pred)
bool timed_wait(lock_type& m,::boost::xtime const& abs_time, predicate_type pred)
{
return timed_wait(m,system_time(abs_time),pred);
}
@@ -231,24 +311,52 @@ namespace boost
template<typename lock_type,typename duration_type,typename predicate_type>
bool timed_wait(lock_type& m,duration_type const& wait_duration,predicate_type pred)
{
return timed_wait(m,get_system_time()+wait_duration,pred);
if (wait_duration.is_pos_infinity())
{
while (!pred())
{
wait(m);
}
return true;
}
if (wait_duration.is_special())
{
return pred();
}
detail::platform_duration d(wait_duration);
#if defined(BOOST_THREAD_HAS_MONO_CLOCK) && !defined(BOOST_THREAD_INTERNAL_CLOCK_IS_MONO)
// 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::mono_platform_timepoint ts(detail::mono_platform_clock::now() + d);
while (!pred())
{
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);
d = ts - detail::mono_platform_clock::now();
}
#else
const detail::internal_platform_timepoint ts(detail::internal_platform_clock::now() + d);
while (!pred())
{
if (!do_wait_until(m, ts)) break; // timeout occurred
}
#endif
return pred();
}
#endif
#ifndef BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
#ifdef BOOST_THREAD_USES_CHRONO
template <class lock_type,class Duration>
cv_status
wait_until(
lock_type& lock,
const chrono::time_point<chrono::system_clock, Duration>& t)
const chrono::time_point<detail::internal_chrono_clock, Duration>& t)
{
using namespace chrono;
typedef time_point<system_clock, nanoseconds> nano_sys_tmpt;
wait_until(lock,
nano_sys_tmpt(ceil<nanoseconds>(t.time_since_epoch())));
return system_clock::now() < t ? cv_status::no_timeout :
cv_status::timeout;
const boost::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>
@@ -257,11 +365,18 @@ namespace boost
lock_type& lock,
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();
wait_until(lock, s_now + ceil<nanoseconds>(t - c_now));
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>
@@ -270,86 +385,24 @@ namespace boost
lock_type& lock,
const chrono::duration<Rep, Period>& d)
{
using namespace chrono;
system_clock::time_point s_now = system_clock::now();
steady_clock::time_point c_now = steady_clock::now();
wait_until(lock, s_now + ceil<nanoseconds>(d));
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>
cv_status wait_until(
lock_type& lk,
chrono::time_point<chrono::system_clock, chrono::nanoseconds> tp)
{
using namespace chrono;
nanoseconds d = tp.time_since_epoch();
timespec ts = boost::detail::to_timespec(d);
if (do_wait_until(lk, ts)) return cv_status::no_timeout;
else return cv_status::timeout;
}
#endif
#else // defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
#ifdef BOOST_THREAD_USES_CHRONO
template <class lock_type, class Duration>
cv_status
template <class lock_type, class Duration, class Predicate>
bool
wait_until(
lock_type& lock,
const chrono::time_point<chrono::steady_clock, Duration>& t)
lock_type& lock,
const chrono::time_point<detail::internal_chrono_clock, Duration>& t,
Predicate pred)
{
using namespace chrono;
typedef time_point<steady_clock, nanoseconds> nano_sys_tmpt;
wait_until(lock,
nano_sys_tmpt(ceil<nanoseconds>(t.time_since_epoch())));
return steady_clock::now() < t ? cv_status::no_timeout :
cv_status::timeout;
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>
cv_status
wait_until(
lock_type& lock,
const chrono::time_point<Clock, Duration>& t)
{
using namespace chrono;
steady_clock::time_point s_now = steady_clock::now();
typename Clock::time_point c_now = Clock::now();
wait_until(lock, s_now + ceil<nanoseconds>(t - c_now));
return Clock::now() < t ? cv_status::no_timeout : cv_status::timeout;
}
template <class lock_type, class Rep, class Period>
cv_status
wait_for(
lock_type& lock,
const chrono::duration<Rep, Period>& d)
{
using namespace chrono;
steady_clock::time_point c_now = steady_clock::now();
wait_until(lock, c_now + ceil<nanoseconds>(d));
return steady_clock::now() - c_now < d ? cv_status::no_timeout :
cv_status::timeout;
}
template <class lock_type>
inline cv_status wait_until(
lock_type& lock,
chrono::time_point<chrono::steady_clock, chrono::nanoseconds> tp)
{
using namespace chrono;
nanoseconds d = tp.time_since_epoch();
timespec ts = boost::detail::to_timespec(d);
if (do_wait_until(lock, ts)) return cv_status::no_timeout;
else return cv_status::timeout;
}
#endif
#endif // defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
#ifdef BOOST_THREAD_USES_CHRONO
template <class lock_type, class Clock, class Duration, class Predicate>
bool
wait_until(
@@ -357,12 +410,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>
@@ -372,7 +431,7 @@ namespace boost
const chrono::duration<Rep, Period>& d,
Predicate pred)
{
return wait_until(lock, chrono::steady_clock::now() + d, boost::move(pred));
return wait_until(lock, chrono::steady_clock::now() + d, boost::move(pred));
}
#endif
@@ -387,12 +446,21 @@ namespace boost
boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex);
BOOST_VERIFY(!pthread_cond_broadcast(&cond));
}
private: // used by boost::thread::try_join_until
private:
// 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 <class lock_type>
bool do_wait_until(
lock_type& m,
struct timespec const &timeout)
detail::internal_platform_timepoint const &timeout)
{
int res=0;
{
@@ -403,7 +471,9 @@ namespace boost
boost::pthread::pthread_mutex_scoped_lock check_for_interruption(&internal_mutex);
#endif
guard.activate(m);
res=pthread_cond_timedwait(&cond,&internal_mutex,&timeout);
res=pthread_cond_timedwait(&cond,&internal_mutex,&timeout.getTs());
check_for_interruption.unlock_if_locked();
guard.deactivate();
}
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
this_thread::interruption_point();
@@ -419,7 +489,6 @@ namespace boost
return true;
}
};
}
#include <boost/config/abi_suffix.hpp>

View File

@@ -13,7 +13,9 @@
#include <boost/thread/mutex.hpp>
#include <boost/thread/lock_types.hpp>
#include <boost/thread/thread_time.hpp>
#include <boost/thread/pthread/timespec.hpp>
#include <boost/thread/detail/platform_time.hpp>
#include <boost/thread/pthread/pthread_helpers.hpp>
#if defined BOOST_THREAD_USES_DATETIME
#include <boost/thread/xtime.hpp>
#endif
@@ -25,96 +27,63 @@
#include <boost/thread/detail/delete.hpp>
#include <boost/date_time/posix_time/posix_time_duration.hpp>
#include <algorithm>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace detail {
inline int monotonic_pthread_cond_init(pthread_cond_t& cond) {
#ifdef BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
pthread_condattr_t attr;
int res = pthread_condattr_init(&attr);
if (res)
{
return res;
}
pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
res=pthread_cond_init(&cond,&attr);
pthread_condattr_destroy(&attr);
return res;
#else
return pthread_cond_init(&cond,NULL);
#endif
}
}
class condition_variable
{
private:
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
//#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
pthread_mutex_t internal_mutex;
#endif
//#endif
pthread_cond_t cond;
public:
//private: // used by boost::thread::try_join_until
inline bool do_wait_until(
bool do_wait_until(
unique_lock<mutex>& lock,
struct timespec const &timeout);
bool do_wait_for(
unique_lock<mutex>& lock,
struct timespec const &timeout)
{
#if ! defined BOOST_THREAD_USEFIXES_TIMESPEC
return do_wait_until(lock, boost::detail::timespec_plus(timeout, boost::detail::timespec_now()));
#elif ! defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
//using namespace chrono;
//nanoseconds ns = chrono::system_clock::now().time_since_epoch();
struct timespec ts = boost::detail::timespec_now_realtime();
//ts.tv_sec = static_cast<long>(chrono::duration_cast<chrono::seconds>(ns).count());
//ts.tv_nsec = static_cast<long>((ns - chrono::duration_cast<chrono::seconds>(ns)).count());
return do_wait_until(lock, boost::detail::timespec_plus(timeout, ts));
#else
// old behavior was fine for monotonic
return do_wait_until(lock, boost::detail::timespec_plus(timeout, boost::detail::timespec_now_realtime()));
#endif
}
detail::internal_platform_timepoint const &timeout);
public:
BOOST_THREAD_NO_COPYABLE(condition_variable)
condition_variable()
{
int res;
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
//#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
// Even if it is not used, the internal_mutex exists (see
// above) and must be initialized (etc) in case some
// compilation units provide interruptions and others
// don't.
res=pthread_mutex_init(&internal_mutex,NULL);
if(res)
{
boost::throw_exception(thread_resource_error(res, "boost::condition_variable::condition_variable() constructor failed in pthread_mutex_init"));
}
#endif
res = detail::monotonic_pthread_cond_init(cond);
//#endif
res = pthread::cond_init(cond);
if (res)
{
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
//#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
// ditto
BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex));
#endif
boost::throw_exception(thread_resource_error(res, "boost::condition_variable::condition_variable() constructor failed in detail::monotonic_pthread_cond_init"));
//#endif
boost::throw_exception(thread_resource_error(res, "boost::condition_variable::condition_variable() constructor failed in pthread::cond_init"));
}
}
~condition_variable()
{
int ret;
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
//#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
// ditto
do {
ret = pthread_mutex_destroy(&internal_mutex);
} while (ret == EINTR);
BOOST_ASSERT(!ret);
#endif
//#endif
do {
ret = pthread_cond_destroy(&cond);
} while (ret == EINTR);
@@ -126,25 +95,40 @@ namespace boost
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
inline bool timed_wait(
bool timed_wait(
unique_lock<mutex>& m,
boost::system_time const& abs_time)
{
#if defined BOOST_THREAD_WAIT_BUG
struct timespec const timeout=detail::to_timespec(abs_time + BOOST_THREAD_WAIT_BUG);
return do_wait_until(m, timeout);
const detail::real_platform_timepoint ts(abs_time + BOOST_THREAD_WAIT_BUG);
#else
struct timespec const timeout=detail::to_timespec(abs_time);
return do_wait_until(m, timeout);
const detail::real_platform_timepoint ts(abs_time);
#endif
#if defined BOOST_THREAD_INTERNAL_CLOCK_IS_MONO
// 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::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();
#else
return do_wait_until(m, ts);
#endif
}
bool timed_wait(
unique_lock<mutex>& m,
xtime const& abs_time)
::boost::xtime const& abs_time)
{
return timed_wait(m,system_time(abs_time));
}
@@ -156,14 +140,28 @@ namespace boost
{
if (wait_duration.is_pos_infinity())
{
wait(m); // or do_wait(m,detail::timeout::sentinel());
wait(m);
return true;
}
if (wait_duration.is_special())
{
return true;
}
return timed_wait(m,get_system_time()+wait_duration);
detail::platform_duration d(wait_duration);
#if defined(BOOST_THREAD_HAS_MONO_CLOCK) && !defined(BOOST_THREAD_INTERNAL_CLOCK_IS_MONO)
// 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::mono_platform_timepoint ts(detail::mono_platform_clock::now() + d);
do_wait_until(m, detail::internal_platform_clock::now() + d);
return ts > detail::mono_platform_clock::now();
#else
return do_wait_until(m, detail::internal_platform_clock::now() + d);
#endif
}
template<typename predicate_type>
@@ -171,18 +169,32 @@ namespace boost
unique_lock<mutex>& m,
boost::system_time const& abs_time,predicate_type pred)
{
#if defined BOOST_THREAD_WAIT_BUG
const detail::real_platform_timepoint ts(abs_time + BOOST_THREAD_WAIT_BUG);
#else
const detail::real_platform_timepoint ts(abs_time);
#endif
while (!pred())
{
if(!timed_wait(m, abs_time))
return pred();
#if defined BOOST_THREAD_INTERNAL_CLOCK_IS_MONO
// 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.
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);
#else
if (!do_wait_until(m, ts)) break; // timeout occurred
#endif
}
return true;
return pred();
}
template<typename predicate_type>
bool timed_wait(
unique_lock<mutex>& m,
xtime const& abs_time,predicate_type pred)
::boost::xtime const& abs_time,predicate_type pred)
{
return timed_wait(m,system_time(abs_time),pred);
}
@@ -196,7 +208,7 @@ namespace boost
{
while (!pred())
{
wait(m); // or do_wait(m,detail::timeout::sentinel());
wait(m);
}
return true;
}
@@ -204,26 +216,41 @@ namespace boost
{
return pred();
}
return timed_wait(m,get_system_time()+wait_duration,pred);
detail::platform_duration d(wait_duration);
#if defined(BOOST_THREAD_HAS_MONO_CLOCK) && !defined(BOOST_THREAD_INTERNAL_CLOCK_IS_MONO)
// 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::mono_platform_timepoint ts(detail::mono_platform_clock::now() + d);
while (!pred())
{
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);
d = ts - detail::mono_platform_clock::now();
}
#else
const detail::internal_platform_timepoint ts(detail::internal_platform_clock::now() + d);
while (!pred())
{
if (!do_wait_until(m, ts)) break; // timeout occurred
}
#endif
return pred();
}
#endif
#ifndef BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
#ifdef BOOST_THREAD_USES_CHRONO
template <class Duration>
cv_status
wait_until(
unique_lock<mutex>& lock,
const chrono::time_point<chrono::system_clock, Duration>& t)
const chrono::time_point<detail::internal_chrono_clock, Duration>& t)
{
using namespace chrono;
typedef time_point<system_clock, nanoseconds> nano_sys_tmpt;
wait_until(lock,
nano_sys_tmpt(ceil<nanoseconds>(t.time_since_epoch())));
return system_clock::now() < t ? cv_status::no_timeout :
cv_status::timeout;
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>
@@ -232,100 +259,44 @@ namespace boost
unique_lock<mutex>& lock,
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();
wait_until(lock, s_now + ceil<nanoseconds>(t - c_now));
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>
cv_status
wait_for(
unique_lock<mutex>& lock,
const chrono::duration<Rep, Period>& d)
{
using namespace chrono;
system_clock::time_point s_now = system_clock::now();
steady_clock::time_point c_now = steady_clock::now();
wait_until(lock, s_now + ceil<nanoseconds>(d));
return steady_clock::now() - c_now < d ? cv_status::no_timeout :
cv_status::timeout;
return wait_until(lock, chrono::steady_clock::now() + d);
}
inline cv_status wait_until(
unique_lock<mutex>& lk,
chrono::time_point<chrono::system_clock, chrono::nanoseconds> tp)
{
using namespace chrono;
nanoseconds d = tp.time_since_epoch();
timespec ts = boost::detail::to_timespec(d);
if (do_wait_until(lk, ts)) return cv_status::no_timeout;
else return cv_status::timeout;
}
#endif
#else // defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
#ifdef BOOST_THREAD_USES_CHRONO
template <class Duration>
cv_status
template <class Duration, class Predicate>
bool
wait_until(
unique_lock<mutex>& lock,
const chrono::time_point<chrono::steady_clock, Duration>& t)
unique_lock<mutex>& lock,
const chrono::time_point<detail::internal_chrono_clock, Duration>& t,
Predicate pred)
{
using namespace chrono;
typedef time_point<steady_clock, nanoseconds> nano_sys_tmpt;
wait_until(lock,
nano_sys_tmpt(ceil<nanoseconds>(t.time_since_epoch())));
return steady_clock::now() < t ? cv_status::no_timeout :
cv_status::timeout;
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>
cv_status
wait_until(
unique_lock<mutex>& lock,
const chrono::time_point<Clock, Duration>& t)
{
using namespace chrono;
steady_clock::time_point s_now = steady_clock::now();
typename Clock::time_point c_now = Clock::now();
wait_until(lock, s_now + ceil<nanoseconds>(t - c_now));
return Clock::now() < t ? cv_status::no_timeout : cv_status::timeout;
}
template <class Rep, class Period>
cv_status
wait_for(
unique_lock<mutex>& lock,
const chrono::duration<Rep, Period>& d)
{
using namespace chrono;
steady_clock::time_point c_now = steady_clock::now();
wait_until(lock, c_now + ceil<nanoseconds>(d));
return steady_clock::now() - c_now < d ? cv_status::no_timeout :
cv_status::timeout;
}
inline cv_status wait_until(
unique_lock<mutex>& lk,
chrono::time_point<chrono::steady_clock, chrono::nanoseconds> tp)
{
using namespace chrono;
nanoseconds d = tp.time_since_epoch();
timespec ts = boost::detail::to_timespec(d);
if (do_wait_until(lk, ts)) return cv_status::no_timeout;
else return cv_status::timeout;
}
#endif
#endif // defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
#ifdef BOOST_THREAD_USES_CHRONO
template <class Clock, class Duration, class Predicate>
bool
wait_until(
@@ -333,12 +304,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 Rep, class Period, class Predicate>
@@ -348,7 +325,7 @@ namespace boost
const chrono::duration<Rep, Period>& d,
Predicate pred)
{
return wait_until(lock, chrono::steady_clock::now() + d, boost::move(pred));
return wait_until(lock, chrono::steady_clock::now() + d, boost::move(pred));
}
#endif
@@ -361,15 +338,11 @@ namespace boost
void notify_one() BOOST_NOEXCEPT;
void notify_all() BOOST_NOEXCEPT;
};
BOOST_THREAD_DECL void notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk);
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -16,24 +16,20 @@
#include <boost/thread/lock_types.hpp>
#endif
#include <boost/thread/thread_time.hpp>
#if defined BOOST_THREAD_USES_DATETIME
#include <boost/thread/xtime.hpp>
#endif
#include <boost/assert.hpp>
#include <errno.h>
#include <boost/thread/pthread/timespec.hpp>
#include <boost/thread/detail/platform_time.hpp>
#include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp>
#include <boost/thread/pthread/pthread_helpers.hpp>
#ifdef BOOST_THREAD_USES_CHRONO
#include <boost/chrono/system_clocks.hpp>
#include <boost/chrono/ceil.hpp>
#endif
#include <boost/thread/detail/delete.hpp>
#if (defined(_POSIX_TIMEOUTS) && (_POSIX_TIMEOUTS-0)>=200112L) \
|| (defined(__ANDROID__) && defined(__ANDROID_API__) && __ANDROID_API__ >= 21)
#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK
#define BOOST_PTHREAD_HAS_TIMEDLOCK
#endif
#endif
#include <boost/config/abi_prefix.hpp>
@@ -43,53 +39,8 @@
namespace boost
{
namespace posix {
#ifdef BOOST_THREAD_HAS_EINTR_BUG
BOOST_FORCEINLINE int pthread_mutex_destroy(pthread_mutex_t* m)
{
int ret;
do
{
ret = ::pthread_mutex_destroy(m);
} while (ret == EINTR);
return ret;
}
BOOST_FORCEINLINE int pthread_mutex_lock(pthread_mutex_t* m)
{
int ret;
do
{
ret = ::pthread_mutex_lock(m);
} while (ret == EINTR);
return ret;
}
BOOST_FORCEINLINE int pthread_mutex_unlock(pthread_mutex_t* m)
{
int ret;
do
{
ret = ::pthread_mutex_unlock(m);
} while (ret == EINTR);
return ret;
}
#else
BOOST_FORCEINLINE int pthread_mutex_destroy(pthread_mutex_t* m)
{
return ::pthread_mutex_destroy(m);
}
BOOST_FORCEINLINE int pthread_mutex_lock(pthread_mutex_t* m)
{
return ::pthread_mutex_lock(m);
}
BOOST_FORCEINLINE int pthread_mutex_unlock(pthread_mutex_t* m)
{
return ::pthread_mutex_unlock(m);
}
#endif
}
class mutex
class BOOST_THREAD_CAPABILITY("mutex") mutex
{
private:
pthread_mutex_t m;
@@ -111,7 +62,7 @@ namespace boost
BOOST_ASSERT(!res);
}
void lock()
void lock() BOOST_THREAD_ACQUIRE()
{
int res = posix::pthread_mutex_lock(&m);
if (res)
@@ -120,7 +71,7 @@ namespace boost
}
}
void unlock()
void unlock() BOOST_THREAD_RELEASE()
{
int res = posix::pthread_mutex_unlock(&m);
(void)res;
@@ -131,12 +82,12 @@ namespace boost
// }
}
bool try_lock()
bool try_lock() BOOST_THREAD_TRY_ACQUIRE(true)
{
int res;
do
{
res = pthread_mutex_trylock(&m);
res = posix::pthread_mutex_trylock(&m);
} while (res == EINTR);
if (res==EBUSY)
{
@@ -165,7 +116,7 @@ namespace boost
{
private:
pthread_mutex_t m;
#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK
#ifndef BOOST_THREAD_USES_PTHREAD_TIMEDLOCK
pthread_cond_t cond;
bool is_locked;
#endif
@@ -178,13 +129,12 @@ namespace boost
{
boost::throw_exception(thread_resource_error(res, "boost:: timed_mutex constructor failed in pthread_mutex_init"));
}
#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK
int const res2=pthread_cond_init(&cond,NULL);
#ifndef BOOST_THREAD_USES_PTHREAD_TIMEDLOCK
int const res2=pthread::cond_init(cond);
if(res2)
{
BOOST_VERIFY(!posix::pthread_mutex_destroy(&m));
//BOOST_VERIFY(!pthread_mutex_destroy(&m));
boost::throw_exception(thread_resource_error(res2, "boost:: timed_mutex constructor failed in pthread_cond_init"));
boost::throw_exception(thread_resource_error(res2, "boost:: timed_mutex constructor failed in pthread::cond_init"));
}
is_locked=false;
#endif
@@ -192,7 +142,7 @@ namespace boost
~timed_mutex()
{
BOOST_VERIFY(!posix::pthread_mutex_destroy(&m));
#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK
#ifndef BOOST_THREAD_USES_PTHREAD_TIMEDLOCK
BOOST_VERIFY(!pthread_cond_destroy(&cond));
#endif
}
@@ -201,14 +151,36 @@ namespace boost
template<typename TimeDuration>
bool timed_lock(TimeDuration const & relative_time)
{
return timed_lock(get_system_time()+relative_time);
if (relative_time.is_pos_infinity())
{
lock();
return true;
}
if (relative_time.is_special())
{
return true;
}
detail::platform_duration d(relative_time);
#if defined(BOOST_THREAD_HAS_MONO_CLOCK) && !defined(BOOST_THREAD_INTERNAL_CLOCK_IS_MONO)
const detail::mono_platform_timepoint ts(detail::mono_platform_clock::now() + d);
d = (std::min)(d, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
while ( ! do_try_lock_until(detail::internal_platform_clock::now() + d) )
{
d = ts - detail::mono_platform_clock::now();
if ( d <= detail::platform_duration::zero() ) return false; // timeout occurred
d = (std::min)(d, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
}
return true;
#else
return do_try_lock_until(detail::internal_platform_clock::now() + d);
#endif
}
bool timed_lock(boost::xtime const & absolute_time)
{
return timed_lock(system_time(absolute_time));
}
#endif
#ifdef BOOST_PTHREAD_HAS_TIMEDLOCK
#ifdef BOOST_THREAD_USES_PTHREAD_TIMEDLOCK
void lock()
{
int res = posix::pthread_mutex_lock(&m);
@@ -234,7 +206,7 @@ namespace boost
int res;
do
{
res = pthread_mutex_trylock(&m);
res = posix::pthread_mutex_trylock(&m);
} while (res == EINTR);
if (res==EBUSY)
{
@@ -246,9 +218,9 @@ namespace boost
private:
bool do_try_lock_until(struct timespec const &timeout)
bool do_try_lock_until(detail::internal_platform_timepoint const &timeout)
{
int const res=pthread_mutex_timedlock(&m,&timeout);
int const res=pthread_mutex_timedlock(&m,&timeout.getTs());
BOOST_ASSERT(!res || res==ETIMEDOUT);
return !res;
}
@@ -260,7 +232,7 @@ namespace boost
boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
while(is_locked)
{
BOOST_VERIFY(!pthread_cond_wait(&cond,&m));
BOOST_VERIFY(!posix::pthread_cond_wait(&cond,&m));
}
is_locked=true;
}
@@ -269,7 +241,7 @@ namespace boost
{
boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
is_locked=false;
BOOST_VERIFY(!pthread_cond_signal(&cond));
BOOST_VERIFY(!posix::pthread_cond_signal(&cond));
}
bool try_lock()
@@ -284,18 +256,22 @@ namespace boost
}
private:
bool do_try_lock_until(struct timespec const &timeout)
bool do_try_lock_until(detail::internal_platform_timepoint const &timeout)
{
boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
while(is_locked)
{
int const cond_res=pthread_cond_timedwait(&cond,&m,&timeout);
int const cond_res=pthread_cond_timedwait(&cond,&m,&timeout.getTs());
if(cond_res==ETIMEDOUT)
{
return false;
break;
}
BOOST_ASSERT(!cond_res);
}
if(is_locked)
{
return false;
}
is_locked=true;
return true;
}
@@ -305,8 +281,20 @@ namespace boost
#if defined BOOST_THREAD_USES_DATETIME
bool timed_lock(system_time const & abs_time)
{
struct timespec const ts=boost::detail::to_timespec(abs_time);
const detail::real_platform_timepoint ts(abs_time);
#if defined BOOST_THREAD_INTERNAL_CLOCK_IS_MONO
detail::platform_duration d(ts - detail::real_platform_clock::now());
d = (std::min)(d, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
while ( ! do_try_lock_until(detail::internal_platform_clock::now() + d) )
{
d = ts - detail::real_platform_clock::now();
if ( d <= detail::platform_duration::zero() ) return false; // timeout occurred
d = (std::min)(d, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
}
return true;
#else
return do_try_lock_until(ts);
#endif
}
#endif
#ifdef BOOST_THREAD_USES_CHRONO
@@ -318,23 +306,21 @@ namespace boost
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<nanoseconds>(t - c_now));
typedef typename common_type<Duration, typename Clock::duration>::type common_duration;
common_duration d(t - Clock::now());
d = (std::min)(d, common_duration(chrono::milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS)));
while ( ! try_lock_until(detail::internal_chrono_clock::now() + d))
{
d = t - Clock::now();
if ( d <= common_duration::zero() ) return false; // timeout occurred
d = (std::min)(d, common_duration(chrono::milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS)));
}
return true;
}
template <class Duration>
bool try_lock_until(const chrono::time_point<chrono::system_clock, Duration>& t)
bool try_lock_until(const chrono::time_point<detail::internal_chrono_clock, Duration>& t)
{
using namespace chrono;
typedef time_point<system_clock, nanoseconds> nano_sys_tmpt;
return try_lock_until(nano_sys_tmpt(ceil<nanoseconds>(t.time_since_epoch())));
}
bool try_lock_until(const chrono::time_point<chrono::system_clock, chrono::nanoseconds>& tp)
{
//using namespace chrono;
chrono::nanoseconds d = tp.time_since_epoch();
timespec ts = boost::detail::to_timespec(d);
detail::internal_platform_timepoint ts(t);
return do_try_lock_until(ts);
}
#endif
@@ -352,7 +338,6 @@ namespace boost
typedef scoped_timed_lock scoped_lock;
#endif
};
}
#include <boost/config/abi_suffix.hpp>

View File

@@ -0,0 +1,42 @@
#ifndef BOOST_THREAD_PTHREAD_PTHREAD_HELPERS_HPP
#define BOOST_THREAD_PTHREAD_PTHREAD_HELPERS_HPP
// Copyright (C) 2017
// 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/detail/config.hpp>
#include <pthread.h>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace pthread
{
inline int cond_init(pthread_cond_t& cond) {
#ifdef BOOST_THREAD_INTERNAL_CLOCK_IS_MONO
pthread_condattr_t attr;
int res = pthread_condattr_init(&attr);
if (res)
{
return res;
}
pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
res=pthread_cond_init(&cond,&attr);
pthread_condattr_destroy(&attr);
return res;
#else
return pthread_cond_init(&cond,NULL);
#endif
}
}
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -1,6 +1,6 @@
#ifndef BOOST_PTHREAD_MUTEX_SCOPED_LOCK_HPP
#define BOOST_PTHREAD_MUTEX_SCOPED_LOCK_HPP
// (C) Copyright 2007-8 Anthony Williams
// (C) Copyright 2007-8 Anthony Williams
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
@@ -13,6 +13,75 @@
namespace boost
{
namespace posix {
#ifdef BOOST_THREAD_HAS_EINTR_BUG
BOOST_FORCEINLINE BOOST_THREAD_DISABLE_THREAD_SAFETY_ANALYSIS
int pthread_mutex_destroy(pthread_mutex_t* m)
{
int ret;
do
{
ret = ::pthread_mutex_destroy(m);
} while (ret == EINTR);
return ret;
}
BOOST_FORCEINLINE BOOST_THREAD_DISABLE_THREAD_SAFETY_ANALYSIS
int pthread_mutex_lock(pthread_mutex_t* m)
{
int ret;
do
{
ret = ::pthread_mutex_lock(m);
} while (ret == EINTR);
return ret;
}
BOOST_FORCEINLINE BOOST_THREAD_DISABLE_THREAD_SAFETY_ANALYSIS
int pthread_mutex_unlock(pthread_mutex_t* m)
{
int ret;
do
{
ret = ::pthread_mutex_unlock(m);
} while (ret == EINTR);
return ret;
}
#else
BOOST_FORCEINLINE BOOST_THREAD_DISABLE_THREAD_SAFETY_ANALYSIS
int pthread_mutex_destroy(pthread_mutex_t* m)
{
return ::pthread_mutex_destroy(m);
}
BOOST_FORCEINLINE BOOST_THREAD_DISABLE_THREAD_SAFETY_ANALYSIS
int pthread_mutex_lock(pthread_mutex_t* m)
{
return ::pthread_mutex_lock(m);
}
BOOST_FORCEINLINE BOOST_THREAD_DISABLE_THREAD_SAFETY_ANALYSIS
int pthread_mutex_unlock(pthread_mutex_t* m)
{
return ::pthread_mutex_unlock(m);
}
#endif
BOOST_FORCEINLINE BOOST_THREAD_DISABLE_THREAD_SAFETY_ANALYSIS
int pthread_mutex_trylock(pthread_mutex_t* m)
{
return ::pthread_mutex_trylock(m);
}
BOOST_FORCEINLINE BOOST_THREAD_DISABLE_THREAD_SAFETY_ANALYSIS
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
{
return ::pthread_cond_wait(cond, mutex);
}
BOOST_FORCEINLINE BOOST_THREAD_DISABLE_THREAD_SAFETY_ANALYSIS
int pthread_cond_signal(pthread_cond_t *cond)
{
return ::pthread_cond_signal(cond);
}
}
namespace pthread
{
class pthread_mutex_scoped_lock
@@ -20,41 +89,47 @@ namespace boost
pthread_mutex_t* m;
bool locked;
public:
explicit pthread_mutex_scoped_lock(pthread_mutex_t* m_):
explicit pthread_mutex_scoped_lock(pthread_mutex_t* m_) BOOST_NOEXCEPT:
m(m_),locked(true)
{
BOOST_VERIFY(!pthread_mutex_lock(m));
BOOST_VERIFY(!posix::pthread_mutex_lock(m));
}
void unlock()
void unlock() BOOST_NOEXCEPT
{
BOOST_VERIFY(!pthread_mutex_unlock(m));
BOOST_VERIFY(!posix::pthread_mutex_unlock(m));
locked=false;
}
~pthread_mutex_scoped_lock()
void unlock_if_locked() BOOST_NOEXCEPT
{
if(locked)
{
unlock();
}
}
~pthread_mutex_scoped_lock() BOOST_NOEXCEPT
{
if(locked)
{
unlock();
}
}
};
class pthread_mutex_scoped_unlock
{
pthread_mutex_t* m;
public:
explicit pthread_mutex_scoped_unlock(pthread_mutex_t* m_):
explicit pthread_mutex_scoped_unlock(pthread_mutex_t* m_) BOOST_NOEXCEPT:
m(m_)
{
BOOST_VERIFY(!pthread_mutex_unlock(m));
BOOST_VERIFY(!posix::pthread_mutex_unlock(m));
}
~pthread_mutex_scoped_unlock()
~pthread_mutex_scoped_unlock() BOOST_NOEXCEPT
{
BOOST_VERIFY(!pthread_mutex_lock(m));
BOOST_VERIFY(!posix::pthread_mutex_lock(m));
}
};
}
}

View File

@@ -19,27 +19,22 @@
#endif
#include <boost/date_time/posix_time/conversion.hpp>
#include <errno.h>
#include <boost/thread/pthread/timespec.hpp>
#include <boost/thread/detail/platform_time.hpp>
#include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp>
#include <boost/thread/pthread/pthread_helpers.hpp>
#ifdef BOOST_THREAD_USES_CHRONO
#include <boost/chrono/system_clocks.hpp>
#include <boost/chrono/ceil.hpp>
#endif
#include <boost/thread/detail/delete.hpp>
#if (defined _POSIX_TIMEOUTS && (_POSIX_TIMEOUTS-0)>=200112L) \
|| (defined __ANDROID__ && defined __ANDROID_API__ && __ANDROID_API__ >= 21)
#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK
#define BOOST_PTHREAD_HAS_TIMEDLOCK
#endif
#endif
#if defined BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE \
|| defined __ANDROID__
#define BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE
#endif
#if defined BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE && defined BOOST_PTHREAD_HAS_TIMEDLOCK
#if defined BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE && defined BOOST_THREAD_USES_PTHREAD_TIMEDLOCK
#define BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK
#endif
@@ -89,11 +84,11 @@ namespace boost
{
boost::throw_exception(thread_resource_error(res, "boost:: recursive_mutex constructor failed in pthread_mutex_init"));
}
int const res2=pthread_cond_init(&cond,NULL);
int const res2=pthread::cond_init(cond);
if(res2)
{
BOOST_VERIFY(!pthread_mutex_destroy(&m));
boost::throw_exception(thread_resource_error(res2, "boost:: recursive_mutex constructor failed in pthread_cond_init"));
boost::throw_exception(thread_resource_error(res2, "boost:: recursive_mutex constructor failed in pthread::cond_init"));
}
is_locked=false;
count=0;
@@ -110,17 +105,17 @@ namespace boost
#ifdef BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE
void lock()
{
BOOST_VERIFY(!pthread_mutex_lock(&m));
BOOST_VERIFY(!posix::pthread_mutex_lock(&m));
}
void unlock()
{
BOOST_VERIFY(!pthread_mutex_unlock(&m));
BOOST_VERIFY(!posix::pthread_mutex_unlock(&m));
}
bool try_lock() BOOST_NOEXCEPT
{
int const res=pthread_mutex_trylock(&m);
int const res=posix::pthread_mutex_trylock(&m);
BOOST_ASSERT(!res || res==EBUSY);
return !res;
}
@@ -224,11 +219,11 @@ namespace boost
{
boost::throw_exception(thread_resource_error(res, "boost:: recursive_timed_mutex constructor failed in pthread_mutex_init"));
}
int const res2=pthread_cond_init(&cond,NULL);
int const res2=pthread::cond_init(cond);
if(res2)
{
BOOST_VERIFY(!pthread_mutex_destroy(&m));
boost::throw_exception(thread_resource_error(res2, "boost:: recursive_timed_mutex constructor failed in pthread_cond_init"));
boost::throw_exception(thread_resource_error(res2, "boost:: recursive_timed_mutex constructor failed in pthread::cond_init"));
}
is_locked=false;
count=0;
@@ -246,31 +241,53 @@ namespace boost
template<typename TimeDuration>
bool timed_lock(TimeDuration const & relative_time)
{
return timed_lock(get_system_time()+relative_time);
if (relative_time.is_pos_infinity())
{
lock();
return true;
}
if (relative_time.is_special())
{
return true;
}
detail::platform_duration d(relative_time);
#if defined(BOOST_THREAD_HAS_MONO_CLOCK) && !defined(BOOST_THREAD_INTERNAL_CLOCK_IS_MONO)
const detail::mono_platform_timepoint ts(detail::mono_platform_clock::now() + d);
d = (std::min)(d, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
while ( ! do_try_lock_until(detail::internal_platform_clock::now() + d) )
{
d = ts - detail::mono_platform_clock::now();
if ( d <= detail::platform_duration::zero() ) return false; // timeout occurred
d = (std::min)(d, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
}
return true;
#else
return do_try_lock_until(detail::internal_platform_clock::now() + d);
#endif
}
#endif
#ifdef BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK
void lock()
{
BOOST_VERIFY(!pthread_mutex_lock(&m));
BOOST_VERIFY(!posix::pthread_mutex_lock(&m));
}
void unlock()
{
BOOST_VERIFY(!pthread_mutex_unlock(&m));
BOOST_VERIFY(!posix::pthread_mutex_unlock(&m));
}
bool try_lock()
{
int const res=pthread_mutex_trylock(&m);
int const res=posix::pthread_mutex_trylock(&m);
BOOST_ASSERT(!res || res==EBUSY);
return !res;
}
private:
bool do_try_lock_until(struct timespec const &timeout)
bool do_try_lock_until(detail::internal_platform_timepoint const &timeout)
{
int const res=pthread_mutex_timedlock(&m,&timeout);
int const res=pthread_mutex_timedlock(&m,&timeout.getTs());
BOOST_ASSERT(!res || res==ETIMEDOUT);
return !res;
}
@@ -320,7 +337,7 @@ namespace boost
}
private:
bool do_try_lock_until(struct timespec const &timeout)
bool do_try_lock_until(detail::internal_platform_timepoint const &timeout)
{
boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
if(is_locked && pthread_equal(owner,pthread_self()))
@@ -330,13 +347,17 @@ namespace boost
}
while(is_locked)
{
int const cond_res=pthread_cond_timedwait(&cond,&m,&timeout);
int const cond_res=pthread_cond_timedwait(&cond,&m,&timeout.getTs());
if(cond_res==ETIMEDOUT)
{
return false;
break;
}
BOOST_ASSERT(!cond_res);
}
if(is_locked)
{
return false;
}
is_locked=true;
++count;
owner=pthread_self();
@@ -349,8 +370,20 @@ namespace boost
#if defined BOOST_THREAD_USES_DATETIME
bool timed_lock(system_time const & abs_time)
{
struct timespec const ts=detail::to_timespec(abs_time);
const detail::real_platform_timepoint ts(abs_time);
#if defined BOOST_THREAD_INTERNAL_CLOCK_IS_MONO
detail::platform_duration d(ts - detail::real_platform_clock::now());
d = (std::min)(d, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
while ( ! do_try_lock_until(detail::internal_platform_clock::now() + d) )
{
d = ts - detail::real_platform_clock::now();
if ( d <= detail::platform_duration::zero() ) return false; // timeout occurred
d = (std::min)(d, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
}
return true;
#else
return do_try_lock_until(ts);
#endif
}
#endif
#ifdef BOOST_THREAD_USES_CHRONO
@@ -362,23 +395,22 @@ namespace boost
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<nanoseconds>(t - c_now));
typedef typename common_type<Duration, typename Clock::duration>::type common_duration;
common_duration d(t - Clock::now());
d = (std::min)(d, common_duration(chrono::milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS)));
while ( ! try_lock_until(detail::internal_chrono_clock::now() + d))
{
d = t - Clock::now();
if ( d <= common_duration::zero() ) return false; // timeout occurred
d = (std::min)(d, common_duration(chrono::milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS)));
}
return true;
}
template <class Duration>
bool try_lock_until(const chrono::time_point<chrono::system_clock, Duration>& t)
bool try_lock_until(const chrono::time_point<detail::internal_chrono_clock, Duration>& t)
{
using namespace chrono;
typedef time_point<system_clock, nanoseconds> nano_sys_tmpt;
return try_lock_until(nano_sys_tmpt(ceil<nanoseconds>(t.time_since_epoch())));
}
bool try_lock_until(const chrono::time_point<chrono::system_clock, chrono::nanoseconds>& tp)
{
//using namespace chrono;
chrono::nanoseconds d = tp.time_since_epoch();
timespec ts = boost::detail::to_timespec(d);
detail::internal_platform_timepoint ts(t);
return do_try_lock_until(ts);
}
#endif

View File

@@ -9,6 +9,7 @@
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/assert.hpp>
#include <boost/bind.hpp>
#include <boost/static_assert.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/condition_variable.hpp>
@@ -20,7 +21,6 @@
#include <boost/chrono/ceil.hpp>
#endif
#include <boost/thread/detail/delete.hpp>
#include <boost/assert.hpp>
#include <boost/config/abi_prefix.hpp>
@@ -79,11 +79,6 @@ namespace boost
return ! (shared_count || exclusive);
}
void exclusive_blocked (bool blocked)
{
exclusive_waiting_blocked = blocked;
}
void lock ()
{
exclusive = true;
@@ -100,17 +95,19 @@ namespace boost
return ! (exclusive || exclusive_waiting_blocked);
}
bool more_shared () const
bool no_shared () const
{
return shared_count > 0 ;
return shared_count==0;
}
unsigned get_shared_count () const
bool one_shared () const
{
return shared_count ;
return shared_count==1;
}
unsigned lock_shared ()
void lock_shared ()
{
return ++shared_count;
++shared_count;
}
@@ -119,18 +116,6 @@ namespace boost
--shared_count;
}
bool unlock_shared_downgrades()
{
if (upgrade) {
upgrade=false;
exclusive=true;
return true;
} else {
exclusive_waiting_blocked=false;
return false;
}
}
void lock_upgrade ()
{
++shared_count;
@@ -186,10 +171,7 @@ namespace boost
boost::this_thread::disable_interruption do_not_disturb;
#endif
boost::unique_lock<boost::mutex> lk(state_change);
while(!state.can_lock_shared())
{
shared_cond.wait(lk);
}
shared_cond.wait(lk, boost::bind(&state_data::can_lock_shared, boost::ref(state)));
state.lock_shared();
}
@@ -212,13 +194,9 @@ namespace boost
boost::this_thread::disable_interruption do_not_disturb;
#endif
boost::unique_lock<boost::mutex> lk(state_change);
while(!state.can_lock_shared())
if(!shared_cond.timed_wait(lk, timeout, boost::bind(&state_data::can_lock_shared, boost::ref(state))))
{
if(!shared_cond.timed_wait(lk,timeout))
{
return false;
}
return false;
}
state.lock_shared();
return true;
@@ -227,7 +205,16 @@ namespace boost
template<typename TimeDuration>
bool timed_lock_shared(TimeDuration const & relative_time)
{
return timed_lock_shared(get_system_time()+relative_time);
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
boost::this_thread::disable_interruption do_not_disturb;
#endif
boost::unique_lock<boost::mutex> lk(state_change);
if(!shared_cond.timed_wait(lk, relative_time, boost::bind(&state_data::can_lock_shared, boost::ref(state))))
{
return false;
}
state.lock_shared();
return true;
}
#endif
#ifdef BOOST_THREAD_USES_CHRONO
@@ -243,14 +230,9 @@ namespace boost
boost::this_thread::disable_interruption do_not_disturb;
#endif
boost::unique_lock<boost::mutex> lk(state_change);
while(!state.can_lock_shared())
//while(state.exclusive || state.exclusive_waiting_blocked)
if(!shared_cond.wait_until(lk, abs_time, boost::bind(&state_data::can_lock_shared, boost::ref(state))))
{
if(cv_status::timeout==shared_cond.wait_until(lk,abs_time))
{
return false;
}
return false;
}
state.lock_shared();
return true;
@@ -261,11 +243,11 @@ namespace boost
boost::unique_lock<boost::mutex> lk(state_change);
state.assert_lock_shared();
state.unlock_shared();
if (! state.more_shared())
if (state.no_shared())
{
if (state.upgrade)
{
// As there is a thread doing a unlock_upgrade_and_lock that is waiting for ! state.more_shared()
// As there is a thread doing a unlock_upgrade_and_lock that is waiting for state.no_shared()
// avoid other threads to lock, lock_upgrade or lock_shared, so only this thread is notified.
state.upgrade=false;
state.exclusive=true;
@@ -287,12 +269,8 @@ namespace boost
boost::this_thread::disable_interruption do_not_disturb;
#endif
boost::unique_lock<boost::mutex> lk(state_change);
while (state.shared_count || state.exclusive)
{
state.exclusive_waiting_blocked=true;
exclusive_cond.wait(lk);
}
state.exclusive_waiting_blocked=true;
exclusive_cond.wait(lk, boost::bind(&state_data::can_lock, boost::ref(state)));
state.exclusive=true;
}
@@ -303,20 +281,12 @@ namespace boost
boost::this_thread::disable_interruption do_not_disturb;
#endif
boost::unique_lock<boost::mutex> lk(state_change);
while(state.shared_count || state.exclusive)
state.exclusive_waiting_blocked=true;
if(!exclusive_cond.timed_wait(lk, timeout, boost::bind(&state_data::can_lock, boost::ref(state))))
{
state.exclusive_waiting_blocked=true;
if(!exclusive_cond.timed_wait(lk,timeout))
{
if(state.shared_count || state.exclusive)
{
state.exclusive_waiting_blocked=false;
release_waiters();
return false;
}
break;
}
state.exclusive_waiting_blocked=false;
release_waiters();
return false;
}
state.exclusive=true;
return true;
@@ -325,7 +295,19 @@ namespace boost
template<typename TimeDuration>
bool timed_lock(TimeDuration const & relative_time)
{
return timed_lock(get_system_time()+relative_time);
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
boost::this_thread::disable_interruption do_not_disturb;
#endif
boost::unique_lock<boost::mutex> lk(state_change);
state.exclusive_waiting_blocked=true;
if(!exclusive_cond.timed_wait(lk, relative_time, boost::bind(&state_data::can_lock, boost::ref(state))))
{
state.exclusive_waiting_blocked=false;
release_waiters();
return false;
}
state.exclusive=true;
return true;
}
#endif
#ifdef BOOST_THREAD_USES_CHRONO
@@ -341,20 +323,12 @@ namespace boost
boost::this_thread::disable_interruption do_not_disturb;
#endif
boost::unique_lock<boost::mutex> lk(state_change);
while(state.shared_count || state.exclusive)
state.exclusive_waiting_blocked=true;
if(!exclusive_cond.wait_until(lk, abs_time, boost::bind(&state_data::can_lock, boost::ref(state))))
{
state.exclusive_waiting_blocked=true;
if(cv_status::timeout == exclusive_cond.wait_until(lk,abs_time))
{
if(state.shared_count || state.exclusive)
{
state.exclusive_waiting_blocked=false;
release_waiters();
return false;
}
break;
}
state.exclusive_waiting_blocked=false;
release_waiters();
return false;
}
state.exclusive=true;
return true;
@@ -364,17 +338,12 @@ namespace boost
bool try_lock()
{
boost::unique_lock<boost::mutex> lk(state_change);
if(state.shared_count || state.exclusive)
if(!state.can_lock())
{
return false;
}
else
{
state.exclusive=true;
return true;
}
state.exclusive=true;
return true;
}
void unlock()
@@ -393,10 +362,7 @@ namespace boost
boost::this_thread::disable_interruption do_not_disturb;
#endif
boost::unique_lock<boost::mutex> lk(state_change);
while(state.exclusive || state.exclusive_waiting_blocked || state.upgrade)
{
shared_cond.wait(lk);
}
shared_cond.wait(lk, boost::bind(&state_data::can_lock_upgrade, boost::ref(state)));
state.lock_shared();
state.upgrade=true;
}
@@ -408,16 +374,9 @@ namespace boost
boost::this_thread::disable_interruption do_not_disturb;
#endif
boost::unique_lock<boost::mutex> lk(state_change);
while(state.exclusive || state.exclusive_waiting_blocked || state.upgrade)
if(!shared_cond.timed_wait(lk, timeout, boost::bind(&state_data::can_lock_upgrade, boost::ref(state))))
{
if(!shared_cond.timed_wait(lk,timeout))
{
if(state.exclusive || state.exclusive_waiting_blocked || state.upgrade)
{
return false;
}
break;
}
return false;
}
state.lock_shared();
state.upgrade=true;
@@ -427,7 +386,17 @@ namespace boost
template<typename TimeDuration>
bool timed_lock_upgrade(TimeDuration const & relative_time)
{
return timed_lock_upgrade(get_system_time()+relative_time);
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
boost::this_thread::disable_interruption do_not_disturb;
#endif
boost::unique_lock<boost::mutex> lk(state_change);
if(!shared_cond.timed_wait(lk, relative_time, boost::bind(&state_data::can_lock_upgrade, boost::ref(state))))
{
return false;
}
state.lock_shared();
state.upgrade=true;
return true;
}
#endif
#ifdef BOOST_THREAD_USES_CHRONO
@@ -443,16 +412,9 @@ namespace boost
boost::this_thread::disable_interruption do_not_disturb;
#endif
boost::unique_lock<boost::mutex> lk(state_change);
while(state.exclusive || state.exclusive_waiting_blocked || state.upgrade)
if(!shared_cond.wait_until(lk, abs_time, boost::bind(&state_data::can_lock_upgrade, boost::ref(state))))
{
if(cv_status::timeout == shared_cond.wait_until(lk,abs_time))
{
if(state.exclusive || state.exclusive_waiting_blocked || state.upgrade)
{
return false;
}
break;
}
return false;
}
state.lock_shared();
state.upgrade=true;
@@ -462,17 +424,14 @@ namespace boost
bool try_lock_upgrade()
{
boost::unique_lock<boost::mutex> lk(state_change);
if(state.exclusive || state.exclusive_waiting_blocked || state.upgrade)
if(!state.can_lock_upgrade())
{
return false;
}
else
{
state.lock_shared();
state.upgrade=true;
state.assert_lock_upgraded();
return true;
}
state.lock_shared();
state.upgrade=true;
state.assert_lock_upgraded();
return true;
}
void unlock_upgrade()
@@ -480,7 +439,7 @@ namespace boost
boost::unique_lock<boost::mutex> lk(state_change);
//state.upgrade=false;
state.unlock_upgrade();
if(! state.more_shared() )
if(state.no_shared())
{
state.exclusive_waiting_blocked=false;
release_waiters();
@@ -498,10 +457,7 @@ namespace boost
boost::unique_lock<boost::mutex> lk(state_change);
state.assert_lock_upgraded();
state.unlock_shared();
while (state.more_shared())
{
upgrade_cond.wait(lk);
}
upgrade_cond.wait(lk, boost::bind(&state_data::no_shared, boost::ref(state)));
state.upgrade=false;
state.exclusive=true;
state.assert_locked();
@@ -555,16 +511,9 @@ namespace boost
#endif
boost::unique_lock<boost::mutex> lk(state_change);
state.assert_lock_upgraded();
if (state.shared_count != 1)
if(!shared_cond.wait_until(lk, abs_time, boost::bind(&state_data::one_shared, boost::ref(state))))
{
for (;;)
{
cv_status status = shared_cond.wait_until(lk,abs_time);
if (state.shared_count == 1)
break;
if(status == cv_status::timeout)
return false;
}
return false;
}
state.upgrade=false;
state.exclusive=true;
@@ -620,16 +569,9 @@ namespace boost
#endif
boost::unique_lock<boost::mutex> lk(state_change);
state.assert_lock_shared();
if (state.shared_count != 1)
if(!shared_cond.wait_until(lk, abs_time, boost::bind(&state_data::one_shared, boost::ref(state))))
{
for (;;)
{
cv_status status = shared_cond.wait_until(lk,abs_time);
if (state.shared_count == 1)
break;
if(status == cv_status::timeout)
return false;
}
return false;
}
state.upgrade=false;
state.exclusive=true;
@@ -655,10 +597,7 @@ namespace boost
{
boost::unique_lock<boost::mutex> lk(state_change);
state.assert_lock_shared();
if( !state.exclusive
&& !state.exclusive_waiting_blocked
&& !state.upgrade
)
if(state.can_lock_upgrade())
{
state.upgrade=true;
return true;
@@ -684,22 +623,9 @@ namespace boost
#endif
boost::unique_lock<boost::mutex> lk(state_change);
state.assert_lock_shared();
if( state.exclusive
|| state.exclusive_waiting_blocked
|| state.upgrade
)
if(!exclusive_cond.wait_until(lk, abs_time, boost::bind(&state_data::can_lock_upgrade, boost::ref(state))))
{
for (;;)
{
cv_status status = exclusive_cond.wait_until(lk,abs_time);
if( ! state.exclusive
&& ! state.exclusive_waiting_blocked
&& ! state.upgrade
)
break;
if(status == cv_status::timeout)
return false;
}
return false;
}
state.upgrade=true;
return true;

View File

@@ -1,724 +0,0 @@
#ifndef BOOST_THREAD_PTHREAD_SHARED_MUTEX_HPP
#define BOOST_THREAD_PTHREAD_SHARED_MUTEX_HPP
// (C) Copyright 2006-8 Anthony Williams
// (C) Copyright 2012 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/assert.hpp>
#include <boost/static_assert.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/condition_variable.hpp>
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
#include <boost/thread/detail/thread_interruption.hpp>
#endif
#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/assert.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
class shared_mutex
{
private:
class state_data
{
public:
state_data () :
shared_count(0),
exclusive(false),
upgrade(false),
exclusive_waiting_blocked(false)
{}
void assert_free() const
{
BOOST_ASSERT( ! exclusive );
BOOST_ASSERT( ! upgrade );
BOOST_ASSERT( shared_count==0 );
}
void assert_locked() const
{
BOOST_ASSERT( exclusive );
BOOST_ASSERT( shared_count==0 );
BOOST_ASSERT( ! upgrade );
}
void assert_lock_shared () const
{
BOOST_ASSERT( ! exclusive );
BOOST_ASSERT( shared_count>0 );
//BOOST_ASSERT( (! upgrade) || (shared_count>1));
// if upgraded there are at least 2 threads sharing the mutex,
// except when unlock_upgrade_and_lock has decreased the number of readers but has not taken yet exclusive ownership.
}
void assert_lock_upgraded () const
{
BOOST_ASSERT( ! exclusive );
BOOST_ASSERT( upgrade );
BOOST_ASSERT( shared_count>0 );
}
void assert_lock_not_upgraded () const
{
BOOST_ASSERT( ! upgrade );
}
bool can_lock () const
{
return ! (shared_count || exclusive);
}
void exclusive_blocked (bool blocked)
{
exclusive_waiting_blocked = blocked;
}
void lock ()
{
exclusive = true;
}
void unlock ()
{
exclusive = false;
exclusive_waiting_blocked = false;
}
bool can_lock_shared () const
{
return ! (exclusive || exclusive_waiting_blocked);
}
bool is_last_shared () const
{
return !shared_count ;
}
unsigned get_shared_count () const
{
return shared_count ;
}
unsigned lock_shared ()
{
return ++shared_count;
}
void unlock_shared ()
{
--shared_count;
}
bool unlock_shared_downgrades()
{
if (upgrade) {
upgrade=false;
exclusive=true;
return true;
} else {
exclusive_waiting_blocked=false;
return false;
}
}
void lock_upgrade ()
{
lock_shared ();
upgrade=true;
}
bool can_lock_upgrade () const
{
return ! (exclusive || exclusive_waiting_blocked || upgrade);
}
void unlock_upgrade ()
{
upgrade=false;
unlock_shared();
}
//private:
unsigned shared_count;
bool exclusive;
bool upgrade;
bool exclusive_waiting_blocked;
};
state_data state;
boost::mutex state_change;
boost::condition_variable shared_cond;
boost::condition_variable exclusive_cond;
boost::condition_variable upgrade_cond;
void release_waiters()
{
exclusive_cond.notify_one();
shared_cond.notify_all();
}
public:
BOOST_THREAD_NO_COPYABLE(shared_mutex)
shared_mutex()
{
}
~shared_mutex()
{
}
void lock_shared()
{
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
boost::this_thread::disable_interruption do_not_disturb;
#endif
boost::unique_lock<boost::mutex> lk(state_change);
while(!state.can_lock_shared())
{
shared_cond.wait(lk);
}
state.lock_shared();
}
bool try_lock_shared()
{
boost::unique_lock<boost::mutex> lk(state_change);
if(!state.can_lock_shared())
{
return false;
}
else
{
state.lock_shared();
return true;
}
}
#if defined BOOST_THREAD_USES_DATETIME
bool timed_lock_shared(system_time const& timeout)
{
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
boost::this_thread::disable_interruption do_not_disturb;
#endif
boost::unique_lock<boost::mutex> lk(state_change);
while(!state.can_lock_shared())
{
if(!shared_cond.timed_wait(lk,timeout))
{
return false;
}
}
state.lock_shared();
return true;
}
template<typename TimeDuration>
bool timed_lock_shared(TimeDuration const & relative_time)
{
return timed_lock_shared(get_system_time()+relative_time);
}
#endif
#ifdef BOOST_THREAD_USES_CHRONO
template <class Rep, class Period>
bool try_lock_shared_for(const chrono::duration<Rep, Period>& rel_time)
{
return try_lock_shared_until(chrono::steady_clock::now() + rel_time);
}
template <class Clock, class Duration>
bool try_lock_shared_until(const chrono::time_point<Clock, Duration>& abs_time)
{
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
boost::this_thread::disable_interruption do_not_disturb;
#endif
boost::unique_lock<boost::mutex> lk(state_change);
while(!state.can_lock_shared())
{
if(cv_status::timeout==shared_cond.wait_until(lk,abs_time))
{
return false;
}
}
state.lock_shared();
return true;
}
#endif
void unlock_shared()
{
boost::unique_lock<boost::mutex> lk(state_change);
state.assert_lock_shared();
state.unlock_shared();
if (state.get_shared_count () == 0)
{
if (state.unlock_shared_downgrades())
{
lk.unlock();
upgrade_cond.notify_one();
} else {
lk.unlock();
}
release_waiters();
}
}
void lock()
{
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
boost::this_thread::disable_interruption do_not_disturb;
#endif
boost::unique_lock<boost::mutex> lk(state_change);
while(!state.can_lock())
{
state.exclusive_blocked(true);
exclusive_cond.wait(lk);
}
state.lock();
}
#if defined BOOST_THREAD_USES_DATETIME
bool timed_lock(system_time const& timeout)
{
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
boost::this_thread::disable_interruption do_not_disturb;
#endif
boost::unique_lock<boost::mutex> lk(state_change);
while(!state.can_lock())
{
state.exclusive_blocked(true);
if(!exclusive_cond.timed_wait(lk,timeout))
{
if(!state.can_lock())
{
state.exclusive_blocked(false);
release_waiters();
return false;
}
break;
}
}
state.exclusive=true;
//state.lock();
return true;
}
template<typename TimeDuration>
bool timed_lock(TimeDuration const & relative_time)
{
return timed_lock(get_system_time()+relative_time);
}
#endif
#ifdef BOOST_THREAD_USES_CHRONO
template <class Rep, class Period>
bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)
{
return try_lock_until(chrono::steady_clock::now() + rel_time);
}
template <class Clock, class Duration>
bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time)
{
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
boost::this_thread::disable_interruption do_not_disturb;
#endif
boost::unique_lock<boost::mutex> lk(state_change);
while(!state.can_lock())
{
state.exclusive_blocked(true);
if(cv_status::timeout == exclusive_cond.wait_until(lk,abs_time))
{
if(!state.can_lock())
{
state.exclusive_blocked(false);
release_waiters();
return false;
}
break;
}
}
state.exclusive=true;
//state.lock();
return true;
}
#endif
bool try_lock()
{
boost::unique_lock<boost::mutex> lk(state_change);
if(!state.can_lock())
{
return false;
}
else
{
state.lock();
return true;
}
}
void unlock()
{
boost::unique_lock<boost::mutex> lk(state_change);
state.assert_locked();
state.unlock();
state.assert_free();
release_waiters();
}
void lock_upgrade()
{
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
boost::this_thread::disable_interruption do_not_disturb;
#endif
boost::unique_lock<boost::mutex> lk(state_change);
while(!state.can_lock_upgrade())
{
shared_cond.wait(lk);
}
state.lock_upgrade();
}
#if defined BOOST_THREAD_USES_DATETIME
bool timed_lock_upgrade(system_time const& timeout)
{
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
boost::this_thread::disable_interruption do_not_disturb;
#endif
boost::unique_lock<boost::mutex> lk(state_change);
while(!state.can_lock_upgrade())
{
if(!shared_cond.timed_wait(lk,timeout))
{
if(!state.can_lock_upgrade())
{
return false;
}
break;
}
}
state.lock_upgrade();
return true;
}
template<typename TimeDuration>
bool timed_lock_upgrade(TimeDuration const & relative_time)
{
return timed_lock_upgrade(get_system_time()+relative_time);
}
#endif
#ifdef BOOST_THREAD_USES_CHRONO
template <class Rep, class Period>
bool try_lock_upgrade_for(const chrono::duration<Rep, Period>& rel_time)
{
return try_lock_upgrade_until(chrono::steady_clock::now() + rel_time);
}
template <class Clock, class Duration>
bool try_lock_upgrade_until(const chrono::time_point<Clock, Duration>& abs_time)
{
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
boost::this_thread::disable_interruption do_not_disturb;
#endif
boost::unique_lock<boost::mutex> lk(state_change);
while(!state.can_lock_upgrade())
{
if(cv_status::timeout == shared_cond.wait_until(lk,abs_time))
{
if(!state.can_lock_upgrade())
{
return false;
}
break;
}
}
state.lock_upgrade();
return true;
}
#endif
bool try_lock_upgrade()
{
boost::unique_lock<boost::mutex> lk(state_change);
if(!state.can_lock_upgrade())
{
return false;
}
else
{
state.lock_upgrade();
state.assert_lock_upgraded();
return true;
}
}
void unlock_upgrade()
{
boost::unique_lock<boost::mutex> lk(state_change);
state.assert_lock_upgraded();
state.unlock_upgrade();
state.assert_lock_not_upgraded ();
if(state.get_shared_count () == 0)
{
state.exclusive_blocked(false);
lk.unlock();
release_waiters();
} else {
lk.unlock();
shared_cond.notify_all();
}
}
// Upgrade <-> Exclusive
void unlock_upgrade_and_lock()
{
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
boost::this_thread::disable_interruption do_not_disturb;
#endif
boost::unique_lock<boost::mutex> lk(state_change);
state.assert_lock_upgraded();
// assert state.get_shared_count() >=1
while(
//! state.exclusive_waiting_blocked // Fixme: is this needed?
//&&
state.get_shared_count()!=1)
{
upgrade_cond.wait(lk);
}
state.unlock_upgrade();
state.lock();
state.assert_locked();
}
void unlock_and_lock_upgrade()
{
boost::unique_lock<boost::mutex> lk(state_change);
state.assert_locked();
state.unlock();
state.lock_upgrade();
state.assert_lock_upgraded();
release_waiters();
}
bool try_unlock_upgrade_and_lock()
{
boost::unique_lock<boost::mutex> lk(state_change);
state.assert_lock_upgraded();
if( //!state.exclusive // this should be removed once the assertion work
! state.exclusive_waiting_blocked // Fixme: why this is needed?
//&& state.upgrade // this should be removed once the assertion work
&& state.get_shared_count()==1)
{
state.unlock_upgrade();
state.lock();
state.assert_locked();
return true;
}
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)
{
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
boost::this_thread::disable_interruption do_not_disturb;
#endif
boost::unique_lock<boost::mutex> lk(state_change);
state.assert_lock_upgraded();
if (//state.exclusive // this should be removed once the assertion work
state.exclusive_waiting_blocked // Fixme: is this needed?
//|| ! state.upgrade // this should be removed once the assertion work
|| state.get_shared_count() != 1)
{
for (;;)
{
//cv_status status = shared_cond.wait_until(lk,abs_time);
cv_status status = upgrade_cond.wait_until(lk,abs_time);
if (//!state.exclusive // this should be removed once the assertion work
! state.exclusive_waiting_blocked // Fixme: is this needed?
//&& ! state.upgrade // this should be removed once the assertion work
&& state.get_shared_count() == 1)
break;
if(status == cv_status::timeout)
return false;
}
}
state.unlock_upgrade();
state.lock();
return true;
}
#endif
// Shared <-> Exclusive
void unlock_and_lock_shared()
{
boost::unique_lock<boost::mutex> lk(state_change);
state.assert_locked();
state.unlock();
state.lock_shared();
release_waiters();
}
#ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
bool try_unlock_shared_and_lock()
{
boost::unique_lock<boost::mutex> lk(state_change);
state.assert_lock_shared();
if( //!state.exclusive // this should be removed once the assertion work
! state.exclusive_waiting_blocked // Fixme: why this is needed?
//&& ! state.upgrade // Fixme: why this is needed if state.get_shared_count()==1?
&& state.get_shared_count()==1)
{
state.unlock_shared();
state.lock();
return true;
}
return false;
}
#ifdef BOOST_THREAD_USES_CHRONO
template <class Rep, class Period>
bool
try_unlock_shared_and_lock_for(
const chrono::duration<Rep, Period>& rel_time)
{
return try_unlock_shared_and_lock_until(
chrono::steady_clock::now() + rel_time);
}
template <class Clock, class Duration>
bool
try_unlock_shared_and_lock_until(
const chrono::time_point<Clock, Duration>& abs_time)
{
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
boost::this_thread::disable_interruption do_not_disturb;
#endif
boost::unique_lock<boost::mutex> lk(state_change);
state.assert_lock_shared();
if ( // !state.exclusive // this should be removed once the assertion work
state.exclusive_waiting_blocked // Fixme: is this needed?
//|| state.upgrade // Fixme: why this is needed if state.get_shared_count()==1?
|| state.get_shared_count() != 1)
{
for (;;)
{
cv_status status = shared_cond.wait_until(lk,abs_time);
if ( //! state.exclusive // this should be removed once the assertion work
! state.exclusive_waiting_blocked // Fixme: is this needed?
//&& ! state.upgrade
&& state.get_shared_count() == 1)
break;
if(status == cv_status::timeout)
return false;
}
}
state.unlock_shared();
state.lock();
state.upgrade=false; // Is this absolutely needed?
state.exclusive_waiting_blocked=false; // Is this absolutely needed?
return true;
}
#endif
#endif
// Shared <-> Upgrade
void unlock_upgrade_and_lock_shared()
{
boost::unique_lock<boost::mutex> lk(state_change);
state.assert_lock_upgraded();
//state.unlock_upgrade();
//state.lock_shared(); // less efficient
state.upgrade=false;
state.exclusive_waiting_blocked=false; // Is this absolutely needed?
release_waiters();
}
#ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
bool try_unlock_shared_and_lock_upgrade()
{
boost::unique_lock<boost::mutex> lk(state_change);
state.assert_lock_shared();
if( //! state.exclusive // this should be removed once the assertion work
! state.exclusive_waiting_blocked // Fixme: is this needed?
&& ! state.upgrade
)
{
state.upgrade=true;
return true;
}
return false;
}
#ifdef BOOST_THREAD_USES_CHRONO
template <class Rep, class Period>
bool
try_unlock_shared_and_lock_upgrade_for(
const chrono::duration<Rep, Period>& rel_time)
{
return try_unlock_shared_and_lock_upgrade_until(
chrono::steady_clock::now() + rel_time);
}
template <class Clock, class Duration>
bool
try_unlock_shared_and_lock_upgrade_until(
const chrono::time_point<Clock, Duration>& abs_time)
{
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
boost::this_thread::disable_interruption do_not_disturb;
#endif
boost::unique_lock<boost::mutex> lk(state_change);
state.assert_lock_shared();
if( //state.exclusive // this should be removed once the assertion work
state.exclusive_waiting_blocked // Fixme: is this needed?
|| state.upgrade
)
{
for (;;)
{
cv_status status = exclusive_cond.wait_until(lk,abs_time);
if( //! state.exclusive // this should be removed once the assertion work
! state.exclusive_waiting_blocked // Fixme: is this needed?
&& ! state.upgrade
)
break;
if(status == cv_status::timeout)
return false;
}
}
//state.unlock_shared();
//state.lock_upgrade(); // less efficient
state.upgrade=true;
return true;
}
#endif
#endif
};
typedef shared_mutex upgrade_mutex;
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -12,10 +12,12 @@
#include <boost/thread/lock_types.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/pthread/condition_variable_fwd.hpp>
#include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/assert.hpp>
#include <boost/thread/detail/platform_time.hpp>
#ifdef BOOST_THREAD_USES_CHRONO
#include <boost/chrono/system_clocks.hpp>
#endif
@@ -50,8 +52,12 @@ namespace boost
// stack
void set_stack_size(std::size_t size) BOOST_NOEXCEPT {
if (size==0) return;
#ifdef BOOST_THREAD_USES_GETPAGESIZE
std::size_t page_size = getpagesize();
#ifdef PTHREAD_STACK_MIN
#else
std::size_t page_size = ::sysconf( _SC_PAGESIZE);
#endif
#if PTHREAD_STACK_MIN > 0
if (size<PTHREAD_STACK_MIN) size=PTHREAD_STACK_MIN;
#endif
size = ((size+page_size-1)/page_size)*page_size;
@@ -88,12 +94,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_)
{}
};
@@ -107,8 +116,6 @@ namespace boost
pthread_t thread_handle;
boost::mutex data_mutex;
boost::condition_variable done_condition;
boost::mutex sleep_mutex;
boost::condition_variable sleep_condition;
bool done;
bool join_started;
bool joined;
@@ -127,9 +134,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.
@@ -145,8 +153,10 @@ namespace boost
cond_mutex(0),
current_cond(0),
//#endif
notify(),
async_states_()
notify()
//#ifndef BOOST_NO_EXCEPTIONS
, async_states_()
//#endif
//#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
, interrupt_enabled(true)
, interrupt_requested(false)
@@ -162,11 +172,12 @@ 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();
@@ -177,6 +188,7 @@ namespace boost
thread_data_base* const thread_info;
pthread_mutex_t* m;
bool set;
bool done;
void check_for_interruption()
{
@@ -193,7 +205,7 @@ namespace boost
public:
explicit interruption_checker(pthread_mutex_t* cond_mutex,pthread_cond_t* cond):
thread_info(detail::get_current_thread_data()),m(cond_mutex),
set(thread_info && thread_info->interrupt_enabled)
set(thread_info && thread_info->interrupt_enabled), done(false)
{
if(set)
{
@@ -201,26 +213,34 @@ namespace boost
check_for_interruption();
thread_info->cond_mutex=cond_mutex;
thread_info->current_cond=cond;
BOOST_VERIFY(!pthread_mutex_lock(m));
BOOST_VERIFY(!posix::pthread_mutex_lock(m));
}
else
{
BOOST_VERIFY(!pthread_mutex_lock(m));
BOOST_VERIFY(!posix::pthread_mutex_lock(m));
}
}
~interruption_checker()
void unlock_if_locked()
{
if(set)
if ( ! done) {
if (set)
{
BOOST_VERIFY(!pthread_mutex_unlock(m));
BOOST_VERIFY(!posix::pthread_mutex_unlock(m));
lock_guard<mutex> guard(thread_info->data_mutex);
thread_info->cond_mutex=NULL;
thread_info->current_cond=NULL;
}
else
{
BOOST_VERIFY(!pthread_mutex_unlock(m));
BOOST_VERIFY(!posix::pthread_mutex_unlock(m));
}
done = true;
}
}
~interruption_checker() BOOST_NOEXCEPT_IF(false)
{
unlock_if_locked();
}
};
#endif
@@ -228,45 +248,15 @@ namespace boost
namespace this_thread
{
void BOOST_THREAD_DECL yield() BOOST_NOEXCEPT;
namespace hidden
{
void BOOST_THREAD_DECL sleep_for(const timespec& ts);
void BOOST_THREAD_DECL sleep_until(const timespec& ts);
}
#ifdef BOOST_THREAD_USES_CHRONO
#ifdef BOOST_THREAD_SLEEP_FOR_IS_STEADY
inline
void BOOST_SYMBOL_VISIBLE sleep_for(const chrono::nanoseconds& ns)
{
return boost::this_thread::hidden::sleep_for(boost::detail::to_timespec(ns));
}
#endif
#endif // BOOST_THREAD_USES_CHRONO
namespace no_interruption_point
{
namespace hidden
inline bool always_false()
{
void BOOST_THREAD_DECL sleep_for(const timespec& ts);
void BOOST_THREAD_DECL sleep_until(const timespec& ts);
return false;
}
#ifdef BOOST_THREAD_USES_CHRONO
#ifdef BOOST_THREAD_SLEEP_FOR_IS_STEADY
inline
void BOOST_SYMBOL_VISIBLE sleep_for(const chrono::nanoseconds& ns)
{
return boost::this_thread::no_interruption_point::hidden::sleep_for(boost::detail::to_timespec(ns));
}
#endif
#endif // BOOST_THREAD_USES_CHRONO
} // no_interruption_point
void BOOST_THREAD_DECL yield() BOOST_NOEXCEPT;
}
#if defined BOOST_THREAD_USES_DATETIME
#ifdef __DECXXX
@@ -275,15 +265,141 @@ namespace boost
#endif
inline void sleep(system_time const& abs_time)
{
return boost::this_thread::hidden::sleep_until(boost::detail::to_timespec(abs_time));
mutex mx;
unique_lock<mutex> lock(mx);
condition_variable cond;
cond.timed_wait(lock, abs_time, hidden::always_false);
}
template<typename TimeDuration>
inline BOOST_SYMBOL_VISIBLE void sleep(TimeDuration const& rel_time)
void sleep(TimeDuration const& rel_time)
{
this_thread::sleep(get_system_time()+rel_time);
mutex mx;
unique_lock<mutex> lock(mx);
condition_variable cond;
cond.timed_wait(lock, rel_time, hidden::always_false);
}
#endif // BOOST_THREAD_USES_DATETIME
#endif
#ifdef BOOST_THREAD_USES_CHRONO
template <class Clock, class Duration>
void sleep_until(const chrono::time_point<Clock, Duration>& t)
{
mutex mut;
unique_lock<mutex> lk(mut);
condition_variable cv;
cv.wait_until(lk, t, hidden::always_false);
}
template <class Rep, class Period>
void sleep_for(const chrono::duration<Rep, Period>& d)
{
mutex mut;
unique_lock<mutex> lk(mut);
condition_variable cv;
cv.wait_for(lk, d, hidden::always_false);
}
#endif
namespace no_interruption_point
{
#if defined BOOST_THREAD_SLEEP_FOR_IS_STEADY
// Use pthread_delay_np or nanosleep when available
// because they do not provide an interruption point.
namespace hidden
{
void BOOST_THREAD_DECL sleep_for_internal(const detail::platform_duration& ts);
}
#if defined BOOST_THREAD_USES_DATETIME
#ifdef __DECXXX
/// Workaround of DECCXX issue of incorrect template substitution
template<>
#endif
inline 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));
hidden::sleep_for_internal(d);
d = ts - detail::real_platform_clock::now();
}
}
template<typename TimeDuration>
void sleep(TimeDuration const& rel_time)
{
hidden::sleep_for_internal(detail::platform_duration(rel_time));
}
#endif
#ifdef BOOST_THREAD_USES_CHRONO
template <class Rep, class Period>
void sleep_for(const chrono::duration<Rep, Period>& d)
{
hidden::sleep_for_internal(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)));
hidden::sleep_for_internal(detail::platform_duration(d));
d = t - Clock::now();
}
}
#endif
#else // BOOST_THREAD_SLEEP_FOR_IS_STEADY
// When pthread_delay_np and nanosleep are not available,
// fall back to using the interruptible sleep functions.
#if defined BOOST_THREAD_USES_DATETIME
#ifdef __DECXXX
/// Workaround of DECCXX issue of incorrect template substitution
template<>
#endif
inline void sleep(system_time const& abs_time)
{
this_thread::sleep(abs_time);
}
template<typename TimeDuration>
void sleep(TimeDuration const& rel_time)
{
this_thread::sleep(rel_time);
}
#endif
#ifdef BOOST_THREAD_USES_CHRONO
template <class Clock, class Duration>
void sleep_until(const chrono::time_point<Clock, Duration>& t)
{
this_thread::sleep_until(t);
}
template <class Rep, class Period>
void sleep_for(const chrono::duration<Rep, Period>& d)
{
this_thread::sleep_for(d);
}
#endif
#endif // BOOST_THREAD_SLEEP_FOR_IS_STEADY
} // no_interruption_point
} // this_thread
}

View File

@@ -16,8 +16,13 @@ namespace boost
{
return new T();
}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) && ! defined (BOOST_NO_CXX11_RVALUE_REFERENCES)
template<typename T,typename... Args>
inline T* heap_new(Args&&... args)
{
return new T(static_cast<Args&&>(args)...);
}
#elif ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
template<typename T,typename A1>
inline T* heap_new(A1&& a1)
{
@@ -61,6 +66,31 @@ namespace boost
{
return new T(a1,a2,a3,a4);
}
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)
{
return new T(a1,a2,a3,a4,a5);
}
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)
{
return new T(a1,a2,a3,a4,a5,a6);
}
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)
{
return new T(a1,a2,a3,a4,a5,a6,a7);
}
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)
{
return new T(a1,a2,a3,a4,a5,a6,a7,a8);
}
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)
{
return new T(a1,a2,a3,a4,a5,a6,a7,a8,a9);
}
template<typename T,typename A1>
inline T* heap_new(A1 const& a1)

View File

@@ -1,149 +0,0 @@
#ifndef BOOST_THREAD_PTHREAD_TIMESPEC_HPP
#define BOOST_THREAD_PTHREAD_TIMESPEC_HPP
// (C) Copyright 2007-8 Anthony Williams
// (C) Copyright 2012 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/thread/detail/config.hpp>
#include <boost/thread/thread_time.hpp>
#if defined BOOST_THREAD_USES_DATETIME
#include <boost/date_time/posix_time/conversion.hpp>
#endif
#include <pthread.h>
#ifndef _WIN32
#include <unistd.h>
#endif
#ifdef BOOST_THREAD_USES_CHRONO
#include <boost/chrono/duration.hpp>
#endif
#if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
# define BOOST_THREAD_TIMESPEC_MAC_API
#include <sys/time.h> //for gettimeofday and timeval
#else
#include <time.h> // for clock_gettime
#endif
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace detail
{
#if defined BOOST_THREAD_USES_DATETIME
inline struct timespec to_timespec(boost::system_time const& abs_time)
{
struct timespec timeout = { 0,0};
boost::posix_time::time_duration const time_since_epoch=abs_time-boost::posix_time::from_time_t(0);
timeout.tv_sec=time_since_epoch.total_seconds();
timeout.tv_nsec=(long)(time_since_epoch.fractional_seconds()*(1000000000l/time_since_epoch.ticks_per_second()));
return timeout;
}
#endif
#if defined BOOST_THREAD_USES_CHRONO
inline timespec to_timespec(chrono::nanoseconds const& ns)
{
struct timespec ts;
ts.tv_sec = static_cast<long>(chrono::duration_cast<chrono::seconds>(ns).count());
ts.tv_nsec = static_cast<long>((ns - chrono::duration_cast<chrono::seconds>(ns)).count());
return ts;
}
#endif
inline timespec to_timespec(boost::intmax_t const& ns)
{
boost::intmax_t s = ns / 1000000000l;
struct timespec ts;
ts.tv_sec = static_cast<long> (s);
ts.tv_nsec = static_cast<long> (ns - s * 1000000000l);
return ts;
}
inline boost::intmax_t to_nanoseconds_int_max(timespec const& ts)
{
return static_cast<boost::intmax_t>(ts.tv_sec) * 1000000000l + ts.tv_nsec;
}
inline bool timespec_ge_zero(timespec const& ts)
{
return (ts.tv_sec >= 0) || (ts.tv_nsec >= 0);
}
inline timespec timespec_now()
{
timespec ts;
#if defined CLOCK_MONOTONIC && defined BOOST_THREAD_USEFIXES_TIMESPEC
if ( ::clock_gettime( CLOCK_MONOTONIC, &ts ) )
{
ts.tv_sec = 0;
ts.tv_nsec = 0;
BOOST_ASSERT(0 && "Boost::Thread - Internal Error");
}
#elif defined(BOOST_THREAD_TIMESPEC_MAC_API)
timeval tv;
::gettimeofday(&tv, 0);
ts.tv_sec = tv.tv_sec;
ts.tv_nsec = tv.tv_usec * 1000;
#else
if ( ::clock_gettime( CLOCK_REALTIME, &ts ) )
{
ts.tv_sec = 0;
ts.tv_nsec = 0;
BOOST_ASSERT(0 && "Boost::Thread - Internal Error");
}
#endif
return ts;
}
inline timespec timespec_now_realtime()
{
timespec ts;
#if defined(BOOST_THREAD_TIMESPEC_MAC_API)
timeval tv;
::gettimeofday(&tv, 0);
ts.tv_sec = tv.tv_sec;
ts.tv_nsec = tv.tv_usec * 1000;
#else
if ( ::clock_gettime( CLOCK_REALTIME, &ts ) )
{
ts.tv_sec = 0;
ts.tv_nsec = 0;
BOOST_ASSERT(0 && "Boost::Thread - Internal Error");
}
#endif
return ts;
}
inline timespec timespec_zero()
{
timespec ts;
ts.tv_sec = 0;
ts.tv_nsec = 0;
return ts;
}
inline timespec timespec_plus(timespec const& lhs, timespec const& rhs)
{
return to_timespec(to_nanoseconds_int_max(lhs) + to_nanoseconds_int_max(rhs));
}
inline timespec timespec_minus(timespec const& lhs, timespec const& rhs)
{
return to_timespec(to_nanoseconds_int_max(lhs) - to_nanoseconds_int_max(rhs));
}
inline bool timespec_gt(timespec const& lhs, timespec const& rhs)
{
return to_nanoseconds_int_max(lhs) > to_nanoseconds_int_max(rhs);
}
inline bool timespec_ge(timespec const& lhs, timespec const& rhs)
{
return to_nanoseconds_int_max(lhs) >= to_nanoseconds_int_max(rhs);
}
}
}
#include <boost/config/abi_suffix.hpp>
#endif