update boost on linux

This commit is contained in:
Bassem Girgis
2019-08-10 16:06:25 -05:00
parent 76ad52be58
commit 861b918727
5363 changed files with 483306 additions and 116507 deletions

View File

@@ -3,7 +3,7 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Vicente J. Botet Escriba 2013-2014. Distributed under the Boost
// (C) Copyright Vicente J. Botet Escriba 2013-2017. 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)
//
@@ -11,15 +11,15 @@
//
//////////////////////////////////////////////////////////////////////////////
#include <boost/bind.hpp>
#include <boost/thread/detail/config.hpp>
#include <boost/thread/condition_variable.hpp>
#include <boost/thread/detail/move.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/concurrent_queues/queue_op_status.hpp>
#include <boost/chrono/duration.hpp>
#include <boost/chrono/time_point.hpp>
#include <boost/chrono/system_clocks.hpp>
#include <boost/throw_exception.hpp>
#include <boost/config/abi_prefix.hpp>
@@ -40,10 +40,6 @@ namespace detail
typedef typename Queue::size_type size_type;
typedef queue_op_status op_status;
typedef typename chrono::steady_clock clock;
typedef typename clock::duration duration;
typedef typename clock::time_point time_point;
// Constructors/Assignment/Destructors
BOOST_THREAD_NO_COPYABLE(sync_deque_base)
inline sync_deque_base();
@@ -90,9 +86,13 @@ namespace detail
inline void throw_if_closed(unique_lock<mutex>&);
inline void throw_if_closed(lock_guard<mutex>&);
inline void wait_until_not_empty(unique_lock<mutex>& lk);
inline bool not_empty_or_closed(unique_lock<mutex>& ) const;
inline bool wait_until_not_empty_or_closed(unique_lock<mutex>& lk);
inline queue_op_status wait_until_not_empty_until(unique_lock<mutex>& lk, time_point const&);
template <class WClock, class Duration>
queue_op_status wait_until_not_empty_or_closed_until(unique_lock<mutex>& lk, chrono::time_point<WClock,Duration> const&tp);
template <class WClock, class Duration>
queue_op_status wait_until_closed_until(unique_lock<mutex>& lk, chrono::time_point<WClock,Duration> const&tp);
inline void notify_not_empty_if_needed(unique_lock<mutex>& )
{
@@ -181,38 +181,38 @@ namespace detail
}
template <class ValueType, class Queue>
void sync_deque_base<ValueType, Queue>::wait_until_not_empty(unique_lock<mutex>& lk)
bool sync_deque_base<ValueType, Queue>::not_empty_or_closed(unique_lock<mutex>& ) const
{
for (;;)
{
if (! empty(lk)) break;
throw_if_closed(lk);
not_empty_.wait(lk);
}
return ! data_.empty() || closed_;
}
template <class ValueType, class Queue>
bool sync_deque_base<ValueType, Queue>::wait_until_not_empty_or_closed(unique_lock<mutex>& lk)
{
for (;;)
{
if (! empty(lk)) break;
if (closed(lk)) return true;
not_empty_.wait(lk);
}
return false;
not_empty_.wait(lk, boost::bind(&sync_deque_base<ValueType, Queue>::not_empty_or_closed, boost::ref(*this), boost::ref(lk)));
if (! empty(lk)) return false; // success
return true; // closed
}
template <class ValueType, class Queue>
queue_op_status sync_deque_base<ValueType, Queue>::wait_until_not_empty_until(unique_lock<mutex>& lk, time_point const&tp)
template <class WClock, class Duration>
queue_op_status sync_deque_base<ValueType, Queue>::wait_until_not_empty_or_closed_until(unique_lock<mutex>& lk, chrono::time_point<WClock,Duration> const&tp)
{
for (;;)
{
if (! empty(lk)) return queue_op_status::success;
throw_if_closed(lk);
if (not_empty_.wait_until(lk, tp) == cv_status::timeout ) return queue_op_status::timeout;
}
if (! not_empty_.wait_until(lk, tp, boost::bind(&sync_deque_base<ValueType, Queue>::not_empty_or_closed, boost::ref(*this), boost::ref(lk))))
return queue_op_status::timeout;
if (! empty(lk)) return queue_op_status::success;
return queue_op_status::closed;
}
template <class ValueType, class Queue>
template <class WClock, class Duration>
queue_op_status sync_deque_base<ValueType, Queue>::wait_until_closed_until(unique_lock<mutex>& lk, chrono::time_point<WClock,Duration> const&tp)
{
bool (sync_queue_base<ValueType, Queue>::*closed_function_ptr)(unique_lock<mutex>&) const = &sync_queue_base<ValueType, Queue>::closed;
if (! not_empty_.wait_until(lk, tp, boost::bind(closed_function_ptr, boost::ref(*this), boost::ref(lk))))
return queue_op_status::timeout;
return queue_op_status::closed;
}
} // detail
} // concurrent

View File

@@ -3,7 +3,7 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Vicente J. Botet Escriba 2013-2014. Distributed under the Boost
// (C) Copyright Vicente J. Botet Escriba 2013-2017. 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)
//
@@ -11,15 +11,15 @@
//
//////////////////////////////////////////////////////////////////////////////
#include <boost/bind.hpp>
#include <boost/thread/detail/config.hpp>
#include <boost/thread/condition_variable.hpp>
#include <boost/thread/detail/move.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/concurrent_queues/queue_op_status.hpp>
#include <boost/chrono/duration.hpp>
#include <boost/chrono/time_point.hpp>
#include <boost/chrono/system_clocks.hpp>
#include <boost/throw_exception.hpp>
#include <boost/config/abi_prefix.hpp>
@@ -40,10 +40,6 @@ namespace detail
typedef typename Queue::size_type size_type;
typedef queue_op_status op_status;
typedef typename chrono::steady_clock clock;
typedef typename clock::duration duration;
typedef typename clock::time_point time_point;
// Constructors/Assignment/Destructors
BOOST_THREAD_NO_COPYABLE(sync_queue_base)
inline sync_queue_base();
@@ -90,9 +86,13 @@ namespace detail
inline void throw_if_closed(unique_lock<mutex>&);
inline void throw_if_closed(lock_guard<mutex>&);
inline void wait_until_not_empty(unique_lock<mutex>& lk);
inline bool not_empty_or_closed(unique_lock<mutex>& ) const;
inline bool wait_until_not_empty_or_closed(unique_lock<mutex>& lk);
inline queue_op_status wait_until_not_empty_until(unique_lock<mutex>& lk, time_point const&);
template <class WClock, class Duration>
queue_op_status wait_until_not_empty_or_closed_until(unique_lock<mutex>& lk, chrono::time_point<WClock,Duration> const&tp);
template <class WClock, class Duration>
queue_op_status wait_until_closed_until(unique_lock<mutex>& lk, chrono::time_point<WClock,Duration> const&tp);
inline void notify_not_empty_if_needed(unique_lock<mutex>& )
{
@@ -181,38 +181,38 @@ namespace detail
}
template <class ValueType, class Queue>
void sync_queue_base<ValueType, Queue>::wait_until_not_empty(unique_lock<mutex>& lk)
bool sync_queue_base<ValueType, Queue>::not_empty_or_closed(unique_lock<mutex>& ) const
{
for (;;)
{
if (! empty(lk)) break;
throw_if_closed(lk);
not_empty_.wait(lk);
}
return ! data_.empty() || closed_;
}
template <class ValueType, class Queue>
bool sync_queue_base<ValueType, Queue>::wait_until_not_empty_or_closed(unique_lock<mutex>& lk)
{
for (;;)
{
if (! empty(lk)) break;
if (closed(lk)) return true;
not_empty_.wait(lk);
}
return false;
not_empty_.wait(lk, boost::bind(&sync_queue_base<ValueType, Queue>::not_empty_or_closed, boost::ref(*this), boost::ref(lk)));
if (! empty(lk)) return false; // success
return true; // closed
}
template <class ValueType, class Queue>
queue_op_status sync_queue_base<ValueType, Queue>::wait_until_not_empty_until(unique_lock<mutex>& lk, time_point const&tp)
template <class WClock, class Duration>
queue_op_status sync_queue_base<ValueType, Queue>::wait_until_not_empty_or_closed_until(unique_lock<mutex>& lk, chrono::time_point<WClock,Duration> const&tp)
{
for (;;)
{
if (! empty(lk)) return queue_op_status::success;
throw_if_closed(lk);
if (not_empty_.wait_until(lk, tp) == cv_status::timeout ) return queue_op_status::timeout;
}
if (! not_empty_.wait_until(lk, tp, boost::bind(&sync_queue_base<ValueType, Queue>::not_empty_or_closed, boost::ref(*this), boost::ref(lk))))
return queue_op_status::timeout;
if (! empty(lk)) return queue_op_status::success;
return queue_op_status::closed;
}
template <class ValueType, class Queue>
template <class WClock, class Duration>
queue_op_status sync_queue_base<ValueType, Queue>::wait_until_closed_until(unique_lock<mutex>& lk, chrono::time_point<WClock,Duration> const&tp)
{
bool (sync_queue_base<ValueType, Queue>::*closed_function_ptr)(unique_lock<mutex>&) const = &sync_queue_base<ValueType, Queue>::closed;
if (! not_empty_.wait_until(lk, tp, boost::bind(closed_function_ptr, boost::ref(*this), boost::ref(lk))))
return queue_op_status::timeout;
return queue_op_status::closed;
}
} // detail
} // concurrent

View File

@@ -11,6 +11,8 @@
//
//////////////////////////////////////////////////////////////////////////////
#include <exception>
#include <boost/core/scoped_enum.hpp>
#include <boost/thread/detail/config.hpp>
#include <boost/thread/detail/move.hpp>
@@ -25,7 +27,7 @@ namespace concurrent
{ success = 0, empty, full, closed, busy, timeout, not_ready }
BOOST_SCOPED_ENUM_DECLARE_END(queue_op_status)
struct sync_queue_is_closed : std::exception
struct BOOST_SYMBOL_VISIBLE sync_queue_is_closed : std::exception
{
};

View File

@@ -127,7 +127,7 @@ namespace concurrent
inline size_type size(lock_guard<mutex>& lk) const BOOST_NOEXCEPT
{
if (full(lk)) return capacity(lk);
return ((out_+capacity(lk)-in_) % capacity(lk));
return ((in_+capacity(lk)-out_) % capacity(lk));
}
inline void throw_if_closed(unique_lock<mutex>&);
@@ -484,7 +484,9 @@ namespace concurrent
queue_op_status sync_bounded_queue<ValueType>::wait_pull_front(ValueType& elem, unique_lock<mutex>& lk)
{
if (empty(lk) && closed(lk)) {return queue_op_status::closed;}
wait_until_not_empty(lk);
bool is_closed = false;
wait_until_not_empty(lk, is_closed);
if (is_closed) {return queue_op_status::closed;}
pull_front(elem, lk);
return queue_op_status::success;
}

View File

@@ -149,11 +149,7 @@ namespace concurrent
template <class ValueType, class Container>
queue_op_status sync_deque<ValueType, Container>::wait_pull_front(ValueType& elem, unique_lock<mutex>& lk)
{
if (super::empty(lk))
{
if (super::closed(lk)) return queue_op_status::closed;
}
bool has_been_closed = super::wait_until_not_empty_or_closed(lk);
const bool has_been_closed = super::wait_until_not_empty_or_closed(lk);
if (has_been_closed) return queue_op_status::closed;
pull_front(elem, lk);
return queue_op_status::success;
@@ -188,7 +184,8 @@ namespace concurrent
void sync_deque<ValueType, Container>::pull_front(ValueType& elem)
{
unique_lock<mutex> lk(super::mtx_);
super::wait_until_not_empty(lk);
const bool has_been_closed = super::wait_until_not_empty_or_closed(lk);
if (has_been_closed) super::throw_if_closed(lk);
pull_front(elem, lk);
}
@@ -197,7 +194,8 @@ namespace concurrent
ValueType sync_deque<ValueType, Container>::pull_front()
{
unique_lock<mutex> lk(super::mtx_);
super::wait_until_not_empty(lk);
const bool has_been_closed = super::wait_until_not_empty_or_closed(lk);
if (has_been_closed) super::throw_if_closed(lk);
return pull_front(lk);
}

View File

@@ -1,5 +1,5 @@
// Copyright (C) 2014 Ian Forbed
// Copyright (C) 2014 Vicente J. Botet Escriba
// Copyright (C) 2014-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)
@@ -82,7 +82,7 @@ namespace detail {
return boost::move(result);
}
Type const& top()
Type const& top() const
{
return _elements.front();
}
@@ -130,8 +130,10 @@ namespace concurrent
void pull(ValueType&);
queue_op_status pull_until(const clock::time_point&, ValueType&);
queue_op_status pull_for(const clock::duration&, ValueType&);
template <class WClock, class Duration>
queue_op_status pull_until(const chrono::time_point<WClock,Duration>&, ValueType&);
template <class Rep, class Period>
queue_op_status pull_for(const chrono::duration<Rep,Period>&, ValueType&);
queue_op_status try_pull(ValueType& elem);
queue_op_status wait_pull(ValueType& elem);
@@ -247,7 +249,8 @@ namespace concurrent
T sync_priority_queue<T,Container,Cmp>::pull()
{
unique_lock<mutex> lk(super::mtx_);
super::wait_until_not_empty(lk);
const bool has_been_closed = super::wait_until_not_empty_or_closed(lk);
if (has_been_closed) super::throw_if_closed(lk);
return pull(lk);
}
@@ -267,28 +270,30 @@ namespace concurrent
void sync_priority_queue<T,Container,Cmp>::pull(T& elem)
{
unique_lock<mutex> lk(super::mtx_);
super::wait_until_not_empty(lk);
const bool has_been_closed = super::wait_until_not_empty_or_closed(lk);
if (has_been_closed) super::throw_if_closed(lk);
pull(lk, elem);
}
//////////////////////
template <class T, class Cont,class Cmp>
template <class WClock, class Duration>
queue_op_status
sync_priority_queue<T,Cont,Cmp>::pull_until(const clock::time_point& tp, T& elem)
sync_priority_queue<T,Cont,Cmp>::pull_until(const chrono::time_point<WClock,Duration>& tp, T& elem)
{
unique_lock<mutex> lk(super::mtx_);
if (queue_op_status::timeout == super::wait_until_not_empty_until(lk, tp))
return queue_op_status::timeout;
pull(lk, elem);
return queue_op_status::success;
const queue_op_status rc = super::wait_until_not_empty_or_closed_until(lk, tp);
if (rc == queue_op_status::success) pull(lk, elem);
return rc;
}
//////////////////////
template <class T, class Cont,class Cmp>
template <class Rep, class Period>
queue_op_status
sync_priority_queue<T,Cont,Cmp>::pull_for(const clock::duration& dura, T& elem)
sync_priority_queue<T,Cont,Cmp>::pull_for(const chrono::duration<Rep,Period>& dura, T& elem)
{
return pull_until(clock::now() + dura, elem);
return pull_until(chrono::steady_clock::now() + dura, elem);
}
//////////////////////
@@ -330,11 +335,7 @@ namespace concurrent
template <class T,class Container, class Cmp>
queue_op_status sync_priority_queue<T,Container,Cmp>::wait_pull(unique_lock<mutex>& lk, T& elem)
{
if (super::empty(lk))
{
if (super::closed(lk)) return queue_op_status::closed;
}
bool has_been_closed = super::wait_until_not_empty_or_closed(lk);
const bool has_been_closed = super::wait_until_not_empty_or_closed(lk);
if (has_been_closed) return queue_op_status::closed;
pull(lk, elem);
return queue_op_status::success;
@@ -348,7 +349,6 @@ namespace concurrent
}
//////////////////////
template <class T,class Container, class Cmp>
queue_op_status sync_priority_queue<T,Container,Cmp>::nonblocking_pull(T& elem)
{

View File

@@ -10,7 +10,6 @@
// See http://www.boost.org/libs/thread for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#include <iostream>
#include <boost/thread/detail/config.hpp>
#include <boost/thread/concurrent_queues/detail/sync_queue_base.hpp>
@@ -51,7 +50,6 @@ namespace concurrent
inline ~sync_queue();
// Modifiers
inline void push(const value_type& x);
inline queue_op_status try_push(const value_type& x);
inline queue_op_status nonblocking_push(const value_type& x);
@@ -151,19 +149,9 @@ namespace concurrent
template <class ValueType, class Container>
queue_op_status sync_queue<ValueType, Container>::wait_pull(ValueType& elem, unique_lock<mutex>& lk)
{
//std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
if (super::empty(lk))
{
//std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
if (super::closed(lk)) return queue_op_status::closed;
}
//std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
bool has_been_closed = super::wait_until_not_empty_or_closed(lk);
//std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
const bool has_been_closed = super::wait_until_not_empty_or_closed(lk);
if (has_been_closed) return queue_op_status::closed;
//std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
pull(elem, lk);
//std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
return queue_op_status::success;
}
@@ -196,7 +184,8 @@ namespace concurrent
void sync_queue<ValueType, Container>::pull(ValueType& elem)
{
unique_lock<mutex> lk(super::mtx_);
super::wait_until_not_empty(lk);
const bool has_been_closed = super::wait_until_not_empty_or_closed(lk);
if (has_been_closed) super::throw_if_closed(lk);
pull(elem, lk);
}
@@ -205,7 +194,8 @@ namespace concurrent
ValueType sync_queue<ValueType, Container>::pull()
{
unique_lock<mutex> lk(super::mtx_);
super::wait_until_not_empty(lk);
const bool has_been_closed = super::wait_until_not_empty_or_closed(lk);
if (has_been_closed) super::throw_if_closed(lk);
return pull(lk);
}

View File

@@ -1,5 +1,5 @@
// Copyright (C) 2014 Ian Forbed
// Copyright (C) 2014 Vicente J. Botet Escriba
// Copyright (C) 2014-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)
@@ -24,12 +24,13 @@ namespace concurrent
{
namespace detail
{
template <class T, class Clock = chrono::steady_clock>
// fixme: shouldn't the timepoint be configurable
template <class T, class Clock = chrono::steady_clock, class TimePoint=typename Clock::time_point>
struct scheduled_type
{
typedef T value_type;
typedef Clock clock;
typedef typename clock::time_point time_point;
typedef TimePoint time_point;
T data;
time_point time;
@@ -52,12 +53,7 @@ namespace detail
return *this;
}
bool time_not_reached() const
{
return time > clock::now();
}
bool operator <(const scheduled_type<T> other) const
bool operator <(const scheduled_type & other) const
{
return this->time > other.time;
}
@@ -65,11 +61,11 @@ namespace detail
} //end detail namespace
template <class T, class Clock = chrono::steady_clock>
template <class T, class Clock = chrono::steady_clock, class TimePoint=typename Clock::time_point>
class sync_timed_queue
: private sync_priority_queue<detail::scheduled_type<T, Clock> >
: private sync_priority_queue<detail::scheduled_type<T, Clock, TimePoint> >
{
typedef detail::scheduled_type<T, Clock> stype;
typedef detail::scheduled_type<T, Clock, TimePoint> stype;
typedef sync_priority_queue<stype> super;
public:
typedef T value_type;
@@ -92,8 +88,8 @@ namespace detail
T pull();
void pull(T& elem);
template <class Duration>
queue_op_status pull_until(chrono::time_point<clock,Duration> const& tp, T& elem);
template <class WClock, class Duration>
queue_op_status pull_until(chrono::time_point<WClock,Duration> const& tp, T& elem);
template <class Rep, class Period>
queue_op_status pull_for(chrono::duration<Rep,Period> const& dura, T& elem);
@@ -122,6 +118,13 @@ namespace detail
queue_op_status try_push(BOOST_THREAD_RV_REF(T) elem, chrono::duration<Rep,Period> const& dura);
private:
inline bool not_empty_and_time_reached(unique_lock<mutex>& lk) const;
inline bool not_empty_and_time_reached(lock_guard<mutex>& lk) const;
bool wait_to_pull(unique_lock<mutex>&);
template <class WClock, class Duration>
queue_op_status wait_to_pull_until(unique_lock<mutex>&, chrono::time_point<WClock, Duration> const& tp);
T pull(unique_lock<mutex>&);
T pull(lock_guard<mutex>&);
@@ -133,15 +136,6 @@ namespace detail
queue_op_status wait_pull(unique_lock<mutex>& lk, T& elem);
bool wait_until_not_empty_time_reached_or_closed(unique_lock<mutex>&);
T pull_when_time_reached(unique_lock<mutex>&);
template <class Duration>
queue_op_status pull_when_time_reached_until(unique_lock<mutex>&, chrono::time_point<clock,Duration> const& tp, T& elem);
bool time_not_reached(unique_lock<mutex>&);
bool time_not_reached(lock_guard<mutex>&);
bool empty_or_time_not_reached(unique_lock<mutex>&);
bool empty_or_time_not_reached(lock_guard<mutex>&);
sync_timed_queue(const sync_timed_queue&);
sync_timed_queue& operator=(const sync_timed_queue&);
sync_timed_queue(BOOST_THREAD_RV_REF(sync_timed_queue));
@@ -149,309 +143,250 @@ namespace detail
}; //end class
template <class T, class Clock>
template <class T, class Clock, class TimePoint>
template <class Duration>
void sync_timed_queue<T, Clock>::push(const T& elem, chrono::time_point<clock,Duration> const& tp)
void sync_timed_queue<T, Clock, TimePoint>::push(const T& elem, chrono::time_point<clock,Duration> const& tp)
{
super::push(stype(elem,tp));
}
template <class T, class Clock>
template <class T, class Clock, class TimePoint>
template <class Rep, class Period>
void sync_timed_queue<T, Clock>::push(const T& elem, chrono::duration<Rep,Period> const& dura)
void sync_timed_queue<T, Clock, TimePoint>::push(const T& elem, chrono::duration<Rep,Period> const& dura)
{
push(elem, clock::now() + dura);
}
template <class T, class Clock>
template <class T, class Clock, class TimePoint>
template <class Duration>
void sync_timed_queue<T, Clock>::push(BOOST_THREAD_RV_REF(T) elem, chrono::time_point<clock,Duration> const& tp)
void sync_timed_queue<T, Clock, TimePoint>::push(BOOST_THREAD_RV_REF(T) elem, chrono::time_point<clock,Duration> const& tp)
{
super::push(stype(boost::move(elem),tp));
}
template <class T, class Clock>
template <class T, class Clock, class TimePoint>
template <class Rep, class Period>
void sync_timed_queue<T, Clock>::push(BOOST_THREAD_RV_REF(T) elem, chrono::duration<Rep,Period> const& dura)
void sync_timed_queue<T, Clock, TimePoint>::push(BOOST_THREAD_RV_REF(T) elem, chrono::duration<Rep,Period> const& dura)
{
push(boost::move(elem), clock::now() + dura);
}
template <class T, class Clock>
template <class T, class Clock, class TimePoint>
template <class Duration>
queue_op_status sync_timed_queue<T, Clock>::try_push(const T& elem, chrono::time_point<clock,Duration> const& tp)
queue_op_status sync_timed_queue<T, Clock, TimePoint>::try_push(const T& elem, chrono::time_point<clock,Duration> const& tp)
{
return super::try_push(stype(elem,tp));
}
template <class T, class Clock>
template <class T, class Clock, class TimePoint>
template <class Rep, class Period>
queue_op_status sync_timed_queue<T, Clock>::try_push(const T& elem, chrono::duration<Rep,Period> const& dura)
queue_op_status sync_timed_queue<T, Clock, TimePoint>::try_push(const T& elem, chrono::duration<Rep,Period> const& dura)
{
return try_push(elem,clock::now() + dura);
}
template <class T, class Clock>
template <class T, class Clock, class TimePoint>
template <class Duration>
queue_op_status sync_timed_queue<T, Clock>::try_push(BOOST_THREAD_RV_REF(T) elem, chrono::time_point<clock,Duration> const& tp)
queue_op_status sync_timed_queue<T, Clock, TimePoint>::try_push(BOOST_THREAD_RV_REF(T) elem, chrono::time_point<clock,Duration> const& tp)
{
return super::try_push(stype(boost::move(elem), tp));
}
template <class T, class Clock>
template <class T, class Clock, class TimePoint>
template <class Rep, class Period>
queue_op_status sync_timed_queue<T, Clock>::try_push(BOOST_THREAD_RV_REF(T) elem, chrono::duration<Rep,Period> const& dura)
queue_op_status sync_timed_queue<T, Clock, TimePoint>::try_push(BOOST_THREAD_RV_REF(T) elem, chrono::duration<Rep,Period> const& dura)
{
return try_push(boost::move(elem), clock::now() + dura);
}
///////////////////////////
template <class T, class Clock>
bool sync_timed_queue<T, Clock>::time_not_reached(unique_lock<mutex>&)
template <class T, class Clock, class TimePoint>
bool sync_timed_queue<T, Clock, TimePoint>::not_empty_and_time_reached(unique_lock<mutex>& lk) const
{
return super::data_.top().time_not_reached();
return ! super::empty(lk) && clock::now() >= super::data_.top().time;
}
template <class T, class Clock>
bool sync_timed_queue<T, Clock>::time_not_reached(lock_guard<mutex>&)
template <class T, class Clock, class TimePoint>
bool sync_timed_queue<T, Clock, TimePoint>::not_empty_and_time_reached(lock_guard<mutex>& lk) const
{
return super::data_.top().time_not_reached();
return ! super::empty(lk) && clock::now() >= super::data_.top().time;
}
///////////////////////////
template <class T, class Clock>
bool sync_timed_queue<T, Clock>::wait_until_not_empty_time_reached_or_closed(unique_lock<mutex>& lk)
template <class T, class Clock, class TimePoint>
bool sync_timed_queue<T, Clock, TimePoint>::wait_to_pull(unique_lock<mutex>& lk)
{
for (;;)
{
if (super::closed(lk)) return true;
while (! super::empty(lk)) {
if (! time_not_reached(lk)) return false;
time_point tp = super::data_.top().time;
super::not_empty_.wait_until(lk, tp);
if (super::closed(lk)) return true;
}
if (super::closed(lk)) return true;
super::not_empty_.wait(lk);
if (not_empty_and_time_reached(lk)) return false; // success
if (super::closed(lk)) return true; // closed
super::wait_until_not_empty_or_closed(lk);
if (not_empty_and_time_reached(lk)) return false; // success
if (super::closed(lk)) return true; // closed
const time_point tp(super::data_.top().time);
super::wait_until_closed_until(lk, tp);
}
}
template <class T, class Clock, class TimePoint>
template <class WClock, class Duration>
queue_op_status sync_timed_queue<T, Clock, TimePoint>::wait_to_pull_until(unique_lock<mutex>& lk, chrono::time_point<WClock, Duration> const& tp)
{
for (;;)
{
if (not_empty_and_time_reached(lk)) return queue_op_status::success;
if (super::closed(lk)) return queue_op_status::closed;
if (clock::now() >= tp) return super::empty(lk) ? queue_op_status::timeout : queue_op_status::not_ready;
super::wait_until_not_empty_or_closed_until(lk, tp);
if (not_empty_and_time_reached(lk)) return queue_op_status::success;
if (super::closed(lk)) return queue_op_status::closed;
if (clock::now() >= tp) return super::empty(lk) ? queue_op_status::timeout : queue_op_status::not_ready;
const time_point tpmin(tp < super::data_.top().time ? tp : super::data_.top().time);
super::wait_until_closed_until(lk, tpmin);
}
//return false;
}
///////////////////////////
template <class T, class Clock>
T sync_timed_queue<T, Clock>::pull_when_time_reached(unique_lock<mutex>& lk)
template <class T, class Clock, class TimePoint>
T sync_timed_queue<T, Clock, TimePoint>::pull(unique_lock<mutex>&)
{
while (time_not_reached(lk))
{
super::throw_if_closed(lk);
time_point tp = super::data_.top().time;
super::not_empty_.wait_until(lk,tp);
super::wait_until_not_empty(lk);
}
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
return boost::move(super::data_.pull().data);
#else
return super::data_.pull().data;
#endif
}
template <class T, class Clock, class TimePoint>
T sync_timed_queue<T, Clock, TimePoint>::pull(lock_guard<mutex>&)
{
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
return boost::move(super::data_.pull().data);
#else
return super::data_.pull().data;
#endif
}
template <class T, class Clock, class TimePoint>
T sync_timed_queue<T, Clock, TimePoint>::pull()
{
unique_lock<mutex> lk(super::mtx_);
const bool has_been_closed = wait_to_pull(lk);
if (has_been_closed) super::throw_if_closed(lk);
return pull(lk);
}
template <class T, class Clock>
template <class Duration>
queue_op_status
sync_timed_queue<T, Clock>::pull_when_time_reached_until(unique_lock<mutex>& lk, chrono::time_point<clock,Duration> const& tp, T& elem)
///////////////////////////
template <class T, class Clock, class TimePoint>
void sync_timed_queue<T, Clock, TimePoint>::pull(unique_lock<mutex>&, T& elem)
{
chrono::time_point<clock,Duration> tpmin = (tp < super::data_.top().time) ? tp : super::data_.top().time;
while (time_not_reached(lk))
{
super::throw_if_closed(lk);
if (cv_status::timeout == super::not_empty_.wait_until(lk, tpmin)) {
if (time_not_reached(lk)) return queue_op_status::not_ready;
return queue_op_status::timeout;
}
}
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
elem = boost::move(super::data_.pull().data);
#else
elem = super::data_.pull().data;
#endif
}
template <class T, class Clock, class TimePoint>
void sync_timed_queue<T, Clock, TimePoint>::pull(lock_guard<mutex>&, T& elem)
{
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
elem = boost::move(super::data_.pull().data);
#else
elem = super::data_.pull().data;
#endif
}
template <class T, class Clock, class TimePoint>
void sync_timed_queue<T, Clock, TimePoint>::pull(T& elem)
{
unique_lock<mutex> lk(super::mtx_);
const bool has_been_closed = wait_to_pull(lk);
if (has_been_closed) super::throw_if_closed(lk);
pull(lk, elem);
return queue_op_status::success;
}
///////////////////////////
template <class T, class Clock>
bool sync_timed_queue<T, Clock>::empty_or_time_not_reached(unique_lock<mutex>& lk)
{
if ( super::empty(lk) ) return true;
if ( time_not_reached(lk) ) return true;
return false;
}
template <class T, class Clock>
bool sync_timed_queue<T, Clock>::empty_or_time_not_reached(lock_guard<mutex>& lk)
{
if ( super::empty(lk) ) return true;
if ( time_not_reached(lk) ) return true;
return false;
}
///////////////////////////
template <class T, class Clock>
T sync_timed_queue<T, Clock>::pull(unique_lock<mutex>&)
{
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
return boost::move(super::data_.pull().data);
#else
return super::data_.pull().data;
#endif
}
template <class T, class Clock>
T sync_timed_queue<T, Clock>::pull(lock_guard<mutex>&)
{
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
return boost::move(super::data_.pull().data);
#else
return super::data_.pull().data;
#endif
}
template <class T, class Clock>
T sync_timed_queue<T, Clock>::pull()
{
unique_lock<mutex> lk(super::mtx_);
super::wait_until_not_empty(lk);
return pull_when_time_reached(lk);
}
///////////////////////////
template <class T, class Clock>
void sync_timed_queue<T, Clock>::pull(unique_lock<mutex>&, T& elem)
{
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
elem = boost::move(super::data_.pull().data);
#else
elem = super::data_.pull().data;
#endif
}
template <class T, class Clock>
void sync_timed_queue<T, Clock>::pull(lock_guard<mutex>&, T& elem)
{
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
elem = boost::move(super::data_.pull().data);
#else
elem = super::data_.pull().data;
#endif
}
template <class T, class Clock>
void sync_timed_queue<T, Clock>::pull(T& elem)
{
unique_lock<mutex> lk(super::mtx_);
super::wait_until_not_empty(lk);
elem = pull_when_time_reached(lk);
}
//////////////////////
template <class T, class Clock>
template <class Duration>
template <class T, class Clock, class TimePoint>
template <class WClock, class Duration>
queue_op_status
sync_timed_queue<T, Clock>::pull_until(chrono::time_point<clock,Duration> const& tp, T& elem)
sync_timed_queue<T, Clock, TimePoint>::pull_until(chrono::time_point<WClock, Duration> const& tp, T& elem)
{
unique_lock<mutex> lk(super::mtx_);
if (queue_op_status::timeout == super::wait_until_not_empty_until(lk, tp))
return queue_op_status::timeout;
return pull_when_time_reached_until(lk, tp, elem);
const queue_op_status rc = wait_to_pull_until(lk, tp);
if (rc == queue_op_status::success) pull(lk, elem);
return rc;
}
//////////////////////
template <class T, class Clock>
template <class T, class Clock, class TimePoint>
template <class Rep, class Period>
queue_op_status
sync_timed_queue<T, Clock>::pull_for(chrono::duration<Rep,Period> const& dura, T& elem)
sync_timed_queue<T, Clock, TimePoint>::pull_for(chrono::duration<Rep,Period> const& dura, T& elem)
{
return pull_until(clock::now() + dura, elem);
return pull_until(chrono::steady_clock::now() + dura, elem);
}
///////////////////////////
template <class T, class Clock>
queue_op_status sync_timed_queue<T, Clock>::try_pull(unique_lock<mutex>& lk, T& elem)
template <class T, class Clock, class TimePoint>
queue_op_status sync_timed_queue<T, Clock, TimePoint>::try_pull(unique_lock<mutex>& lk, T& elem)
{
if ( super::empty(lk) )
if (not_empty_and_time_reached(lk))
{
if (super::closed(lk)) return queue_op_status::closed;
return queue_op_status::empty;
pull(lk, elem);
return queue_op_status::success;
}
if ( time_not_reached(lk) )
{
if (super::closed(lk)) return queue_op_status::closed;
return queue_op_status::not_ready;
}
pull(lk, elem);
return queue_op_status::success;
if (super::closed(lk)) return queue_op_status::closed;
if (super::empty(lk)) return queue_op_status::empty;
return queue_op_status::not_ready;
}
template <class T, class Clock>
queue_op_status sync_timed_queue<T, Clock>::try_pull(lock_guard<mutex>& lk, T& elem)
template <class T, class Clock, class TimePoint>
queue_op_status sync_timed_queue<T, Clock, TimePoint>::try_pull(lock_guard<mutex>& lk, T& elem)
{
if ( super::empty(lk) )
if (not_empty_and_time_reached(lk))
{
if (super::closed(lk)) return queue_op_status::closed;
return queue_op_status::empty;
pull(lk, elem);
return queue_op_status::success;
}
if ( time_not_reached(lk) )
{
if (super::closed(lk)) return queue_op_status::closed;
return queue_op_status::not_ready;
}
pull(lk, elem);
return queue_op_status::success;
if (super::closed(lk)) return queue_op_status::closed;
if (super::empty(lk)) return queue_op_status::empty;
return queue_op_status::not_ready;
}
template <class T, class Clock>
queue_op_status sync_timed_queue<T, Clock>::try_pull(T& elem)
template <class T, class Clock, class TimePoint>
queue_op_status sync_timed_queue<T, Clock, TimePoint>::try_pull(T& elem)
{
lock_guard<mutex> lk(super::mtx_);
return try_pull(lk, elem);
}
///////////////////////////
template <class T, class Clock>
queue_op_status sync_timed_queue<T, Clock>::wait_pull(unique_lock<mutex>& lk, T& elem)
template <class T, class Clock, class TimePoint>
queue_op_status sync_timed_queue<T, Clock, TimePoint>::wait_pull(unique_lock<mutex>& lk, T& elem)
{
if (super::empty(lk))
{
if (super::closed(lk)) return queue_op_status::closed;
}
bool has_been_closed = wait_until_not_empty_time_reached_or_closed(lk);
const bool has_been_closed = wait_to_pull(lk);
if (has_been_closed) return queue_op_status::closed;
pull(lk, elem);
return queue_op_status::success;
}
template <class T, class Clock>
queue_op_status sync_timed_queue<T, Clock>::wait_pull(T& elem)
template <class T, class Clock, class TimePoint>
queue_op_status sync_timed_queue<T, Clock, TimePoint>::wait_pull(T& elem)
{
unique_lock<mutex> lk(super::mtx_);
return wait_pull(lk, elem);
}
// ///////////////////////////
// template <class T, class Clock>
// queue_op_status sync_timed_queue<T, Clock>::wait_pull(unique_lock<mutex> &lk, T& elem)
// {
// if (super::empty(lk))
// {
// if (super::closed(lk)) return queue_op_status::closed;
// }
// bool has_been_closed = super::wait_until_not_empty_or_closed(lk);
// if (has_been_closed) return queue_op_status::closed;
// pull(lk, elem);
// return queue_op_status::success;
// }
// template <class T>
// queue_op_status sync_timed_queue<T, Clock>::wait_pull(T& elem)
// {
// unique_lock<mutex> lk(super::mtx_);
// return wait_pull(lk, elem);
// }
///////////////////////////
template <class T, class Clock>
queue_op_status sync_timed_queue<T, Clock>::nonblocking_pull(T& elem)
template <class T, class Clock, class TimePoint>
queue_op_status sync_timed_queue<T, Clock, TimePoint>::nonblocking_pull(T& elem)
{
unique_lock<mutex> lk(super::mtx_, try_to_lock);
if (! lk.owns_lock()) return queue_op_status::busy;

View File

@@ -5,7 +5,7 @@
//
// 2013/10 Vicente J. Botet Escriba
// Creation.
#if 0
#ifndef BOOST_CSBL_QUEUE_HPP
#define BOOST_CSBL_QUEUE_HPP
@@ -43,3 +43,4 @@ namespace boost
}
}
#endif // header
#endif

View File

@@ -0,0 +1,19 @@
// Copyright (C) 2013 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#if defined(BOOST_INTEL)
#pragma pop_macro("atomic_compare_exchange")
#pragma pop_macro("atomic_compare_exchange_explicit")
#pragma pop_macro("atomic_exchange")
#pragma pop_macro("atomic_exchange_explicit")
#pragma pop_macro("atomic_is_lock_free")
#pragma pop_macro("atomic_load")
#pragma pop_macro("atomic_load_explicit")
#pragma pop_macro("atomic_store")
#pragma pop_macro("atomic_store_explicit")
#endif // #if defined(BOOST_INTEL)

View File

@@ -0,0 +1,39 @@
// Copyright (C) 2013 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#if defined(BOOST_INTEL)
#pragma push_macro("atomic_compare_exchange")
#undef atomic_compare_exchange
#pragma push_macro("atomic_compare_exchange_explicit")
#undef atomic_compare_exchange_explicit
#pragma push_macro("atomic_exchange")
#undef atomic_exchange
#pragma push_macro("atomic_exchange_explicit")
#undef atomic_exchange_explicit
#pragma push_macro("atomic_is_lock_free")
#undef atomic_is_lock_free
#pragma push_macro("atomic_load")
#undef atomic_load
#pragma push_macro("atomic_load_explicit")
#undef atomic_load_explicit
#pragma push_macro("atomic_store")
#undef atomic_store
#pragma push_macro("atomic_store_explicit")
#undef atomic_store_explicit
#endif // #if defined(BOOST_INTEL)

View File

@@ -11,23 +11,52 @@
#include <boost/config.hpp>
#include <boost/detail/workaround.hpp>
#include <boost/thread/detail/platform.hpp>
#include <boost/thread/detail/thread_safety.hpp>
//#define BOOST_THREAD_USEFIXES_TIMESPEC
//#define BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
//#define BOOST_THREAD_DONT_PROVIDE_INTERRUPTIONS
// ATTRIBUTE_MAY_ALIAS
#if defined(__GNUC__) && !defined(__INTEL_COMPILER)
//#if defined(__GNUC__) && !defined(__INTEL_COMPILER)
#if !defined(BOOST_NO_MAY_ALIAS)
// GCC since 3.3 has may_alias attribute that helps to alleviate optimizer issues with
// regard to violation of the strict aliasing rules.
// GCC since 3.3 and some other compilers have may_alias attribute that helps
// to alleviate optimizer issues with regard to violation of the strict aliasing rules.
#define BOOST_THREAD_DETAIL_USE_ATTRIBUTE_MAY_ALIAS
#define BOOST_THREAD_ATTRIBUTE_MAY_ALIAS __attribute__((__may_alias__))
#endif
#if defined(BOOST_MAY_ALIAS)
#define BOOST_THREAD_ATTRIBUTE_MAY_ALIAS BOOST_MAY_ALIAS
#else
#define BOOST_THREAD_ATTRIBUTE_MAY_ALIAS
#define BOOST_THREAD_ATTRIBUTE_MAY_ALIAS
#endif
#if defined(BOOST_THREAD_CHRONO_WINDOWS_API)
# warning Boost.Thread will use the Windows API for time
#elif defined(BOOST_THREAD_CHRONO_MAC_API)
# warning Boost.Thread will use the Mac API for time
#elif defined(BOOST_THREAD_CHRONO_POSIX_API)
# warning Boost.Thread will use the POSIX API for time
#endif
# if defined( BOOST_THREAD_CHRONO_WINDOWS_API ) && defined( BOOST_THREAD_CHRONO_POSIX_API )
# error both BOOST_THREAD_CHRONO_WINDOWS_API and BOOST_THREAD_CHRONO_POSIX_API are defined
# elif defined( BOOST_THREAD_CHRONO_WINDOWS_API ) && defined( BOOST_THREAD_CHRONO_MAC_API )
# error both BOOST_THREAD_CHRONO_WINDOWS_API and BOOST_THREAD_CHRONO_MAC_API are defined
# elif defined( BOOST_THREAD_CHRONO_MAC_API ) && defined( BOOST_THREAD_CHRONO_POSIX_API )
# error both BOOST_THREAD_CHRONO_MAC_API and BOOST_THREAD_CHRONO_POSIX_API are defined
# elif !defined( BOOST_THREAD_CHRONO_WINDOWS_API ) && !defined( BOOST_THREAD_CHRONO_MAC_API ) && !defined( BOOST_THREAD_CHRONO_POSIX_API )
# if defined(BOOST_THREAD_PLATFORM_WIN32)
# define BOOST_THREAD_CHRONO_WINDOWS_API
# elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
# define BOOST_THREAD_CHRONO_MAC_API
# else
# define BOOST_THREAD_CHRONO_POSIX_API
# endif
# endif
#if !defined(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS)
#define BOOST_THREAD_POLL_INTERVAL_MILLISECONDS 100
#endif
#if defined BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED
#define BOOST_THREAD_ASSERT_PRECONDITION(EXPR, EX) \
@@ -95,7 +124,7 @@
/// RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR
//#if defined BOOST_NO_CXX11_RVALUE_REFERENCES || defined BOOST_MSVC
#define BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR
#define BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNCTION_PTR
//#endif
// Default version
@@ -309,10 +338,18 @@
#if BOOST_THREAD_VERSION>=5
//#define BOOST_THREAD_FUTURE_BLOCKING
#if ! defined BOOST_THREAD_PROVIDES_EXECUTORS \
&& ! defined BOOST_THREAD_DONT_PROVIDE_EXECUTORS
#define BOOST_THREAD_PROVIDES_EXECUTORS
#endif
#else
//#define BOOST_THREAD_FUTURE_BLOCKING
#define BOOST_THREAD_ASYNC_FUTURE_WAITS
#endif
// INTERRUPTIONS
#if ! defined BOOST_THREAD_PROVIDES_INTERRUPTIONS \
&& ! defined BOOST_THREAD_DONT_PROVIDE_INTERRUPTIONS
@@ -384,9 +421,37 @@
# endif
#endif
#if defined(BOOST_THREAD_CHRONO_WINDOWS_API)
#define BOOST_THREAD_HAS_MONO_CLOCK
#define BOOST_THREAD_INTERNAL_CLOCK_IS_MONO
#elif defined(BOOST_THREAD_CHRONO_MAC_API)
#define BOOST_THREAD_HAS_MONO_CLOCK
#elif defined(__ANDROID__)
#define BOOST_THREAD_HAS_MONO_CLOCK
#if defined(__ANDROID_API__) && __ANDROID_API__ >= 21
#define BOOST_THREAD_INTERNAL_CLOCK_IS_MONO
#endif
#else
#include <time.h> // check for CLOCK_MONOTONIC
#if defined(CLOCK_MONOTONIC)
#define BOOST_THREAD_HAS_MONO_CLOCK
#define BOOST_THREAD_INTERNAL_CLOCK_IS_MONO
#endif
#endif
#if defined(BOOST_THREAD_PLATFORM_WIN32)
#elif ! defined BOOST_THREAD_INTERNAL_CLOCK_IS_MONO
#if defined BOOST_PTHREAD_HAS_TIMEDLOCK
#define BOOST_THREAD_USES_PTHREAD_TIMEDLOCK
#elif (defined(_POSIX_TIMEOUTS) && (_POSIX_TIMEOUTS-0)>=200112L) \
|| (defined(__ANDROID__) && defined(__ANDROID_API__) && __ANDROID_API__ >= 21)
#define BOOST_THREAD_USES_PTHREAD_TIMEDLOCK
#endif
#endif
// provided for backwards compatibility, since this
// macro was used for several releases by mistake.
#if defined(BOOST_THREAD_DYN_DLL) && ! defined BOOST_THREAD_DYN_LINK
#if defined(BOOST_THREAD_DYN_DLL) && ! defined(BOOST_THREAD_DYN_LINK)
# define BOOST_THREAD_DYN_LINK
#endif
@@ -445,7 +510,7 @@
// Tell the autolink to link dynamically, this will get undef'ed by auto_link.hpp
// once it's done with it:
//
#if defined(BOOST_THREAD_USE_DLL)
#if defined(BOOST_THREAD_USE_DLL) & ! defined(BOOST_DYN_LINK)
# define BOOST_DYN_LINK
#endif
//

View File

@@ -72,7 +72,13 @@ namespace boost
}
}
#ifdef BOOST_MSVC
#define BOOST_THREAD_LOG \
__pragma(warning(suppress:4127)) /* conditional expression is constant */ \
if (true) {} else boost::thread_detail::dummy_stream
#else
#define BOOST_THREAD_LOG if (true) {} else boost::thread_detail::dummy_stream
#endif
#define BOOST_THREAD_END_LOG boost::thread_detail::dummy_stream
#endif
@@ -80,4 +86,13 @@ namespace boost
#define BOOST_THREAD_TRACE BOOST_THREAD_LOG << BOOST_THREAD_END_LOG
#ifdef BOOST_MSVC
#define BOOST_DETAIL_THREAD_LOG \
__pragma(warning(suppress:4127)) /* conditional expression is constant */ \
if (false) {} else std::cout << std::endl << __FILE__ << "[" << __LINE__ << "]"
#else
#define BOOST_DETAIL_THREAD_LOG \
if (false) {} else std::cout << std::endl << __FILE__ << "[" << __LINE__ << "]"
#endif
#endif // header

View File

@@ -18,9 +18,7 @@
#include <boost/type_traits/remove_extent.hpp>
#include <boost/type_traits/is_array.hpp>
#include <boost/type_traits/is_function.hpp>
#include <boost/type_traits/remove_cv.hpp>
#include <boost/type_traits/add_pointer.hpp>
#include <boost/type_traits/decay.hpp>
#endif
#include <boost/thread/detail/delete.hpp>
@@ -352,12 +350,19 @@ namespace boost
#endif
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
template <class T>
typename decay<T>::type
decay_copy(T&& t)
{
return boost::forward<T>(t);
}
template <class T>
typename decay<T>::type
decay_copy(T&& t)
{
return boost::forward<T>(t);
}
typedef void (*void_fct_ptr)();
// inline void_fct_ptr
// decay_copy(void (&t)())
// {
// return &t;
// }
#else
template <class T>
typename decay<T>::type

View File

@@ -3,7 +3,7 @@
// 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)
//
// 2013/09 Vicente J. Botet Escriba
// 2013,2018 Vicente J. Botet Escriba
// Adapt to boost from CCIA C++11 implementation
// Make use of Boost.Move
@@ -15,6 +15,7 @@
#include <boost/thread/detail/move.hpp>
#include <boost/thread/csbl/memory/shared_ptr.hpp>
#include <boost/type_traits/decay.hpp>
#include <boost/type_traits/is_same.hpp>
namespace boost
{
@@ -72,12 +73,16 @@ namespace boost
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
template<typename F>
explicit nullary_function(F& f):
explicit nullary_function(F& f
, typename disable_if<is_same<typename decay<F>::type, nullary_function>, int* >::type=0
):
impl(new impl_type<F>(f))
{}
#endif
template<typename F>
nullary_function(BOOST_THREAD_RV_REF(F) f):
nullary_function(BOOST_THREAD_RV_REF(F) f
, typename disable_if<is_same<typename decay<F>::type, nullary_function>, int* >::type=0
):
impl(new impl_type<typename decay<F>::type>(thread_detail::decay_copy(boost::forward<F>(f))))
{}

View File

@@ -31,7 +31,9 @@
#elif defined(__CYGWIN__)
# define BOOST_THREAD_CYGWIN
#elif (defined(_WIN32) || defined(__WIN32__) || defined(WIN32)) && !defined(BOOST_DISABLE_WIN32)
#if ! defined BOOST_THREAD_WIN32
# define BOOST_THREAD_WIN32
#endif
#elif defined(__BEOS__)
# define BOOST_THREAD_BEOS
#elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)

View File

@@ -0,0 +1,478 @@
#ifndef BOOST_THREAD_DETAIL_PLATFORM_TIME_HPP
#define BOOST_THREAD_DETAIL_PLATFORM_TIME_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
#ifndef _WIN32
#include <unistd.h>
#endif
#ifdef BOOST_THREAD_USES_CHRONO
#include <boost/chrono/duration.hpp>
#include <boost/chrono/system_clocks.hpp>
#include <boost/chrono/ceil.hpp>
#endif
#if defined(BOOST_THREAD_CHRONO_WINDOWS_API)
#include <boost/detail/winapi/time.hpp>
#include <boost/detail/winapi/timers.hpp>
#include <boost/thread/win32/thread_primitives.hpp>
#elif defined(BOOST_THREAD_CHRONO_MAC_API)
#include <sys/time.h> //for gettimeofday and timeval
#include <mach/mach_time.h> // mach_absolute_time, mach_timebase_info_data_t
#else
#include <time.h> // for clock_gettime
#endif
#include <limits>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
//typedef boost::int_least64_t time_max_t;
typedef boost::intmax_t time_max_t;
#if defined BOOST_THREAD_CHRONO_MAC_API
namespace threads
{
namespace chrono_details
{
// steady_clock
// Note, in this implementation steady_clock and high_resolution_clock
// are the same clock. They are both based on mach_absolute_time().
// mach_absolute_time() * MachInfo.numer / MachInfo.denom is the number of
// nanoseconds since the computer booted up. MachInfo.numer and MachInfo.denom
// are run time constants supplied by the OS. This clock has no relationship
// to the Gregorian calendar. It's main use is as a high resolution timer.
// MachInfo.numer / MachInfo.denom is often 1 on the latest equipment. Specialize
// for that case as an optimization.
inline time_max_t
steady_simplified()
{
return mach_absolute_time();
}
inline double compute_steady_factor(kern_return_t& err)
{
mach_timebase_info_data_t MachInfo;
err = mach_timebase_info(&MachInfo);
if ( err != 0 ) {
return 0;
}
return static_cast<double>(MachInfo.numer) / MachInfo.denom;
}
inline time_max_t steady_full()
{
kern_return_t err;
const double factor = chrono_details::compute_steady_factor(err);
if (err != 0)
{
BOOST_ASSERT(0 && "Boost::Chrono - Internal Error");
}
return static_cast<time_max_t>(mach_absolute_time() * factor);
}
typedef time_max_t (*FP)();
inline FP init_steady_clock(kern_return_t & err)
{
mach_timebase_info_data_t MachInfo;
err = mach_timebase_info(&MachInfo);
if ( err != 0 )
{
return 0;
}
if (MachInfo.numer == MachInfo.denom)
{
return &chrono_details::steady_simplified;
}
return &chrono_details::steady_full;
}
}
}
#endif
namespace detail
{
#if defined BOOST_THREAD_CHRONO_POSIX_API || defined BOOST_THREAD_CHRONO_MAC_API
inline timespec ns_to_timespec(boost::time_max_t const& ns)
{
boost::time_max_t s = ns / 1000000000l;
timespec ts;
ts.tv_sec = static_cast<long> (s);
ts.tv_nsec = static_cast<long> (ns - s * 1000000000l);
return ts;
}
inline boost::time_max_t timespec_to_ns(timespec const& ts)
{
return static_cast<boost::time_max_t>(ts.tv_sec) * 1000000000l + ts.tv_nsec;
}
#endif
struct platform_duration
{
#if defined BOOST_THREAD_CHRONO_POSIX_API || defined BOOST_THREAD_CHRONO_MAC_API
explicit platform_duration(timespec const& v) : ts_val(v) {}
timespec const& getTs() const { return ts_val; }
explicit platform_duration(boost::time_max_t const& ns = 0) : ts_val(ns_to_timespec(ns)) {}
boost::time_max_t getNs() const { return timespec_to_ns(ts_val); }
#else
explicit platform_duration(boost::time_max_t const& ns = 0) : ns_val(ns) {}
boost::time_max_t getNs() const { return ns_val; }
#endif
#if defined BOOST_THREAD_USES_DATETIME
platform_duration(boost::posix_time::time_duration const& rel_time)
{
#if defined BOOST_THREAD_CHRONO_POSIX_API || defined BOOST_THREAD_CHRONO_MAC_API
ts_val.tv_sec = rel_time.total_seconds();
ts_val.tv_nsec = static_cast<long>(rel_time.fractional_seconds() * (1000000000l / rel_time.ticks_per_second()));
#else
ns_val = static_cast<boost::time_max_t>(rel_time.total_seconds()) * 1000000000l;
ns_val += rel_time.fractional_seconds() * (1000000000l / rel_time.ticks_per_second());
#endif
}
#endif
#if defined BOOST_THREAD_USES_CHRONO
template <class Rep, class Period>
platform_duration(chrono::duration<Rep, Period> const& d)
{
#if defined BOOST_THREAD_CHRONO_POSIX_API || defined BOOST_THREAD_CHRONO_MAC_API
ts_val = ns_to_timespec(chrono::ceil<chrono::nanoseconds>(d).count());
#else
ns_val = chrono::ceil<chrono::nanoseconds>(d).count();
#endif
}
#endif
boost::time_max_t getMs() const
{
const boost::time_max_t ns = getNs();
// ceil/floor away from zero
if (ns >= 0)
{
// return ceiling of positive numbers
return (ns + 999999) / 1000000;
}
else
{
// return floor of negative numbers
return (ns - 999999) / 1000000;
}
}
static platform_duration zero()
{
return platform_duration(0);
}
private:
#if defined BOOST_THREAD_CHRONO_POSIX_API || defined BOOST_THREAD_CHRONO_MAC_API
timespec ts_val;
#else
boost::time_max_t ns_val;
#endif
};
inline bool operator==(platform_duration const& lhs, platform_duration const& rhs)
{
return lhs.getNs() == rhs.getNs();
}
inline bool operator!=(platform_duration const& lhs, platform_duration const& rhs)
{
return lhs.getNs() != rhs.getNs();
}
inline bool operator<(platform_duration const& lhs, platform_duration const& rhs)
{
return lhs.getNs() < rhs.getNs();
}
inline bool operator<=(platform_duration const& lhs, platform_duration const& rhs)
{
return lhs.getNs() <= rhs.getNs();
}
inline bool operator>(platform_duration const& lhs, platform_duration const& rhs)
{
return lhs.getNs() > rhs.getNs();
}
inline bool operator>=(platform_duration const& lhs, platform_duration const& rhs)
{
return lhs.getNs() >= rhs.getNs();
}
static inline platform_duration platform_milliseconds(long const& ms)
{
return platform_duration(ms * 1000000l);
}
struct real_platform_timepoint
{
#if defined BOOST_THREAD_CHRONO_POSIX_API || defined BOOST_THREAD_CHRONO_MAC_API
explicit real_platform_timepoint(timespec const& v) : dur(v) {}
timespec const& getTs() const { return dur.getTs(); }
#endif
explicit real_platform_timepoint(boost::time_max_t const& ns) : dur(ns) {}
boost::time_max_t getNs() const { return dur.getNs(); }
#if defined BOOST_THREAD_USES_DATETIME
real_platform_timepoint(boost::system_time const& abs_time)
: dur(abs_time - boost::posix_time::from_time_t(0)) {}
#endif
#if defined BOOST_THREAD_USES_CHRONO
template <class Duration>
real_platform_timepoint(chrono::time_point<chrono::system_clock, Duration> const& abs_time)
: dur(abs_time.time_since_epoch()) {}
#endif
private:
platform_duration dur;
};
inline bool operator==(real_platform_timepoint const& lhs, real_platform_timepoint const& rhs)
{
return lhs.getNs() == rhs.getNs();
}
inline bool operator!=(real_platform_timepoint const& lhs, real_platform_timepoint const& rhs)
{
return lhs.getNs() != rhs.getNs();
}
inline bool operator<(real_platform_timepoint const& lhs, real_platform_timepoint const& rhs)
{
return lhs.getNs() < rhs.getNs();
}
inline bool operator<=(real_platform_timepoint const& lhs, real_platform_timepoint const& rhs)
{
return lhs.getNs() <= rhs.getNs();
}
inline bool operator>(real_platform_timepoint const& lhs, real_platform_timepoint const& rhs)
{
return lhs.getNs() > rhs.getNs();
}
inline bool operator>=(real_platform_timepoint const& lhs, real_platform_timepoint const& rhs)
{
return lhs.getNs() >= rhs.getNs();
}
inline real_platform_timepoint operator+(real_platform_timepoint const& lhs, platform_duration const& rhs)
{
return real_platform_timepoint(lhs.getNs() + rhs.getNs());
}
inline real_platform_timepoint operator+(platform_duration const& lhs, real_platform_timepoint const& rhs)
{
return real_platform_timepoint(lhs.getNs() + rhs.getNs());
}
inline platform_duration operator-(real_platform_timepoint const& lhs, real_platform_timepoint const& rhs)
{
return platform_duration(lhs.getNs() - rhs.getNs());
}
struct real_platform_clock
{
static real_platform_timepoint now()
{
#if defined(BOOST_THREAD_CHRONO_WINDOWS_API)
boost::detail::winapi::FILETIME_ ft;
boost::detail::winapi::GetSystemTimeAsFileTime(&ft); // never fails
boost::time_max_t ns = ((((static_cast<boost::time_max_t>(ft.dwHighDateTime) << 32) | ft.dwLowDateTime) - 116444736000000000LL) * 100LL);
return real_platform_timepoint(ns);
#elif defined(BOOST_THREAD_CHRONO_MAC_API)
timeval tv;
::gettimeofday(&tv, 0);
timespec ts;
ts.tv_sec = tv.tv_sec;
ts.tv_nsec = tv.tv_usec * 1000;
return real_platform_timepoint(ts);
#else
timespec ts;
if ( ::clock_gettime( CLOCK_REALTIME, &ts ) )
{
BOOST_ASSERT(0 && "Boost::Thread - clock_gettime(CLOCK_REALTIME) Internal Error");
return real_platform_timepoint(0);
}
return real_platform_timepoint(ts);
#endif
}
};
#if defined(BOOST_THREAD_HAS_MONO_CLOCK)
struct mono_platform_timepoint
{
#if defined BOOST_THREAD_CHRONO_POSIX_API || defined BOOST_THREAD_CHRONO_MAC_API
explicit mono_platform_timepoint(timespec const& v) : dur(v) {}
timespec const& getTs() const { return dur.getTs(); }
#endif
explicit mono_platform_timepoint(boost::time_max_t const& ns) : dur(ns) {}
boost::time_max_t getNs() const { return dur.getNs(); }
#if defined BOOST_THREAD_USES_CHRONO
// This conversion assumes that chrono::steady_clock::time_point and mono_platform_timepoint share the same epoch.
template <class Duration>
mono_platform_timepoint(chrono::time_point<chrono::steady_clock, Duration> const& abs_time)
: dur(abs_time.time_since_epoch()) {}
#endif
// can't name this max() since that is a macro on some Windows systems
static mono_platform_timepoint getMax()
{
#if defined BOOST_THREAD_CHRONO_POSIX_API || defined BOOST_THREAD_CHRONO_MAC_API
timespec ts;
ts.tv_sec = (std::numeric_limits<time_t>::max)();
ts.tv_nsec = 999999999;
return mono_platform_timepoint(ts);
#else
boost::time_max_t ns = (std::numeric_limits<boost::time_max_t>::max)();
return mono_platform_timepoint(ns);
#endif
}
private:
platform_duration dur;
};
inline bool operator==(mono_platform_timepoint const& lhs, mono_platform_timepoint const& rhs)
{
return lhs.getNs() == rhs.getNs();
}
inline bool operator!=(mono_platform_timepoint const& lhs, mono_platform_timepoint const& rhs)
{
return lhs.getNs() != rhs.getNs();
}
inline bool operator<(mono_platform_timepoint const& lhs, mono_platform_timepoint const& rhs)
{
return lhs.getNs() < rhs.getNs();
}
inline bool operator<=(mono_platform_timepoint const& lhs, mono_platform_timepoint const& rhs)
{
return lhs.getNs() <= rhs.getNs();
}
inline bool operator>(mono_platform_timepoint const& lhs, mono_platform_timepoint const& rhs)
{
return lhs.getNs() > rhs.getNs();
}
inline bool operator>=(mono_platform_timepoint const& lhs, mono_platform_timepoint const& rhs)
{
return lhs.getNs() >= rhs.getNs();
}
inline mono_platform_timepoint operator+(mono_platform_timepoint const& lhs, platform_duration const& rhs)
{
return mono_platform_timepoint(lhs.getNs() + rhs.getNs());
}
inline mono_platform_timepoint operator+(platform_duration const& lhs, mono_platform_timepoint const& rhs)
{
return mono_platform_timepoint(lhs.getNs() + rhs.getNs());
}
inline platform_duration operator-(mono_platform_timepoint const& lhs, mono_platform_timepoint const& rhs)
{
return platform_duration(lhs.getNs() - rhs.getNs());
}
struct mono_platform_clock
{
static mono_platform_timepoint now()
{
#if defined(BOOST_THREAD_CHRONO_WINDOWS_API)
#if defined(BOOST_THREAD_USES_CHRONO)
// Use QueryPerformanceCounter() to match the implementation in Boost
// Chrono so that chrono::steady_clock::now() and this function share the
// same epoch and so can be converted between each other.
boost::detail::winapi::LARGE_INTEGER_ freq;
if ( !boost::detail::winapi::QueryPerformanceFrequency( &freq ) )
{
BOOST_ASSERT(0 && "Boost::Thread - QueryPerformanceFrequency Internal Error");
return mono_platform_timepoint(0);
}
if ( freq.QuadPart <= 0 )
{
BOOST_ASSERT(0 && "Boost::Thread - QueryPerformanceFrequency Internal Error");
return mono_platform_timepoint(0);
}
boost::detail::winapi::LARGE_INTEGER_ pcount;
unsigned times=0;
while ( ! boost::detail::winapi::QueryPerformanceCounter( &pcount ) )
{
if ( ++times > 3 )
{
BOOST_ASSERT(0 && "Boost::Thread - QueryPerformanceCounter Internal Error");
return mono_platform_timepoint(0);
}
}
long double ns = 1000000000.0L * pcount.QuadPart / freq.QuadPart;
return mono_platform_timepoint(static_cast<boost::time_max_t>(ns));
#else
// Use GetTickCount64() because it's more reliable on older
// systems like Windows XP and Windows Server 2003.
win32::ticks_type msec = win32::gettickcount64();
return mono_platform_timepoint(msec * 1000000);
#endif
#elif defined(BOOST_THREAD_CHRONO_MAC_API)
kern_return_t err;
threads::chrono_details::FP fp = threads::chrono_details::init_steady_clock(err);
if ( err != 0 )
{
BOOST_ASSERT(0 && "Boost::Chrono - Internal Error");
}
return mono_platform_timepoint(fp());
#else
timespec ts;
if ( ::clock_gettime( CLOCK_MONOTONIC, &ts ) )
{
BOOST_ASSERT(0 && "Boost::Thread - clock_gettime(CLOCK_MONOTONIC) Internal Error");
return mono_platform_timepoint(0);
}
return mono_platform_timepoint(ts);
#endif
}
};
#endif
#if defined(BOOST_THREAD_INTERNAL_CLOCK_IS_MONO)
typedef mono_platform_clock internal_platform_clock;
typedef mono_platform_timepoint internal_platform_timepoint;
#else
typedef real_platform_clock internal_platform_clock;
typedef real_platform_timepoint internal_platform_timepoint;
#endif
#ifdef BOOST_THREAD_USES_CHRONO
#ifdef BOOST_THREAD_INTERNAL_CLOCK_IS_MONO
typedef chrono::steady_clock internal_chrono_clock;
#else
typedef chrono::system_clock internal_chrono_clock;
#endif
#endif
}
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -18,6 +18,9 @@
#if defined BOOST_THREAD_USES_DATETIME
#include <boost/thread/xtime.hpp>
#endif
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
#include <boost/thread/interruption.hpp>
#endif
#include <boost/thread/detail/thread_heap_alloc.hpp>
#include <boost/thread/detail/make_tuple_indices.hpp>
#include <boost/thread/detail/invoke.hpp>
@@ -36,6 +39,7 @@
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/decay.hpp>
#include <boost/functional/hash.hpp>
#include <boost/thread/detail/platform_time.hpp>
#ifdef BOOST_THREAD_USES_CHRONO
#include <boost/chrono/system_clocks.hpp>
#include <boost/chrono/ceil.hpp>
@@ -291,7 +295,7 @@ namespace boost
template <class F>
explicit thread(F f
, typename disable_if_c<
boost::thread_detail::is_rv<F>::value // todo ass a thread_detail::is_rv
boost::thread_detail::is_rv<F>::value // todo as a thread_detail::is_rv
//boost::thread_detail::is_convertible<F&,BOOST_THREAD_RV_REF(F)>::value
//|| is_same<typename decay<F>::type, thread>::value
, dummy* >::type=0
@@ -454,111 +458,80 @@ namespace boost
}
class id;
#ifdef BOOST_THREAD_PLATFORM_PTHREAD
inline id get_id() const BOOST_NOEXCEPT;
#else
id get_id() const BOOST_NOEXCEPT;
#endif
bool joinable() const BOOST_NOEXCEPT;
private:
bool join_noexcept();
bool do_try_join_until_noexcept(detail::internal_platform_timepoint const &timeout, bool& res);
bool do_try_join_until(detail::internal_platform_timepoint const &timeout);
public:
inline void join();
void join();
#ifdef BOOST_THREAD_USES_CHRONO
#if defined(BOOST_THREAD_PLATFORM_WIN32)
template <class Rep, class Period>
bool try_join_for(const chrono::duration<Rep, Period>& rel_time)
template <class Duration>
bool try_join_until(const chrono::time_point<detail::internal_chrono_clock, Duration>& t)
{
chrono::milliseconds rel_time2= chrono::ceil<chrono::milliseconds>(rel_time);
return do_try_join_until(rel_time2.count());
return do_try_join_until(boost::detail::internal_platform_timepoint(t));
}
#else
template <class Clock, class Duration>
bool try_join_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());
d = (std::min)(d, common_duration(chrono::milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS)));
while ( ! try_join_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 Rep, class Period>
bool try_join_for(const chrono::duration<Rep, Period>& rel_time)
{
return try_join_until(chrono::steady_clock::now() + rel_time);
}
#endif
#if defined(BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC) && defined(BOOST_THREAD_USEFIXES_TIMESPEC)
typedef chrono::steady_clock my_clock_t;
#else
typedef chrono::system_clock my_clock_t;
#endif
template <class Clock, class Duration>
bool try_join_until(const chrono::time_point<Clock, Duration>& t)
{
using namespace chrono;
bool joined= false;
do {
my_clock_t::time_point s_now = my_clock_t::now();
typename Clock::duration d = ceil<nanoseconds>(t-Clock::now());
if (d <= Clock::duration::zero()) return false; // in case the Clock::time_point t is already reached
joined = try_join_until(s_now + d);
} while (! joined);
return true;
}
template <class Duration>
bool try_join_until(const chrono::time_point<my_clock_t, Duration>& t)
{
using namespace chrono;
typedef time_point<my_clock_t, nanoseconds> nano_sys_tmpt;
return try_join_until(nano_sys_tmpt(ceil<nanoseconds>(t.time_since_epoch())));
}
#endif
#if defined(BOOST_THREAD_PLATFORM_WIN32)
private:
bool do_try_join_until_noexcept(uintmax_t milli, bool& res);
inline bool do_try_join_until(uintmax_t milli);
public:
bool timed_join(const system_time& abs_time);
//{
// return do_try_join_until(get_milliseconds_until(wait_until));
//}
#ifdef BOOST_THREAD_USES_CHRONO
bool try_join_until(const chrono::time_point<my_clock_t, chrono::nanoseconds>& tp)
{
chrono::milliseconds rel_time= chrono::ceil<chrono::milliseconds>(tp-chrono::system_clock::now());
return do_try_join_until(rel_time.count());
}
#endif
#else
private:
bool do_try_join_until_noexcept(struct timespec const &timeout, bool& res);
inline bool do_try_join_until(struct timespec const &timeout);
public:
#if defined BOOST_THREAD_USES_DATETIME
bool timed_join(const system_time& 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_join_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_join_until(ts);
#endif
}
#endif
#ifdef BOOST_THREAD_USES_CHRONO
bool try_join_until(const 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);
return do_try_join_until(ts);
}
#endif
#endif
public:
#if defined BOOST_THREAD_USES_DATETIME
template<typename TimeDuration>
inline bool timed_join(TimeDuration const& rel_time)
bool timed_join(TimeDuration const& rel_time)
{
return timed_join(get_system_time()+rel_time);
detail::platform_duration d(rel_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_join_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_join_until(detail::internal_platform_clock::now() + d);
#endif
}
#endif
void detach();
@@ -612,19 +585,13 @@ namespace boost
namespace this_thread
{
#ifdef BOOST_THREAD_PLATFORM_PTHREAD
inline thread::id get_id() BOOST_NOEXCEPT;
thread::id get_id() BOOST_NOEXCEPT;
#else
thread::id BOOST_THREAD_DECL get_id() BOOST_NOEXCEPT;
#endif
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
void BOOST_THREAD_DECL interruption_point();
bool BOOST_THREAD_DECL interruption_enabled() BOOST_NOEXCEPT;
bool BOOST_THREAD_DECL interruption_requested() BOOST_NOEXCEPT;
#endif
#if defined BOOST_THREAD_USES_DATETIME
inline BOOST_SYMBOL_VISIBLE void sleep(xtime const& abs_time)
inline BOOST_SYMBOL_VISIBLE void sleep(::boost::xtime const& abs_time)
{
sleep(system_time(abs_time));
}
@@ -743,7 +710,7 @@ namespace boost
};
#ifdef BOOST_THREAD_PLATFORM_PTHREAD
thread::id thread::get_id() const BOOST_NOEXCEPT
inline thread::id thread::get_id() const BOOST_NOEXCEPT
{
#if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID
return const_cast<thread*>(this)->native_handle();
@@ -766,7 +733,7 @@ namespace boost
}
}
#endif
void thread::join() {
inline void thread::join() {
if (this_thread::get_id() == get_id())
boost::throw_exception(thread_resource_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost thread: trying joining itself"));
@@ -775,11 +742,7 @@ namespace boost
);
}
#ifdef BOOST_THREAD_PLATFORM_PTHREAD
bool thread::do_try_join_until(struct timespec const &timeout)
#else
bool thread::do_try_join_until(uintmax_t timeout)
#endif
inline bool thread::do_try_join_until(detail::internal_platform_timepoint const &timeout)
{
if (this_thread::get_id() == get_id())
boost::throw_exception(thread_resource_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost thread: trying joining itself"));
@@ -845,6 +808,7 @@ namespace boost
};
void BOOST_THREAD_DECL add_thread_exit_function(thread_exit_function_base*);
//#ifndef BOOST_NO_EXCEPTIONS
struct shared_state_base;
#if defined(BOOST_THREAD_PLATFORM_WIN32)
inline void make_ready_at_thread_exit(shared_ptr<shared_state_base> as)
@@ -858,6 +822,7 @@ namespace boost
#else
void BOOST_THREAD_DECL make_ready_at_thread_exit(shared_ptr<shared_state_base> as);
#endif
//#endif
}
namespace this_thread

View File

@@ -0,0 +1,160 @@
#ifndef BOOST_THREAD_DETAIL_THREAD_SAFETY_HPP
#define BOOST_THREAD_DETAIL_THREAD_SAFETY_HPP
#if defined(__GNUC__) && !defined(__GXX_EXPERIMENTAL_CXX0X__)
//
// This is horrible, but it seems to be the only we can shut up the
// "anonymous variadic macros were introduced in C99 [-Wvariadic-macros]"
// warning that get spewed out otherwise in non-C++11 mode.
//
#pragma GCC system_header
#endif
// See https://clang.llvm.org/docs/ThreadSafetyAnalysis.html
// Un-comment to enable Thread Safety Analysis
//#define BOOST_THREAD_ENABLE_THREAD_SAFETY_ANALYSIS
// Enable thread safety attributes only with clang.
// The attributes can be safely erased when compiling with other compilers.
#if defined (BOOST_THREAD_ENABLE_THREAD_SAFETY_ANALYSIS) && defined(__clang__) && (!defined(SWIG))
#define BOOST_THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x))
#else
#define BOOST_THREAD_ANNOTATION_ATTRIBUTE__(x) // no-op
#endif
#define BOOST_THREAD_CAPABILITY(x) \
BOOST_THREAD_ANNOTATION_ATTRIBUTE__(capability(x))
#define BOOST_THREAD_SCOPED_CAPABILITY \
BOOST_THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable)
#define BOOST_THREAD_GUARDED_BY(x) \
BOOST_THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x))
#define BOOST_THREAD_PT_GUARDED_BY(x) \
BOOST_THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_by(x))
#define BOOST_THREAD_ACQUIRED_BEFORE(...) \
BOOST_THREAD_ANNOTATION_ATTRIBUTE__(acquired_before(__VA_ARGS__))
#define BOOST_THREAD_ACQUIRED_AFTER(...) \
BOOST_THREAD_ANNOTATION_ATTRIBUTE__(acquired_after(__VA_ARGS__))
#define BOOST_THREAD_REQUIRES(...) \
BOOST_THREAD_ANNOTATION_ATTRIBUTE__(requires_capability(__VA_ARGS__))
#define BOOST_THREAD_REQUIRES_SHARED(...) \
BOOST_THREAD_ANNOTATION_ATTRIBUTE__(requires_shared_capability(__VA_ARGS__))
#define BOOST_THREAD_ACQUIRE(...) \
BOOST_THREAD_ANNOTATION_ATTRIBUTE__(acquire_capability(__VA_ARGS__))
#define BOOST_THREAD_ACQUIRE_SHARED(...) \
BOOST_THREAD_ANNOTATION_ATTRIBUTE__(acquire_shared_capability(__VA_ARGS__))
#define BOOST_THREAD_RELEASE(...) \
BOOST_THREAD_ANNOTATION_ATTRIBUTE__(release_capability(__VA_ARGS__))
#define BOOST_THREAD_RELEASE_SHARED(...) \
BOOST_THREAD_ANNOTATION_ATTRIBUTE__(release_shared_capability(__VA_ARGS__))
#define BOOST_THREAD_TRY_ACQUIRE(...) \
BOOST_THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_capability(__VA_ARGS__))
#define BOOST_THREAD_TRY_ACQUIRE_SHARED(...) \
BOOST_THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_shared_capability(__VA_ARGS__))
#define BOOST_THREAD_EXCLUDES(...) \
BOOST_THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(__VA_ARGS__))
#define BOOST_THREAD_ASSERT_CAPABILITY(x) \
BOOST_THREAD_ANNOTATION_ATTRIBUTE__(assert_capability(x))
#define BOOST_THREAD_ASSERT_SHARED_CAPABILITY(x) \
BOOST_THREAD_ANNOTATION_ATTRIBUTE__(assert_shared_capability(x))
#define BOOST_THREAD_RETURN_CAPABILITY(x) \
BOOST_THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x))
#define BOOST_THREAD_NO_THREAD_SAFETY_ANALYSIS \
BOOST_THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis)
#if defined(__clang__) && (!defined(SWIG)) && defined(__FreeBSD__)
#if __has_attribute(no_thread_safety_analysis)
#define BOOST_THREAD_DISABLE_THREAD_SAFETY_ANALYSIS __attribute__((no_thread_safety_analysis))
#else
#define BOOST_THREAD_DISABLE_THREAD_SAFETY_ANALYSIS
#endif
#else
#define BOOST_THREAD_DISABLE_THREAD_SAFETY_ANALYSIS
#endif
#ifdef USE_LOCK_STYLE_THREAD_SAFETY_ATTRIBUTES
// The original version of thread safety analysis the following attribute
// definitions. These use a lock-based terminology. They are still in use
// by existing thread safety code, and will continue to be supported.
// Deprecated.
#define BOOST_THREAD_PT_GUARDED_VAR \
BOOST_THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_var)
// Deprecated.
#define BOOST_THREAD_GUARDED_VAR \
BOOST_THREAD_ANNOTATION_ATTRIBUTE__(guarded_var)
// Replaced by REQUIRES
#define BOOST_THREAD_EXCLUSIVE_LOCKS_REQUIRED(...) \
BOOST_THREAD_ANNOTATION_ATTRIBUTE__(exclusive_locks_required(__VA_ARGS__))
// Replaced by REQUIRES_SHARED
#define BOOST_THREAD_SHARED_LOCKS_REQUIRED(...) \
BOOST_THREAD_ANNOTATION_ATTRIBUTE__(shared_locks_required(__VA_ARGS__))
// Replaced by CAPABILITY
#define BOOST_THREAD_LOCKABLE \
BOOST_THREAD_ANNOTATION_ATTRIBUTE__(lockable)
// Replaced by SCOPED_CAPABILITY
#define BOOST_THREAD_SCOPED_LOCKABLE \
BOOST_THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable)
// Replaced by ACQUIRE
#define BOOST_THREAD_EXCLUSIVE_LOCK_FUNCTION(...) \
BOOST_THREAD_ANNOTATION_ATTRIBUTE__(exclusive_lock_function(__VA_ARGS__))
// Replaced by ACQUIRE_SHARED
#define BOOST_THREAD_SHARED_LOCK_FUNCTION(...) \
BOOST_THREAD_ANNOTATION_ATTRIBUTE__(shared_lock_function(__VA_ARGS__))
// Replaced by RELEASE and RELEASE_SHARED
#define BOOST_THREAD_UNLOCK_FUNCTION(...) \
BOOST_THREAD_ANNOTATION_ATTRIBUTE__(unlock_function(__VA_ARGS__))
// Replaced by TRY_ACQUIRE
#define BOOST_THREAD_EXCLUSIVE_TRYLOCK_FUNCTION(...) \
BOOST_THREAD_ANNOTATION_ATTRIBUTE__(exclusive_trylock_function(__VA_ARGS__))
// Replaced by TRY_ACQUIRE_SHARED
#define BOOST_THREAD_SHARED_TRYLOCK_FUNCTION(...) \
BOOST_THREAD_ANNOTATION_ATTRIBUTE__(shared_trylock_function(__VA_ARGS__))
// Replaced by ASSERT_CAPABILITY
#define BOOST_THREAD_ASSERT_EXCLUSIVE_LOCK(...) \
BOOST_THREAD_ANNOTATION_ATTRIBUTE__(assert_exclusive_lock(__VA_ARGS__))
// Replaced by ASSERT_SHARED_CAPABILITY
#define BOOST_THREAD_ASSERT_SHARED_LOCK(...) \
BOOST_THREAD_ANNOTATION_ATTRIBUTE__(assert_shared_lock(__VA_ARGS__))
// Replaced by EXCLUDE_CAPABILITY.
#define BOOST_THREAD_LOCKS_EXCLUDED(...) \
BOOST_THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(__VA_ARGS__))
// Replaced by RETURN_CAPABILITY
#define BOOST_THREAD_LOCK_RETURNED(x) \
BOOST_THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x))
#endif // USE_LOCK_STYLE_THREAD_SAFETY_ATTRIBUTES
#endif // BOOST_THREAD_DETAIL_THREAD_SAFETY_HPP

View File

@@ -10,7 +10,7 @@
#include <boost/config/abi_prefix.hpp>
#if defined(BOOST_HAS_WINTHREADS)
#if defined(BOOST_THREAD_WIN32)
namespace boost
{
@@ -58,7 +58,7 @@ namespace boost
//it to be linked into the Boost.Threads library.
}
#endif //defined(BOOST_HAS_WINTHREADS)
#endif //defined(BOOST_THREAD_WIN32)
#include <boost/config/abi_suffix.hpp>

View File

@@ -56,7 +56,7 @@ namespace boost
{
}
~thread_exception() throw()
~thread_exception() BOOST_NOEXCEPT_OR_NOTHROW
{}
@@ -113,7 +113,7 @@ namespace boost
{
}
~lock_error() throw()
~lock_error() BOOST_NOEXCEPT_OR_NOTHROW
{}
};
@@ -141,7 +141,7 @@ namespace boost
}
~thread_resource_error() throw()
~thread_resource_error() BOOST_NOEXCEPT_OR_NOTHROW
{}
};

View File

@@ -11,6 +11,8 @@
#define BOOST_THREAD_EXECUTORS_BASIC_THREAD_POOL_HPP
#include <boost/thread/detail/config.hpp>
#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION && defined BOOST_THREAD_PROVIDES_EXECUTORS && defined BOOST_THREAD_USES_MOVE
#include <boost/thread/detail/delete.hpp>
#include <boost/thread/detail/move.hpp>
#include <boost/thread/thread.hpp>
@@ -86,11 +88,18 @@ namespace executors
for(;;)
{
work task;
queue_op_status st = work_queue.wait_pull(task);
if (st == queue_op_status::closed) {
try
{
queue_op_status st = work_queue.wait_pull(task);
if (st == queue_op_status::closed) {
return;
}
task();
}
catch (boost::thread_interrupted&)
{
return;
}
task();
}
}
catch (...)
@@ -224,7 +233,7 @@ namespace executors
// signal to all the worker threads that there will be no more submissions.
close();
// joins all the threads before destroying the thread pool resources (e.g. the queue).
join();
interrupt_and_join();
}
/**
@@ -234,6 +243,30 @@ namespace executors
{
for (unsigned i = 0; i < threads.size(); ++i)
{
//threads[i].interrupt();
threads[i].join();
}
}
/**
* \b Effects: interrupt all the threads.
*/
void interrupt()
{
for (unsigned i = 0; i < threads.size(); ++i)
{
threads[i].interrupt();
}
}
/**
* \b Effects: interrupt and join all the threads.
*/
void interrupt_and_join()
{
for (unsigned i = 0; i < threads.size(); ++i)
{
threads[i].interrupt();
threads[i].join();
}
}
@@ -316,3 +349,4 @@ using executors::basic_thread_pool;
#include <boost/config/abi_suffix.hpp>
#endif
#endif

View File

@@ -57,10 +57,16 @@ namespace detail
{
for(;;)
{
work task;
queue_op_status st = _workq.wait_pull(task);
if (st == queue_op_status::closed) return;
task();
try {
work task;
queue_op_status st = _workq.wait_pull(task);
if (st == queue_op_status::closed) return;
task();
}
catch (boost::thread_interrupted&)
{
return;
}
}
}
catch (...)

View File

@@ -10,6 +10,7 @@
#define BOOST_THREAD_EXECUTORS_EXECUTOR_HPP
#include <boost/thread/detail/config.hpp>
#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION && defined BOOST_THREAD_PROVIDES_EXECUTORS && defined BOOST_THREAD_USES_MOVE
#include <boost/thread/detail/delete.hpp>
#include <boost/thread/detail/move.hpp>
@@ -146,3 +147,4 @@ namespace boost
#include <boost/config/abi_suffix.hpp>
#endif
#endif

View File

@@ -10,6 +10,7 @@
#define BOOST_THREAD_EXECUTORS_EXECUTOR_ADAPTOR_HPP
#include <boost/thread/detail/config.hpp>
#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION && defined BOOST_THREAD_PROVIDES_EXECUTORS && defined BOOST_THREAD_USES_MOVE
#include <boost/thread/executors/executor.hpp>
@@ -134,3 +135,4 @@ using executors::executor_adaptor;
#include <boost/config/abi_suffix.hpp>
#endif
#endif

View File

@@ -8,6 +8,7 @@
#define BOOST_THREAD_EXECUTORS_GENERIC_EXECUTOR_REF_HPP
#include <boost/thread/detail/config.hpp>
#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION && defined BOOST_THREAD_PROVIDES_EXECUTORS && defined BOOST_THREAD_USES_MOVE
#include <boost/thread/detail/delete.hpp>
#include <boost/thread/detail/move.hpp>
@@ -211,3 +212,4 @@ namespace boost
#include <boost/config/abi_suffix.hpp>
#endif
#endif

View File

@@ -10,9 +10,16 @@
#define BOOST_THREAD_INLINE_EXECUTOR_HPP
#include <boost/thread/detail/config.hpp>
#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION && defined BOOST_THREAD_PROVIDES_EXECUTORS && defined BOOST_THREAD_USES_MOVE
#include <exception> // std::terminate
#include <boost/throw_exception.hpp>
#include <boost/thread/detail/delete.hpp>
#include <boost/thread/detail/move.hpp>
#include <boost/thread/executors/work.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/lock_guard.hpp>
#include <boost/thread/concurrent_queues/queue_op_status.hpp> // sync_queue_is_closed
#include <boost/config/abi_prefix.hpp>
@@ -169,3 +176,4 @@ using executors::inline_executor;
#include <boost/config/abi_suffix.hpp>
#endif
#endif

View File

@@ -12,6 +12,9 @@
#define BOOST_THREAD_EXECUTORS_LOOP_EXECUTOR_HPP
#include <boost/thread/detail/config.hpp>
#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION && defined BOOST_THREAD_PROVIDES_EXECUTORS && defined BOOST_THREAD_USES_MOVE
#include <boost/thread/detail/delete.hpp>
#include <boost/thread/detail/move.hpp>
#include <boost/thread/concurrent_queues/sync_queue.hpp>
@@ -205,5 +208,6 @@ using executors::loop_executor;
}
#include <boost/config/abi_suffix.hpp>
#endif
#endif

View File

@@ -8,6 +8,9 @@
#ifndef BOOST_THREAD_EXECUTORS_SCHEDULED_THREAD_POOL_HPP
#define BOOST_THREAD_EXECUTORS_SCHEDULED_THREAD_POOL_HPP
#include <boost/thread/detail/config.hpp>
#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION && defined BOOST_THREAD_PROVIDES_EXECUTORS && defined BOOST_THREAD_USES_MOVE
#include <boost/thread/executors/detail/scheduled_executor_base.hpp>
namespace boost
@@ -32,6 +35,7 @@ namespace executors
~scheduled_thread_pool()
{
this->close();
_workers.interrupt_all();
_workers.join_all();
}
@@ -45,4 +49,5 @@ using executors::scheduled_thread_pool;
} //end boost
#endif
#endif

View File

@@ -8,6 +8,7 @@
#define BOOST_THREAD_EXECUTORS_SCHEDULER_HPP
#include <boost/thread/detail/config.hpp>
#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION && defined BOOST_THREAD_PROVIDES_EXECUTORS && defined BOOST_THREAD_USES_MOVE
#include <boost/thread/executors/detail/scheduled_executor_base.hpp>
#include <boost/chrono/time_point.hpp>
@@ -16,6 +17,11 @@
#include <boost/config/abi_prefix.hpp>
#if defined(BOOST_MSVC)
# pragma warning(push)
# pragma warning(disable: 4355) // 'this' : used in base member initializer list
#endif
namespace boost
{
namespace executors
@@ -231,6 +237,7 @@ namespace boost
~scheduler()
{
this->close();
thr.interrupt();
thr.join();
}
template <class Ex>
@@ -266,6 +273,11 @@ namespace boost
using executors::scheduler;
}
#if defined(BOOST_MSVC)
# pragma warning(pop)
#endif
#include <boost/config/abi_suffix.hpp>
#endif
#endif

View File

@@ -8,29 +8,37 @@
#ifndef BOOST_THREAD_EXECUTORS_SCHEDULING_ADAPTOR_HPP
#define BOOST_THREAD_EXECUTORS_SCHEDULING_ADAPTOR_HPP
#include <boost/thread/detail/config.hpp>
#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION && defined BOOST_THREAD_PROVIDES_EXECUTORS && defined BOOST_THREAD_USES_MOVE
#include <boost/thread/executors/detail/scheduled_executor_base.hpp>
#if defined(BOOST_MSVC)
# pragma warning(push)
# pragma warning(disable: 4355) // 'this' : used in base member initializer list
#endif
namespace boost
{
namespace executors
{
template <typename Executor>
class scheduling_adpator : public detail::scheduled_executor_base<>
class scheduling_adaptor : public detail::scheduled_executor_base<>
{
private:
Executor& _exec;
thread _scheduler;
public:
scheduling_adpator(Executor& ex)
scheduling_adaptor(Executor& ex)
: super(),
_exec(ex),
_scheduler(&super::loop, this) {}
~scheduling_adpator()
~scheduling_adaptor()
{
this->close();
_scheduler.interrupt();
_scheduler.join();
}
@@ -45,7 +53,13 @@ namespace executors
} //end executors
using executors::scheduling_adpator;
using executors::scheduling_adaptor;
} //end boost
#if defined(BOOST_MSVC)
# pragma warning(pop)
#endif
#endif
#endif

View File

@@ -10,6 +10,9 @@
#define BOOST_THREAD_SERIAL_EXECUTOR_HPP
#include <boost/thread/detail/config.hpp>
#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION && defined BOOST_THREAD_PROVIDES_EXECUTORS && defined BOOST_THREAD_USES_MOVE
#include <exception>
#include <boost/thread/detail/delete.hpp>
#include <boost/thread/detail/move.hpp>
#include <boost/thread/concurrent_queues/sync_queue.hpp>
@@ -20,6 +23,11 @@
#include <boost/config/abi_prefix.hpp>
#if defined(BOOST_MSVC)
# pragma warning(push)
# pragma warning(disable: 4355) // 'this' : used in base member initializer list
#endif
namespace boost
{
namespace executors
@@ -211,6 +219,11 @@ namespace executors
using executors::serial_executor;
}
#if defined(BOOST_MSVC)
# pragma warning(pop)
#endif
#include <boost/config/abi_suffix.hpp>
#endif
#endif

View File

@@ -10,13 +10,19 @@
#define BOOST_THREAD_SERIAL_EXECUTOR_CONT_HPP
#include <boost/thread/detail/config.hpp>
#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION && defined BOOST_THREAD_PROVIDES_EXECUTORS && defined BOOST_THREAD_USES_MOVE
#include <exception> // std::terminate
#include <boost/throw_exception.hpp>
#include <boost/thread/detail/delete.hpp>
#include <boost/thread/detail/move.hpp>
#include <boost/thread/concurrent_queues/sync_queue.hpp>
#include <boost/thread/executors/work.hpp>
#include <boost/thread/executors/generic_executor_ref.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/future.hpp>
#include <boost/thread/scoped_thread.hpp>
#include <boost/thread/lock_guard.hpp>
#include <boost/config/abi_prefix.hpp>
@@ -32,7 +38,7 @@ namespace executors
private:
generic_executor_ref ex_;
future<void> fut_; // protected by mtx_
BOOST_THREAD_FUTURE<void> fut_; // protected by mtx_
bool closed_; // protected by mtx_
mutex mtx_;
@@ -44,7 +50,7 @@ namespace executors
};
continuation(BOOST_THREAD_RV_REF(work) tsk)
: task(boost::move(tsk)) {}
void operator()(future<void> f)
void operator()(BOOST_THREAD_FUTURE<void> f)
{
try {
task();
@@ -168,3 +174,4 @@ using executors::serial_executor_cont;
#include <boost/config/abi_suffix.hpp>
#endif
#endif

View File

@@ -10,10 +10,15 @@
#define BOOST_THREAD_THREAD_EXECUTOR_HPP
#include <boost/thread/detail/config.hpp>
#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION && defined BOOST_THREAD_PROVIDES_EXECUTORS && defined BOOST_THREAD_USES_MOVE
#include <boost/throw_exception.hpp>
#include <boost/thread/detail/delete.hpp>
#include <boost/thread/detail/move.hpp>
#include <boost/thread/executors/work.hpp>
#include <boost/thread/executors/executor.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/lock_guard.hpp>
#include <boost/thread/thread_only.hpp>
#include <boost/thread/scoped_thread.hpp>
#include <boost/thread/csbl/vector.hpp>
@@ -155,3 +160,4 @@ using executors::thread_executor;
#include <boost/config/abi_suffix.hpp>
#endif
#endif

View File

@@ -8,6 +8,8 @@
#define BOOST_THREAD_EXECUTORS_WORK_HPP
#include <boost/thread/detail/config.hpp>
#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION && defined BOOST_THREAD_PROVIDES_EXECUTORS && defined BOOST_THREAD_USES_MOVE
#include <boost/thread/detail/nullary_function.hpp>
#include <boost/thread/csbl/functional.hpp>
@@ -26,5 +28,5 @@ namespace boost
}
} // namespace boost
#endif
#endif // BOOST_THREAD_EXECUTORS_WORK_HPP

View File

@@ -10,6 +10,9 @@
// See http://www.boost.org/libs/thread for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#include <exception>
#include <boost/throw_exception.hpp>
#include <boost/thread/detail/config.hpp>
#include <boost/thread/future.hpp>
@@ -18,6 +21,7 @@
#endif
#include <boost/thread/experimental/exception_list.hpp>
#include <boost/thread/experimental/parallel/v2/inline_namespace.hpp>
#include <boost/thread/csbl/vector.hpp>
#include <boost/thread/detail/move.hpp>
#include <boost/config/abi_prefix.hpp>
@@ -126,7 +130,7 @@ BOOST_THREAD_INLINE_NAMESPACE(v2)
for (group_type::iterator it = group.begin(); it != group.end(); ++it)
{
future<void>& f = *it;
BOOST_THREAD_FUTURE<void>& f = *it;
if (f.has_exception())
{
try
@@ -191,7 +195,7 @@ protected:
Executor* ex;
#endif
exception_list exs;
typedef csbl::vector<future<void> > group_type;
typedef csbl::vector<BOOST_THREAD_FUTURE<void> > group_type;
group_type group;
public:

View File

@@ -24,6 +24,7 @@
namespace boost
{
class mutex;
/**
* externally_locked cloaks an object of type T, and actually provides full

View File

@@ -15,7 +15,16 @@
//#define BOOST_THREAD_CONTINUATION_SYNC
#ifndef BOOST_NO_EXCEPTIONS
#ifdef BOOST_NO_EXCEPTIONS
namespace boost
{
namespace detail {
struct shared_state_base {
void notify_deferred() {}
};
}
}
#else
#include <boost/thread/condition_variable.hpp>
#include <boost/thread/detail/move.hpp>
@@ -109,6 +118,7 @@ namespace boost
namespace executors {
class executor;
}
using executors::executor;
#endif
typedef shared_ptr<executor> executor_ptr_type;
@@ -159,7 +169,7 @@ namespace boost
boost::function<void()> callback;
// This declaration should be only included conditionally, but is included to maintain the same layout.
continuations_type continuations;
executor_ptr_type ex;
executor_ptr_type ex_;
// This declaration should be only included conditionally, but is included to maintain the same layout.
virtual void launch_continuation()
@@ -173,43 +183,49 @@ namespace boost
is_constructed(false),
policy_(launch::none),
continuations(),
ex()
ex_()
{}
shared_state_base(exceptional_ptr const& ex_):
exception(ex_.ptr_),
shared_state_base(exceptional_ptr const& ex):
exception(ex.ptr_),
done(true),
is_valid_(true),
is_deferred_(false),
is_constructed(false),
policy_(launch::none),
continuations(),
ex()
ex_()
{}
virtual ~shared_state_base()
{
}
bool is_done()
{
return done;
}
executor_ptr_type get_executor()
{
return ex;
return ex_;
}
void set_executor_policy(executor_ptr_type aex)
{
set_executor();
ex = aex;
ex_ = aex;
}
void set_executor_policy(executor_ptr_type aex, boost::lock_guard<boost::mutex>&)
{
set_executor();
ex = aex;
ex_ = aex;
}
void set_executor_policy(executor_ptr_type aex, boost::unique_lock<boost::mutex>&)
{
set_executor();
ex = aex;
ex_ = aex;
}
bool valid(boost::unique_lock<boost::mutex>&) { return is_valid_; }
@@ -262,6 +278,10 @@ namespace boost
external_waiters.erase(it);
}
#if 0
// this inline definition results in ODR. See https://github.com/boostorg/thread/issues/193
// to avoid it, we define the function on the derived templates using the macro BOOST_THREAD_DO_CONTINUATION
#define BOOST_THREAD_DO_CONTINUATION
#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
void do_continuation(boost::unique_lock<boost::mutex>& lock)
{
@@ -279,6 +299,31 @@ namespace boost
{
}
#endif
#else
#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
#define BOOST_THREAD_DO_CONTINUATION \
void do_continuation(boost::unique_lock<boost::mutex>& lock) \
{ \
if (! this->continuations.empty()) { \
continuations_type the_continuations = this->continuations; \
this->continuations.clear(); \
relocker rlk(lock); \
for (continuations_type::iterator it = the_continuations.begin(); it != the_continuations.end(); ++it) { \
(*it)->launch_continuation(); \
} \
} \
}
#else
#define BOOST_THREAD_DO_CONTINUATION \
void do_continuation(boost::unique_lock<boost::mutex>&) \
{ \
}
#endif
virtual void do_continuation(boost::unique_lock<boost::mutex>&) = 0;
#endif
#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
virtual void set_continuation_ptr(continuation_ptr_type continuation, boost::unique_lock<boost::mutex>& lock)
{
@@ -299,7 +344,7 @@ namespace boost
}
do_continuation(lock);
}
void make_ready()
void notify_deferred()
{
boost::unique_lock<boost::mutex> lock(this->mutex);
mark_finished_internal(lock);
@@ -348,10 +393,7 @@ namespace boost
is_deferred_=false;
execute(lk);
}
while(!done)
{
waiters.wait(lk);
}
waiters.wait(lk, boost::bind(&shared_state_base::is_done, boost::ref(*this)));
if(rethrow && exception)
{
boost::rethrow_exception(exception);
@@ -370,6 +412,17 @@ namespace boost
}
#if defined BOOST_THREAD_USES_DATETIME
template<typename Duration>
bool timed_wait(Duration const& rel_time)
{
boost::unique_lock<boost::mutex> lock(this->mutex);
if (is_deferred_)
return false;
do_callback(lock);
return waiters.timed_wait(lock, rel_time, boost::bind(&shared_state_base::is_done, boost::ref(*this)));
}
bool timed_wait_until(boost::system_time const& target_time)
{
boost::unique_lock<boost::mutex> lock(this->mutex);
@@ -377,15 +430,7 @@ namespace boost
return false;
do_callback(lock);
while(!done)
{
bool const success=waiters.timed_wait(lock,target_time);
if(!success && !done)
{
return false;
}
}
return true;
return waiters.timed_wait(lock, target_time, boost::bind(&shared_state_base::is_done, boost::ref(*this)));
}
#endif
#ifdef BOOST_THREAD_USES_CHRONO
@@ -398,13 +443,9 @@ namespace boost
if (is_deferred_)
return future_status::deferred;
do_callback(lock);
while(!done)
if(!waiters.wait_until(lock, abs_time, boost::bind(&shared_state_base::is_done, boost::ref(*this))))
{
cv_status const st=waiters.wait_until(lock,abs_time);
if(st==cv_status::timeout && !done)
{
return future_status::timeout;
}
return future_status::timeout;
}
return future_status::ready;
}
@@ -421,7 +462,7 @@ namespace boost
mark_exceptional_finish_internal(boost::current_exception(), lock);
}
void set_exception_at_thread_exit(exception_ptr e)
void set_exception_deferred(exception_ptr e)
{
unique_lock<boost::mutex> lk(this->mutex);
if (has_value(lk))
@@ -430,6 +471,17 @@ namespace boost
}
exception=e;
this->is_constructed = true;
}
void set_exception_at_thread_exit(exception_ptr e)
{
set_exception_deferred(e);
// unique_lock<boost::mutex> lk(this->mutex);
// if (has_value(lk))
// {
// throw_exception(promise_already_satisfied());
// }
// exception=e;
// this->is_constructed = true;
detail::make_ready_at_thread_exit(shared_from_this());
}
@@ -535,10 +587,8 @@ namespace boost
detail::shared_state_base(ex), result()
{}
~shared_state()
{
}
// locating this definition on the template avoid the ODR issue. See https://github.com/boostorg/thread/issues/193
BOOST_THREAD_DO_CONTINUATION
void mark_finished_with_result_internal(source_reference_type result_, boost::unique_lock<boost::mutex>& lock)
{
@@ -617,8 +667,7 @@ namespace boost
boost::unique_lock<boost::mutex> lk(this->mutex);
return this->get_sh(lk);
}
void set_value_at_thread_exit(source_reference_type result_)
void set_value_deferred(source_reference_type result_)
{
unique_lock<boost::mutex> lk(this->mutex);
if (this->has_value(lk))
@@ -632,13 +681,14 @@ namespace boost
#endif
this->is_constructed = true;
detail::make_ready_at_thread_exit(shared_from_this());
}
void set_value_at_thread_exit(rvalue_source_type result_)
void set_value_deferred(rvalue_source_type result_)
{
unique_lock<boost::mutex> lk(this->mutex);
if (this->has_value(lk))
{
throw_exception(promise_already_satisfied());
}
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
#if defined BOOST_THREAD_FUTURE_USES_OPTIONAL
@@ -654,6 +704,46 @@ namespace boost
#endif
#endif
this->is_constructed = true;
}
void set_value_at_thread_exit(source_reference_type result_)
{
set_value_deferred(result_);
// unique_lock<boost::mutex> lk(this->mutex);
// if (this->has_value(lk))
// {
// throw_exception(promise_already_satisfied());
// }
//#if defined BOOST_THREAD_FUTURE_USES_OPTIONAL
// result = result_;
//#else
// result.reset(new T(result_));
//#endif
//
// this->is_constructed = true;
detail::make_ready_at_thread_exit(shared_from_this());
}
void set_value_at_thread_exit(rvalue_source_type result_)
{
set_value_deferred(boost::move(result_));
// unique_lock<boost::mutex> lk(this->mutex);
// if (this->has_value(lk))
// throw_exception(promise_already_satisfied());
//
//#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
//#if defined BOOST_THREAD_FUTURE_USES_OPTIONAL
// result = boost::move(result_);
//#else
// result.reset(new T(boost::move(result_)));
//#endif
//#else
//#if defined BOOST_THREAD_FUTURE_USES_OPTIONAL
// result = boost::move(result_);
//#else
// result.reset(new T(static_cast<rvalue_source_type>(result_)));
//#endif
//#endif
// this->is_constructed = true;
detail::make_ready_at_thread_exit(shared_from_this());
}
@@ -681,9 +771,8 @@ namespace boost
detail::shared_state_base(ex), result(0)
{}
~shared_state()
{
}
// locating this definition on the template avoid the ODR issue. See https://github.com/boostorg/thread/issues/193
BOOST_THREAD_DO_CONTINUATION
void mark_finished_with_result_internal(source_reference_type result_, boost::unique_lock<boost::mutex>& lock)
{
@@ -719,13 +808,25 @@ namespace boost
return get_sh(lock);
}
void set_value_at_thread_exit(T& result_)
void set_value_deferred(T& result_)
{
unique_lock<boost::mutex> lk(this->mutex);
if (this->has_value(lk))
{
throw_exception(promise_already_satisfied());
}
result= &result_;
this->is_constructed = true;
}
void set_value_at_thread_exit(T& result_)
{
set_value_deferred(result_);
// unique_lock<boost::mutex> lk(this->mutex);
// if (this->has_value(lk))
// throw_exception(promise_already_satisfied());
// result= &result_;
// this->is_constructed = true;
detail::make_ready_at_thread_exit(shared_from_this());
}
@@ -748,6 +849,9 @@ namespace boost
detail::shared_state_base(ex)
{}
// locating this definition on the template avoid the ODR issue. See https://github.com/boostorg/thread/issues/193
BOOST_THREAD_DO_CONTINUATION
void mark_finished_with_result_internal(boost::unique_lock<boost::mutex>& lock)
{
mark_finished_internal(lock);
@@ -779,7 +883,7 @@ namespace boost
this->get_sh(lock);
}
void set_value_at_thread_exit()
void set_value_deferred()
{
unique_lock<boost::mutex> lk(this->mutex);
if (this->has_value(lk))
@@ -787,6 +891,16 @@ namespace boost
throw_exception(promise_already_satisfied());
}
this->is_constructed = true;
}
void set_value_at_thread_exit()
{
set_value_deferred();
// unique_lock<boost::mutex> lk(this->mutex);
// if (this->has_value(lk))
// {
// throw_exception(promise_already_satisfied());
// }
// this->is_constructed = true;
detail::make_ready_at_thread_exit(shared_from_this());
}
private:
@@ -826,10 +940,7 @@ namespace boost
join();
#elif defined BOOST_THREAD_ASYNC_FUTURE_WAITS
unique_lock<boost::mutex> lk(this->mutex);
while(!this->done)
{
this->waiters.wait(lk);
}
this->waiters.wait(lk, boost::bind(&shared_state_base::is_done, boost::ref(*this)));
#endif
}
@@ -934,10 +1045,8 @@ namespace boost
template<typename Rp, typename Fp>
struct future_deferred_shared_state: shared_state<Rp>
{
typedef shared_state<Rp> base_type;
Fp func_;
public:
explicit future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f)
: func_(boost::move(f))
{
@@ -962,10 +1071,8 @@ namespace boost
template<typename Rp, typename Fp>
struct future_deferred_shared_state<Rp&,Fp>: shared_state<Rp&>
{
typedef shared_state<Rp&> base_type;
Fp func_;
public:
explicit future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f)
: func_(boost::move(f))
{
@@ -987,10 +1094,8 @@ namespace boost
template<typename Fp>
struct future_deferred_shared_state<void,Fp>: shared_state<void>
{
typedef shared_state<void> base_type;
Fp func_;
public:
explicit future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f)
: func_(boost::move(f))
{
@@ -1018,7 +1123,6 @@ namespace boost
public:
typedef std::vector<int>::size_type count_type;
private:
struct registered_waiter;
struct registered_waiter
{
boost::shared_ptr<detail::shared_state_base> future_;
@@ -1335,7 +1439,7 @@ namespace boost
bool valid() const BOOST_NOEXCEPT
{
return future_ != 0 && future_->valid();
return future_.get() != 0 && future_->valid();
}
void wait() const
@@ -1379,7 +1483,11 @@ namespace boost
template<typename Duration>
bool timed_wait(Duration const& rel_time) const
{
return timed_wait_until(boost::get_system_time()+rel_time);
if(!future_)
{
boost::throw_exception(future_uninitialized());
}
return future_->timed_wait(rel_time);
}
bool timed_wait_until(boost::system_time const& abs_time) const
@@ -1639,7 +1747,9 @@ namespace boost
base_type(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))))
{
}
#if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
inline explicit BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R> >) other); // EXTENSION
#endif
explicit BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(shared_future<R>) other) :
base_type(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))))
@@ -1680,7 +1790,7 @@ namespace boost
// retrieving the value
move_dest_type get()
{
if (this->future_ == 0)
if (this->future_.get() == 0)
{
boost::throw_exception(future_uninitialized());
}
@@ -1700,7 +1810,7 @@ namespace boost
get_or(BOOST_THREAD_RV_REF(R2) v)
{
if (this->future_ == 0)
if (this->future_.get() == 0)
{
boost::throw_exception(future_uninitialized());
}
@@ -1726,7 +1836,7 @@ namespace boost
typename boost::disable_if< is_void<R2>, move_dest_type>::type
get_or(R2 const& v) // EXTENSION
{
if (this->future_ == 0)
if (this->future_.get() == 0)
{
boost::throw_exception(future_uninitialized());
}
@@ -1941,7 +2051,7 @@ namespace boost
// retrieving the value
move_dest_type get()
{
if (this->future_ == 0)
if (this->future_.get() == 0)
{
boost::throw_exception(future_uninitialized());
}
@@ -1957,7 +2067,7 @@ namespace boost
}
move_dest_type get_or(BOOST_THREAD_RV_REF(R) v) // EXTENSION
{
if (this->future_ == 0)
if (this->future_.get() == 0)
{
boost::throw_exception(future_uninitialized());
}
@@ -1976,7 +2086,7 @@ namespace boost
move_dest_type get_or(R const& v) // EXTENSION
{
if (this->future_ == 0)
if (this->future_.get() == 0)
{
boost::throw_exception(future_uninitialized());
}
@@ -2163,13 +2273,13 @@ namespace boost
void lazy_init()
{
#if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
#include <boost/detail/atomic_undef_macros.hpp>
#include <boost/thread/detail/atomic_undef_macros.hpp>
if(!atomic_load(&future_))
{
future_ptr blank;
atomic_compare_exchange(&future_,&blank,future_ptr(new detail::shared_state<R>));
}
#include <boost/detail/atomic_redef_macros.hpp>
#include <boost/thread/detail/atomic_redef_macros.hpp>
#endif
}
@@ -2261,7 +2371,8 @@ namespace boost
#if defined BOOST_NO_CXX11_RVALUE_REFERENCES
template <class TR>
typename boost::enable_if_c<is_copy_constructible<TR>::value && is_same<R, TR>::value, void>::type set_value(TR const & r)
typename boost::enable_if_c<is_copy_constructible<TR>::value && is_same<R, TR>::value, void>::type
set_value(TR const & r)
{
lazy_init();
boost::unique_lock<boost::mutex> lock(future_->mutex);
@@ -2299,6 +2410,44 @@ namespace boost
#endif
}
#if defined BOOST_NO_CXX11_RVALUE_REFERENCES
template <class TR>
typename boost::enable_if_c<is_copy_constructible<TR>::value && is_same<R, TR>::value, void>::type
set_value_deferred(TR const & r)
{
lazy_init();
if (future_.get()==0)
{
boost::throw_exception(promise_moved());
}
future_->set_value_deferred(r);
}
#else
void set_value_deferred(source_reference_type r)
{
lazy_init();
if (future_.get()==0)
{
boost::throw_exception(promise_moved());
}
future_->set_value_deferred(r);
}
#endif
void set_value_deferred(rvalue_source_type r)
{
lazy_init();
if (future_.get()==0)
{
boost::throw_exception(promise_moved());
}
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
future_->set_value_deferred(boost::move(r));
#else
future_->set_value_deferred(static_cast<rvalue_source_type>(r));
#endif
}
#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <class ...Args>
void emplace(BOOST_THREAD_FWD_REF(Args) ...args)
@@ -2329,6 +2478,21 @@ namespace boost
{
set_exception(boost::copy_exception(ex));
}
void set_exception_deferred(boost::exception_ptr p)
{
lazy_init();
if (future_.get()==0)
{
boost::throw_exception(promise_moved());
}
future_->set_exception_deferred(p);
}
template <typename E>
void set_exception_deferred(E ex)
{
set_exception_deferred(boost::copy_exception(ex));
}
// setting the result with deferred notification
#if defined BOOST_NO_CXX11_RVALUE_REFERENCES
template <class TR>
@@ -2378,6 +2542,14 @@ namespace boost
lazy_init();
future_->set_wait_callback(f,this);
}
void notify_deferred()
{
if (future_.get()==0)
{
boost::throw_exception(promise_moved());
}
future_->notify_deferred();
}
};
@@ -2392,13 +2564,13 @@ namespace boost
void lazy_init()
{
#if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
#include <boost/detail/atomic_undef_macros.hpp>
#include <boost/thread/detail/atomic_undef_macros.hpp>
if(!atomic_load(&future_))
{
future_ptr blank;
atomic_compare_exchange(&future_,&blank,future_ptr(new detail::shared_state<R&>));
}
#include <boost/detail/atomic_redef_macros.hpp>
#include <boost/thread/detail/atomic_redef_macros.hpp>
#endif
}
@@ -2486,7 +2658,15 @@ namespace boost
}
future_->mark_finished_with_result_internal(r, lock);
}
void set_value_deferred(R& r)
{
lazy_init();
if (future_.get()==0)
{
boost::throw_exception(promise_already_satisfied());
}
future_->set_value_deferred(r);
}
void set_exception(boost::exception_ptr p)
{
lazy_init();
@@ -2502,7 +2682,20 @@ namespace boost
{
set_exception(boost::copy_exception(ex));
}
void set_exception_deferred(boost::exception_ptr p)
{
lazy_init();
if (future_.get()==0)
{
boost::throw_exception(promise_moved());
}
future_->set_exception_deferred(p);
}
template <typename E>
void set_exception_deferred(E ex)
{
set_exception_deferred(boost::copy_exception(ex));
}
// setting the result with deferred notification
void set_value_at_thread_exit(R& r)
{
@@ -2533,6 +2726,14 @@ namespace boost
lazy_init();
future_->set_wait_callback(f,this);
}
void notify_deferred()
{
if (future_.get()==0)
{
boost::throw_exception(promise_moved());
}
future_->notify_deferred();
}
};
template <>
@@ -2642,6 +2843,15 @@ namespace boost
}
future_->mark_finished_with_result_internal(lock);
}
void set_value_deferred()
{
lazy_init();
if (future_.get()==0)
{
boost::throw_exception(promise_moved());
}
future_->set_value_deferred();
}
void set_exception(boost::exception_ptr p)
{
@@ -2658,7 +2868,20 @@ namespace boost
{
set_exception(boost::copy_exception(ex));
}
void set_exception_deferred(boost::exception_ptr p)
{
lazy_init();
if (future_.get()==0)
{
boost::throw_exception(promise_moved());
}
future_->set_exception_deferred(p);
}
template <typename E>
void set_exception_deferred(E ex)
{
set_exception_deferred(boost::copy_exception(ex));
}
// setting the result with deferred notification
void set_value_at_thread_exit()
{
@@ -2689,7 +2912,14 @@ namespace boost
lazy_init();
future_->set_wait_callback(f,this);
}
void notify_deferred()
{
if (future_.get()==0)
{
boost::throw_exception(promise_moved());
}
future_->notify_deferred();
}
};
}
#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
@@ -2960,7 +3190,7 @@ namespace boost
}
};
#if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR)
#if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNCTION_PTR)
#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
@@ -3302,7 +3532,7 @@ namespace boost
{}
// construction and destruction
#if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR)
#if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNCTION_PTR)
#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
@@ -3392,7 +3622,7 @@ namespace boost
#endif
#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
#if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR)
#if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNCTION_PTR)
template <class Allocator>
packaged_task(boost::allocator_arg_t, Allocator a, R(*f)())
{
@@ -3413,7 +3643,7 @@ namespace boost
task = task_ptr(::new(a2.allocate(1)) task_shared_state_type(f), D(a2, 1) );
future_obtained = false;
}
#endif // BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR
#endif // BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNCTION_PTR
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
template <class F, class Allocator>
@@ -3630,7 +3860,7 @@ namespace detail
// future<R> async(launch policy, F&&, ArgTypes&&...);
////////////////////////////////
#if defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR
#if defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNCTION_PTR
#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
template <class R, class... ArgTypes>
@@ -3689,7 +3919,7 @@ namespace detail
}
}
#endif
#endif // defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR)
#endif // defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNCTION_PTR)
#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
@@ -3918,7 +4148,7 @@ namespace detail {
//#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
#if defined(BOOST_THREAD_PROVIDES_INVOKE) && ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && ! defined(BOOST_NO_CXX11_HDR_TUPLE)
#if defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR
#if defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNCTION_PTR
template <class Executor, class R, class... ArgTypes>
BOOST_THREAD_FUTURE<R>
@@ -3934,7 +4164,7 @@ namespace detail {
)
));
}
#endif // defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR
#endif // defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNCTION_PTR
template <class Executor, class F, class ...ArgTypes>
BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type(
@@ -3953,7 +4183,7 @@ namespace detail {
}
#else // ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
#if defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR
#if defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNCTION_PTR
template <class Executor, class R>
BOOST_THREAD_FUTURE<R>
@@ -3983,7 +4213,7 @@ namespace detail {
)
));
}
#endif // defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR
#endif // defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNCTION_PTR
template <class Executor, class F>
BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type()>::type>
@@ -4039,7 +4269,7 @@ namespace detail {
// future<R> async(F&&, ArgTypes&&...);
////////////////////////////////
#if defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR
#if defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNCTION_PTR
#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
template <class R, class... ArgTypes>
BOOST_THREAD_FUTURE<R>
@@ -4747,7 +4977,7 @@ namespace detail {
inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type>
BOOST_THREAD_FUTURE<R>::then(launch policy, BOOST_THREAD_FWD_REF(F) func) {
typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type;
BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
BOOST_THREAD_ASSERT_PRECONDITION(this->future_.get()!=0, future_uninitialized());
// keep state alive as we move ourself but hold the lock
shared_ptr<detail::shared_state_base> sentinel(this->future_);
@@ -4761,6 +4991,10 @@ namespace detail {
return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_deferred_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
lock, boost::move(*this), boost::forward<F>(func)
)));
} else if (underlying_cast<int>(policy) & int(launch::sync)) {
return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_sync_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
lock, boost::move(*this), boost::forward<F>(func)
)));
#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
} else if (underlying_cast<int>(policy) & int(launch::executor)) {
assert(this->future_->get_executor());
@@ -4781,6 +5015,10 @@ namespace detail {
return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_deferred_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
lock, boost::move(*this), boost::forward<F>(func)
)));
} else if (underlying_cast<int>(policy_) & int(launch::sync)) {
return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_sync_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type>(
lock, boost::move(*this), boost::forward<F>(func)
)));
#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
} else if (underlying_cast<int>(policy_) & int(launch::executor)) {
assert(this->future_->get_executor());
@@ -4811,7 +5049,7 @@ namespace detail {
inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type>
BOOST_THREAD_FUTURE<R>::then(Ex& ex, BOOST_THREAD_FWD_REF(F) func) {
typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type;
BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
BOOST_THREAD_ASSERT_PRECONDITION(this->future_.get()!=0, future_uninitialized());
// keep state alive as we move ourself but hold the lock
shared_ptr<detail::shared_state_base> sentinel(this->future_);
@@ -4835,7 +5073,7 @@ namespace detail {
return this->then(this->launch_policy(), boost::forward<F>(func));
#else
typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type;
BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
BOOST_THREAD_ASSERT_PRECONDITION(this->future_.get()!=0, future_uninitialized());
// keep state alive as we move ourself but hold the lock
shared_ptr<detail::shared_state_base> sentinel(this->future_);
@@ -4865,7 +5103,7 @@ namespace detail {
BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >::then(launch policy, BOOST_THREAD_FWD_REF(F) func) {
typedef BOOST_THREAD_FUTURE<R2> R;
typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type;
BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
BOOST_THREAD_ASSERT_PRECONDITION(this->future_.get()!=0, future_uninitialized());
// keep state alive as we move ourself but hold the lock
shared_ptr<detail::shared_state_base> sentinel(this->future_);
@@ -4939,7 +5177,7 @@ namespace detail {
BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >::then(Ex& ex, BOOST_THREAD_FWD_REF(F) func) {
typedef BOOST_THREAD_FUTURE<R2> R;
typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type;
BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
BOOST_THREAD_ASSERT_PRECONDITION(this->future_.get()!=0, future_uninitialized());
// keep state alive as we move ourself but hold the lock
shared_ptr<detail::shared_state_base> sentinel(this->future_);
@@ -4965,7 +5203,7 @@ namespace detail {
#else
typedef BOOST_THREAD_FUTURE<R2> R;
typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type;
BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
BOOST_THREAD_ASSERT_PRECONDITION(this->future_.get()!=0, future_uninitialized());
// keep state alive as we move ourself but hold the lock
shared_ptr<detail::shared_state_base> sentinel(this->future_);
@@ -4995,7 +5233,7 @@ namespace detail {
shared_future<R>::then(launch policy, BOOST_THREAD_FWD_REF(F) func) const
{
typedef typename boost::result_of<F(shared_future<R>)>::type future_type;
BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
BOOST_THREAD_ASSERT_PRECONDITION(this->future_.get()!=0, future_uninitialized());
boost::unique_lock<boost::mutex> lock(this->future_->mutex);
if (underlying_cast<int>(policy) & int(launch::async)) {
@@ -5064,7 +5302,7 @@ namespace detail {
shared_future<R>::then(Ex& ex, BOOST_THREAD_FWD_REF(F) func) const
{
typedef typename boost::result_of<F(shared_future<R>)>::type future_type;
BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
BOOST_THREAD_ASSERT_PRECONDITION(this->future_.get()!=0, future_uninitialized());
boost::unique_lock<boost::mutex> lock(this->future_->mutex);
return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_executor_continuation_shared_state<Ex, shared_future<R>, future_type>(ex,
@@ -5085,7 +5323,7 @@ namespace detail {
return this->then(this->launch_policy(), boost::forward<F>(func));
#else
typedef typename boost::result_of<F(shared_future<R>)>::type future_type;
BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
BOOST_THREAD_ASSERT_PRECONDITION(this->future_.get()!=0, future_uninitialized());
boost::unique_lock<boost::mutex> lock(this->future_->mutex);
launch policy = this->launch_policy(lock);
@@ -5257,7 +5495,7 @@ namespace detail
BOOST_THREAD_FUTURE<R2>
BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >::unwrap()
{
BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
BOOST_THREAD_ASSERT_PRECONDITION(this->future_.get()!=0, future_uninitialized());
// keep state alive as we move ourself but hold the lock
shared_ptr<detail::shared_state_base> sentinel(this->future_);

View File

@@ -14,6 +14,7 @@
#include <boost/thread/futures/is_future_type.hpp>
#include <boost/thread/lock_algorithms.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/condition_variable.hpp>
#include <boost/core/enable_if.hpp>
#include <boost/next_prior.hpp>

View File

@@ -0,0 +1,22 @@
// (C) Copyright 2013 Vicente J. Botet Escriba
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_THREAD_INTERRUPTION_HPP
#define BOOST_THREAD_INTERRUPTION_HPP
#include <boost/thread/detail/config.hpp>
namespace boost
{
namespace this_thread
{
void BOOST_THREAD_DECL interruption_point();
bool BOOST_THREAD_DECL interruption_enabled() BOOST_NOEXCEPT;
bool BOOST_THREAD_DECL interruption_requested() BOOST_NOEXCEPT;
}
}
#endif // header

View File

@@ -23,7 +23,7 @@ namespace boost
{
template <typename Mutex>
class lock_guard
class BOOST_THREAD_SCOPED_CAPABILITY lock_guard
{
private:
Mutex& m;
@@ -32,13 +32,13 @@ namespace boost
typedef Mutex mutex_type;
BOOST_THREAD_NO_COPYABLE( lock_guard )
explicit lock_guard(Mutex& m_) :
explicit lock_guard(Mutex& m_) BOOST_THREAD_ACQUIRE(m_) :
m(m_)
{
m.lock();
}
lock_guard(Mutex& m_, adopt_lock_t) :
lock_guard(Mutex& m_, adopt_lock_t) BOOST_THREAD_REQUIRES(m_) :
m(m_)
{
#if ! defined BOOST_THREAD_PROVIDES_NESTED_LOCKS
@@ -62,7 +62,7 @@ namespace boost
}
#endif
~lock_guard()
~lock_guard() BOOST_THREAD_RELEASE()
{
m.unlock();
}

View File

@@ -11,7 +11,12 @@
#include <boost/assert.hpp>
#include <boost/detail/workaround.hpp>
#include <boost/type_traits/integral_constant.hpp>
#ifdef BOOST_NO_CXX11_SFINAE_EXPR
#include <boost/type_traits/is_class.hpp>
#else
#include <boost/type_traits/declval.hpp>
#endif
#include <boost/config/abi_prefix.hpp>
@@ -33,6 +38,7 @@ namespace boost
#ifndef BOOST_THREAD_NO_AUTO_DETECT_MUTEX_TYPES
namespace detail
{
#ifdef BOOST_NO_CXX11_SFINAE_EXPR
#define BOOST_THREAD_DEFINE_HAS_MEMBER_CALLED(member_name) \
template<typename T, bool=boost::is_class<T>::value> \
struct has_member_called_##member_name \
@@ -142,6 +148,31 @@ namespace boost
BOOST_STATIC_CONSTANT(
bool,value=sizeof(has_member_try_lock<T>::has_member(&T::try_lock))==sizeof(true_type));
};
#else
template<typename T,typename Enabled=void>
struct has_member_lock : false_type {};
template<typename T>
struct has_member_lock<T,
decltype(void(boost::declval<T&>().lock()))
> : true_type {};
template<typename T,typename Enabled=void>
struct has_member_unlock : false_type {};
template<typename T>
struct has_member_unlock<T,
decltype(void(boost::declval<T&>().unlock()))
> : true_type {};
template<typename T,typename Enabled=bool>
struct has_member_try_lock : false_type {};
template<typename T>
struct has_member_try_lock<T,
decltype(bool(boost::declval<T&>().try_lock()))
> : true_type {};
#endif
}

View File

@@ -10,6 +10,12 @@
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/thread/detail/config.hpp>
#ifdef BOOST_MSVC
# pragma warning(push)
# pragma warning(disable: 4702) // unreachable code
#endif
#include <boost/thread/detail/platform.hpp>
#if defined(BOOST_THREAD_PLATFORM_WIN32)
#include <boost/thread/win32/once.hpp>
@@ -41,4 +47,8 @@ inline void call_once(Function func,once_flag& flag)
#include <boost/config/abi_suffix.hpp>
#ifdef BOOST_MSVC
# pragma warning(pop)
#endif
#endif

View File

@@ -30,6 +30,9 @@ namespace boost
};
//]
// A proper name for basic_poly_lockable, consistent with naming scheme of other polymorphic wrappers
typedef basic_poly_lockable poly_basic_lockable;
//[poly_lockable
class poly_lockable : public basic_poly_lockable
{
@@ -51,18 +54,20 @@ namespace boost
template <typename Clock, typename Duration>
bool try_lock_until(chrono::time_point<Clock, Duration> const & abs_time)
{
return try_lock_until(time_point_cast<Clock::time_point>(abs_time));
return try_lock_until(chrono::time_point_cast<Clock::time_point>(abs_time));
}
virtual bool try_lock_for(chrono::nanoseconds const & relative_time)=0;
template <typename Rep, typename Period>
bool try_lock_for(chrono::duration<Rep, Period> const & rel_time)
{
return try_lock_for(duration_cast<Clock::duration>(rel_time));
return try_lock_for(chrono::duration_cast<chrono::nanoseconds>(rel_time));
}
};
//]
// A proper name for timed_poly_lockable, consistent with naming scheme of other polymorphic wrappers
typedef timed_poly_lockable poly_timed_lockable;
}
#endif

View File

@@ -33,20 +33,22 @@ namespace boost
template <typename Clock, typename Duration>
bool try_lock_shared_until(chrono::time_point<Clock, Duration> const & abs_time)
{
return try_lock_shared_until(time_point_cast<Clock::time_point>(abs_time));
return try_lock_shared_until(chrono::time_point_cast<Clock::time_point>(abs_time));
}
virtual bool try_lock_shared_for(chrono::nanoseconds const & relative_time)=0;
template <typename Rep, typename Period>
bool try_lock_shared_for(chrono::duration<Rep, Period> const & rel_time)
{
return try_lock_shared_for(duration_cast<Clock::duration>(rel_time));
return try_lock_shared_for(chrono::duration_cast<chrono::nanoseconds>(rel_time));
}
};
//]
// A proper name for shared_poly_lockable, consistent with naming scheme of other polymorphic wrappers
typedef shared_poly_lockable poly_shared_lockable;
//[upgrade_poly_lockable
class upgrade_poly_lockable: public shared_poly_lockable
{
@@ -62,14 +64,14 @@ namespace boost
template <typename Clock, typename Duration>
bool try_lock_upgrade_until(chrono::time_point<Clock, Duration> const & abs_time)
{
return try_lock_upgrade_until(time_point_cast<Clock::time_point>(abs_time));
return try_lock_upgrade_until(chrono::time_point_cast<Clock::time_point>(abs_time));
}
virtual bool try_lock_upgrade_for(chrono::nanoseconds const & relative_time)=0;
template <typename Rep, typename Period>
bool try_lock_upgrade_for(chrono::duration<Rep, Period> const & rel_time)
{
return try_lock_upgrade_for(duration_cast<Clock::duration>(rel_time));
return try_lock_upgrade_for(chrono::duration_cast<chrono::nanoseconds>(rel_time));
}
virtual bool try_unlock_shared_and_lock() = 0;
@@ -79,14 +81,14 @@ namespace boost
template <typename Clock, typename Duration>
bool try_unlock_shared_and_lock_until(chrono::time_point<Clock, Duration> const & abs_time)
{
return try_unlock_shared_and_lock_until(time_point_cast<Clock::time_point>(abs_time));
return try_unlock_shared_and_lock_until(chrono::time_point_cast<Clock::time_point>(abs_time));
}
virtual bool try_unlock_shared_and_lock_for(chrono::nanoseconds const & relative_time)=0;
template <typename Rep, typename Period>
bool try_unlock_shared_and_lock_for(chrono::duration<Rep, Period> const & rel_time)
{
return try_unlock_shared_and_lock_for(duration_cast<Clock::duration>(rel_time));
return try_unlock_shared_and_lock_for(chrono::duration_cast<chrono::nanoseconds>(rel_time));
}
virtual void unlock_and_lock_shared() = 0;
@@ -97,14 +99,14 @@ namespace boost
template <typename Clock, typename Duration>
bool try_unlock_shared_and_lock_upgrade_until(chrono::time_point<Clock, Duration> const & abs_time)
{
return try_unlock_shared_and_lock_upgrade_until(time_point_cast<Clock::time_point>(abs_time));
return try_unlock_shared_and_lock_upgrade_until(chrono::time_point_cast<Clock::time_point>(abs_time));
}
virtual bool try_unlock_shared_and_lock_upgrade_for(chrono::nanoseconds const & relative_time)=0;
template <typename Rep, typename Period>
bool try_unlock_shared_and_lock_upgrade_for(chrono::duration<Rep, Period> const & rel_time)
{
return try_unlock_shared_and_lock_upgrade_for(duration_cast<Clock::duration>(rel_time));
return try_unlock_shared_and_lock_upgrade_for(chrono::duration_cast<chrono::nanoseconds>(rel_time));
}
virtual void unlock_and_lock_upgrade() = 0;
@@ -116,20 +118,22 @@ namespace boost
template <typename Clock, typename Duration>
bool try_unlock_upgrade_and_lock_until(chrono::time_point<Clock, Duration> const & abs_time)
{
return try_unlock_upgrade_and_lock_until(time_point_cast<Clock::time_point>(abs_time));
return try_unlock_upgrade_and_lock_until(chrono::time_point_cast<Clock::time_point>(abs_time));
}
virtual bool try_unlock_upgrade_and_lock_for(chrono::nanoseconds const & relative_time)=0;
template <typename Rep, typename Period>
bool try_unlock_upgrade_and_lock_for(chrono::duration<Rep, Period> const & rel_time)
{
return try_unlock_upgrade_and_lock_for(duration_cast<Clock::duration>(rel_time));
return try_unlock_upgrade_and_lock_for(chrono::duration_cast<chrono::nanoseconds>(rel_time));
}
virtual void unlock_upgrade_and_lock_shared() = 0;
};
//]
//]
// A proper name for upgrade_poly_lockable, consistent with naming scheme of other polymorphic wrappers
typedef upgrade_poly_lockable poly_upgrade_lockable;
}
#endif

View File

@@ -17,7 +17,7 @@
namespace boost
{
//[shared_lockable_adapter
//[poly_shared_lockable_adapter
template <typename Mutex, typename Base=poly_shared_lockable>
class poly_shared_lockable_adapter: public poly_timed_lockable_adapter<Mutex, Base>
{
@@ -54,9 +54,9 @@ namespace boost
//]
//[upgrade_lockable_adapter
//[poly_upgrade_lockable_adapter
template <typename Mutex, typename Base=poly_shared_lockable>
class upgrade_lockable_adapter: public shared_lockable_adapter<Mutex, Base>
class poly_upgrade_lockable_adapter: public poly_shared_lockable_adapter<Mutex, Base>
{
public:
typedef Mutex mutex_type;
@@ -102,7 +102,6 @@ namespace boost
{
return this->mtx().try_unlock_shared_and_lock_until(abs_time);
}
template <typename Rep, typename Period>
bool try_unlock_shared_and_lock_for(chrono::nanoseconds const & rel_time)
{
return this->mtx().try_unlock_shared_and_lock_for(rel_time);

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

View File

@@ -13,13 +13,20 @@
#include <boost/thread/detail/config.hpp>
#if defined(BOOST_THREAD_PLATFORM_WIN32)
#if defined(BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN)
#if defined(BOOST_THREAD_V2_SHARED_MUTEX)
#include <boost/thread/v2/shared_mutex.hpp>
#else
#include <boost/thread/pthread/shared_mutex.hpp>
#endif
#else
#include <boost/thread/win32/shared_mutex.hpp>
#endif
#elif defined(BOOST_THREAD_PLATFORM_PTHREAD)
//#include <boost/thread/v2/shared_mutex.hpp>
#if defined(BOOST_THREAD_V2_SHARED_MUTEX)
#include <boost/thread/v2/shared_mutex.hpp>
#else
#include <boost/thread/pthread/shared_mutex.hpp>
#endif
#else
#error "Boost threads unavailable on this platform"
#endif

View File

@@ -23,7 +23,7 @@
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
#include <boost/thread/detail/thread_interruption.hpp>
#endif
#include <boost/thread/v2/thread.hpp>
#include <boost/thread/condition_variable.hpp>
#endif

View File

@@ -6,8 +6,8 @@
// (C) Copyright 2007-8 Anthony Williams
#include <boost/thread/detail/config.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/thread/detail/thread_heap_alloc.hpp>
#include <boost/type_traits/add_reference.hpp>
#include <boost/config/abi_prefix.hpp>
@@ -15,15 +15,13 @@ namespace boost
{
namespace detail
{
struct tss_cleanup_function
namespace thread
{
virtual ~tss_cleanup_function()
{}
typedef void(*cleanup_func_t)(void*);
typedef void(*cleanup_caller_t)(cleanup_func_t, void*);
}
virtual void operator()(void* data)=0;
};
BOOST_THREAD_DECL void set_tss_data(void const* key,boost::shared_ptr<tss_cleanup_function> func,void* tss_data,bool cleanup_existing);
BOOST_THREAD_DECL void set_tss_data(void const* key,detail::thread::cleanup_caller_t caller,detail::thread::cleanup_func_t func,void* tss_data,bool cleanup_existing);
BOOST_THREAD_DECL void* get_tss_data(void const* key);
}
@@ -34,49 +32,33 @@ namespace boost
thread_specific_ptr(thread_specific_ptr&);
thread_specific_ptr& operator=(thread_specific_ptr&);
struct delete_data:
detail::tss_cleanup_function
typedef void(*original_cleanup_func_t)(T*);
static void default_deleter(T* data)
{
void operator()(void* data)
{
delete static_cast<T*>(data);
}
};
delete data;
}
struct run_custom_cleanup_function:
detail::tss_cleanup_function
static void cleanup_caller(detail::thread::cleanup_func_t cleanup_function,void* data)
{
void (*cleanup_function)(T*);
explicit run_custom_cleanup_function(void (*cleanup_function_)(T*)):
cleanup_function(cleanup_function_)
{}
void operator()(void* data)
{
cleanup_function(static_cast<T*>(data));
}
};
reinterpret_cast<original_cleanup_func_t>(cleanup_function)(static_cast<T*>(data));
}
boost::shared_ptr<detail::tss_cleanup_function> cleanup;
detail::thread::cleanup_func_t cleanup;
public:
typedef T element_type;
thread_specific_ptr():
cleanup(detail::heap_new<delete_data>(),detail::do_heap_delete<delete_data>())
cleanup(reinterpret_cast<detail::thread::cleanup_func_t>(&default_deleter))
{}
explicit thread_specific_ptr(void (*func_)(T*))
{
if(func_)
{
cleanup.reset(detail::heap_new<run_custom_cleanup_function>(func_),detail::do_heap_delete<run_custom_cleanup_function>());
}
}
: cleanup(reinterpret_cast<detail::thread::cleanup_func_t>(func_))
{}
~thread_specific_ptr()
{
detail::set_tss_data(this,boost::shared_ptr<detail::tss_cleanup_function>(),0,true);
detail::set_tss_data(this,0,0,0,true);
}
T* get() const
@@ -87,14 +69,14 @@ namespace boost
{
return get();
}
typename boost::detail::sp_dereference< T >::type operator*() const
typename add_reference<T>::type operator*() const
{
return *get();
}
T* release()
{
T* const temp=get();
detail::set_tss_data(this,boost::shared_ptr<detail::tss_cleanup_function>(),0,false);
detail::set_tss_data(this,0,0,0,false);
return temp;
}
void reset(T* new_value=0)
@@ -102,7 +84,7 @@ namespace boost
T* const current_value=get();
if(current_value!=new_value)
{
detail::set_tss_data(this,cleanup,new_value,true);
detail::set_tss_data(this,&cleanup_caller,cleanup,new_value,true);
}
}
};

View File

@@ -10,6 +10,8 @@
#define BOOST_THREAD_USER_SCHEDULER_HPP
#include <boost/thread/detail/config.hpp>
#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION && defined BOOST_THREAD_PROVIDES_EXECUTORS && defined BOOST_THREAD_USES_MOVE
#include <boost/thread/detail/delete.hpp>
#include <boost/thread/detail/move.hpp>
#include <boost/thread/concurrent_queues/sync_queue.hpp>
@@ -200,3 +202,4 @@ namespace boost
#include <boost/config/abi_suffix.hpp>
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,155 +0,0 @@
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// (C) Copyright 2011 Vicente J. Botet Escriba
#ifndef BOOST_THREAD_V2_THREAD_HPP
#define BOOST_THREAD_V2_THREAD_HPP
#include <boost/thread/detail/config.hpp>
#ifdef BOOST_THREAD_USES_CHRONO
#include <boost/chrono/system_clocks.hpp>
#include <boost/chrono/ceil.hpp>
#endif
#include <boost/thread/condition_variable.hpp>
#include <boost/thread/lock_types.hpp>
namespace boost
{
namespace this_thread
{
namespace no_interruption_point
{
#ifdef BOOST_THREAD_USES_CHRONO
template <class Clock, class Duration>
void sleep_until(const chrono::time_point<Clock, Duration>& t)
{
using namespace chrono;
mutex mut;
condition_variable cv;
unique_lock<mutex> lk(mut);
while (Clock::now() < t)
cv.wait_until(lk, t);
}
#ifdef BOOST_THREAD_SLEEP_FOR_IS_STEADY
template <class Rep, class Period>
void sleep_for(const chrono::duration<Rep, Period>& d)
{
using namespace chrono;
if (d > duration<Rep, Period>::zero())
{
duration<long double> Max = nanoseconds::max BOOST_PREVENT_MACRO_SUBSTITUTION ();
nanoseconds ns;
if (d < Max)
{
ns = duration_cast<nanoseconds>(d);
if (ns < d)
++ns;
}
else
ns = nanoseconds:: max BOOST_PREVENT_MACRO_SUBSTITUTION ();
sleep_for(ns);
}
}
template <class Duration>
inline BOOST_SYMBOL_VISIBLE
void sleep_until(const chrono::time_point<chrono::steady_clock, Duration>& t)
{
using namespace chrono;
sleep_for(t - steady_clock::now());
}
#else
template <class Rep, class Period>
void sleep_for(const chrono::duration<Rep, Period>& d)
{
using namespace chrono;
if (d > duration<Rep, Period>::zero())
{
steady_clock::time_point c_timeout = steady_clock::now() + ceil<nanoseconds>(d);
sleep_until(c_timeout);
}
}
#endif
#endif
}
#ifdef BOOST_THREAD_USES_CHRONO
template <class Clock, class Duration>
void sleep_until(const chrono::time_point<Clock, Duration>& t)
{
using namespace chrono;
mutex mut;
condition_variable cv;
unique_lock<mutex> lk(mut);
while (Clock::now() < t)
cv.wait_until(lk, t);
}
#if defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC && defined BOOST_CHRONO_HAS_CLOCK_STEADY
template <class Rep, class Period>
void sleep_for(const chrono::duration<Rep, Period>& d)
{
using namespace chrono;
if (d > duration<Rep, Period>::zero())
{
steady_clock::time_point c_timeout = steady_clock::now() + ceil<nanoseconds>(d);
sleep_until(c_timeout);
}
}
#elif defined BOOST_THREAD_SLEEP_FOR_IS_STEADY
template <class Rep, class Period>
void sleep_for(const chrono::duration<Rep, Period>& d)
{
using namespace chrono;
if (d > duration<Rep, Period>::zero())
{
duration<long double> Max = nanoseconds::max BOOST_PREVENT_MACRO_SUBSTITUTION ();
nanoseconds ns;
if (d < Max)
{
ns = duration_cast<nanoseconds>(d);
if (ns < d)
++ns;
}
else
ns = nanoseconds:: max BOOST_PREVENT_MACRO_SUBSTITUTION ();
sleep_for(ns);
}
}
template <class Duration>
inline BOOST_SYMBOL_VISIBLE
void sleep_until(const chrono::time_point<chrono::steady_clock, Duration>& t)
{
using namespace chrono;
sleep_for(t - steady_clock::now());
}
#else
template <class Rep, class Period>
void sleep_for(const chrono::duration<Rep, Period>& d)
{
using namespace chrono;
if (d > duration<Rep, Period>::zero())
{
//system_clock::time_point c_timeout = time_point_cast<system_clock::duration>(system_clock::now() + ceil<nanoseconds>(d));
system_clock::time_point c_timeout = system_clock::now() + ceil<system_clock::duration>(d);
sleep_until(c_timeout);
}
}
#endif
#endif
}
}
#endif

View File

@@ -4,7 +4,7 @@
// basic_recursive_mutex.hpp
//
// (C) Copyright 2006-8 Anthony Williams
// (C) Copyright 2011-2012 Vicente J. Botet Escriba
// (C) Copyright 2011-2012,2017-2018 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
@@ -44,13 +44,13 @@ namespace boost
bool try_lock() BOOST_NOEXCEPT
{
long const current_thread_id=win32::GetCurrentThreadId();
long const current_thread_id=boost::winapi::GetCurrentThreadId();
return try_recursive_lock(current_thread_id) || try_basic_lock(current_thread_id);
}
void lock()
{
long const current_thread_id=win32::GetCurrentThreadId();
long const current_thread_id=boost::winapi::GetCurrentThreadId();
if(!try_recursive_lock(current_thread_id))
{
mutex.lock();
@@ -61,29 +61,30 @@ namespace boost
#if defined BOOST_THREAD_USES_DATETIME
bool timed_lock(::boost::system_time const& target)
{
long const current_thread_id=win32::GetCurrentThreadId();
long const current_thread_id=boost::winapi::GetCurrentThreadId();
return try_recursive_lock(current_thread_id) || try_timed_lock(current_thread_id,target);
}
template<typename Duration>
bool timed_lock(Duration const& timeout)
bool timed_lock(Duration const& target)
{
return timed_lock(get_system_time()+timeout);
long const current_thread_id=boost::winapi::GetCurrentThreadId();
return try_recursive_lock(current_thread_id) || try_timed_lock(current_thread_id,target);
}
#endif
#ifdef BOOST_THREAD_USES_CHRONO
template <class Rep, class Period>
bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)
{
long const current_thread_id=win32::GetCurrentThreadId();
template <class Rep, class Period>
bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)
{
long const current_thread_id=boost::winapi::GetCurrentThreadId();
return try_recursive_lock(current_thread_id) || try_timed_lock_for(current_thread_id,rel_time);
}
template <class Clock, class Duration>
bool try_lock_until(const chrono::time_point<Clock, Duration>& t)
{
long const current_thread_id=win32::GetCurrentThreadId();
}
template <class Clock, class Duration>
bool try_lock_until(const chrono::time_point<Clock, Duration>& t)
{
long const current_thread_id=boost::winapi::GetCurrentThreadId();
return try_recursive_lock(current_thread_id) || try_timed_lock_until(current_thread_id,t);
}
}
#endif
void unlock()
{
@@ -127,6 +128,17 @@ namespace boost
}
return false;
}
template<typename Duration>
bool try_timed_lock(long current_thread_id,Duration const& target)
{
if(mutex.timed_lock(target))
{
BOOST_INTERLOCKED_EXCHANGE(&locking_thread_id,current_thread_id);
recursion_count=1;
return true;
}
return false;
}
#endif
template <typename TP>
bool try_timed_lock_until(long current_thread_id,TP const& target)

View File

@@ -22,6 +22,8 @@
#include <boost/chrono/system_clocks.hpp>
#include <boost/chrono/ceil.hpp>
#endif
#include <boost/thread/detail/platform_time.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
@@ -55,11 +57,11 @@ namespace boost
#endif
if(old_event)
{
win32::CloseHandle(old_event);
winapi::CloseHandle(old_event);
}
}
// Take the lock flag if it's available
bool try_lock() BOOST_NOEXCEPT
{
return !win32::interlocked_bit_test_and_set(&active_count,lock_flag_bit);
@@ -76,21 +78,21 @@ namespace boost
if(old_count&lock_flag_value)
{
bool lock_acquired=false;
void* const sem=get_event();
do
{
unsigned const retval(win32::WaitForSingleObjectEx(sem, ::boost::detail::win32::infinite,0));
BOOST_VERIFY(0 == retval || ::boost::detail::win32::wait_abandoned == retval);
// BOOST_VERIFY(win32::WaitForSingleObject(
// sem,::boost::detail::win32::infinite)==0);
clear_waiting_and_try_lock(old_count);
lock_acquired=!(old_count&lock_flag_value);
if(winapi::WaitForSingleObjectEx(sem,::boost::detail::win32::infinite,0)==0)
{
clear_waiting_and_try_lock(old_count);
}
}
while(!lock_acquired);
while(old_count&lock_flag_value);
}
}
// Loop until the number of waiters has been incremented or we've taken the lock flag
// The loop is necessary since this function may be called by multiple threads simultaneously
void mark_waiting_and_try_lock(long& old_count)
{
for(;;)
@@ -102,12 +104,19 @@ namespace boost
{
if(was_locked)
old_count=new_count;
// else we've taken the lock flag
// don't update old_count so that the calling function can see that
// the old lock flag was 0 and know that we've taken the lock flag
break;
}
old_count=current;
}
}
// Loop until someone else has taken the lock flag and cleared the event set flag or
// until we've taken the lock flag and cleared the event set flag and decremented the
// number of waiters
// The loop is necessary since this function may be called by multiple threads simultaneously
void clear_waiting_and_try_lock(long& old_count)
{
old_count&=~lock_flag_value;
@@ -118,126 +127,135 @@ namespace boost
long const current=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&active_count,new_count,old_count);
if(current==old_count)
{
// if someone else has taken the lock flag
// no need to update old_count since old_count == new_count (ignoring
// event_set_flag_value which the calling function doesn't care about)
// else we've taken the lock flag
// don't update old_count so that the calling function can see that
// the old lock flag was 0 and know that we've taken the lock flag
break;
}
old_count=current;
}
}
private:
unsigned long getMs(detail::platform_duration const& d)
{
return static_cast<unsigned long>(d.getMs());
}
#if defined BOOST_THREAD_USES_DATETIME
bool timed_lock(::boost::system_time const& wait_until)
template <typename Duration>
unsigned long getMs(Duration const& d)
{
return static_cast<unsigned long>(chrono::ceil<chrono::milliseconds>(d).count());
}
template <typename Clock, typename Timepoint, typename Duration>
bool do_lock_until(Timepoint const& t, Duration const& max)
{
if(try_lock())
{
return true;
}
long old_count=active_count;
mark_waiting_and_try_lock(old_count);
if(old_count&lock_flag_value)
{
bool lock_acquired=false;
void* const sem=get_event();
// If the clock is the system clock, it may jump while this function
// is waiting. To compensate for this and time out near the correct
// time, we call WaitForSingleObjectEx() in a loop with a short
// timeout and recheck the time remaining each time through the loop.
do
{
if(win32::WaitForSingleObjectEx(sem,::boost::detail::get_milliseconds_until(wait_until),0)!=0)
Duration d(t - Clock::now());
if(d <= Duration::zero()) // timeout occurred
{
BOOST_INTERLOCKED_DECREMENT(&active_count);
return false;
}
clear_waiting_and_try_lock(old_count);
lock_acquired=!(old_count&lock_flag_value);
if(max != Duration::zero())
{
d = (std::min)(d, max);
}
if(winapi::WaitForSingleObjectEx(sem,getMs(d),0)==0)
{
clear_waiting_and_try_lock(old_count);
}
}
while(!lock_acquired);
while(old_count&lock_flag_value);
}
return true;
}
public:
#if defined BOOST_THREAD_USES_DATETIME
bool timed_lock(::boost::system_time const& wait_until)
{
const detail::real_platform_timepoint t(wait_until);
return do_lock_until<detail::real_platform_clock>(t, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
}
template<typename Duration>
bool timed_lock(Duration const& timeout)
{
return timed_lock(get_system_time()+timeout);
const detail::mono_platform_timepoint t(detail::mono_platform_clock::now() + detail::platform_duration(timeout));
// The reference clock is steady and so no need to poll periodically, thus 0 ms max (i.e. no max)
return do_lock_until<detail::mono_platform_clock>(t, detail::platform_duration::zero());
}
bool timed_lock(boost::xtime const& timeout)
{
return timed_lock(system_time(timeout));
return timed_lock(boost::system_time(timeout));
}
#endif
#ifdef BOOST_THREAD_USES_CHRONO
template <class Rep, class Period>
bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)
{
return try_lock_until(chrono::steady_clock::now() + rel_time);
const chrono::steady_clock::time_point t(chrono::steady_clock::now() + rel_time);
typedef typename chrono::duration<Rep, Period> Duration;
typedef typename common_type<Duration, typename chrono::steady_clock::duration>::type common_duration;
// The reference clock is steady and so no need to poll periodically, thus 0 ms max (i.e. no max)
return do_lock_until<chrono::steady_clock>(t, common_duration::zero());
}
template <class Duration>
bool try_lock_until(const chrono::time_point<chrono::steady_clock, Duration>& t)
{
typedef typename common_type<Duration, typename chrono::steady_clock::duration>::type common_duration;
// The reference clock is steady and so no need to poll periodically, thus 0 ms max (i.e. no max)
return do_lock_until<chrono::steady_clock>(t, common_duration::zero());
}
template <class Clock, class Duration>
bool try_lock_until(const chrono::time_point<Clock, Duration>& t)
{
using namespace chrono;
system_clock::time_point s_now = system_clock::now();
typename Clock::time_point c_now = Clock::now();
return try_lock_until(s_now + ceil<system_clock::duration>(t - c_now));
}
template <class Duration>
bool try_lock_until(const chrono::time_point<chrono::system_clock, Duration>& t)
{
using namespace chrono;
typedef time_point<chrono::system_clock, chrono::system_clock::duration> sys_tmpt;
return try_lock_until(sys_tmpt(chrono::ceil<chrono::system_clock::duration>(t.time_since_epoch())));
}
bool try_lock_until(const chrono::time_point<chrono::system_clock, chrono::system_clock::duration>& tp)
{
if(try_lock())
{
return true;
}
long old_count=active_count;
mark_waiting_and_try_lock(old_count);
if(old_count&lock_flag_value)
{
bool lock_acquired=false;
void* const sem=get_event();
do
{
chrono::time_point<chrono::system_clock, chrono::system_clock::duration> now = chrono::system_clock::now();
if (tp<=now) {
BOOST_INTERLOCKED_DECREMENT(&active_count);
return false;
}
chrono::milliseconds rel_time= chrono::ceil<chrono::milliseconds>(tp-now);
if(win32::WaitForSingleObjectEx(sem,static_cast<unsigned long>(rel_time.count()),0)!=0)
{
BOOST_INTERLOCKED_DECREMENT(&active_count);
return false;
}
clear_waiting_and_try_lock(old_count);
lock_acquired=!(old_count&lock_flag_value);
}
while(!lock_acquired);
}
return true;
typedef typename common_type<Duration, typename Clock::duration>::type common_duration;
return do_lock_until<Clock>(t, common_duration(chrono::milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS)));
}
#endif
void unlock()
{
long const offset=lock_flag_value;
// Clear the lock flag using atomic addition (works since long is always 32 bits on Windows)
long const old_count=BOOST_INTERLOCKED_EXCHANGE_ADD(&active_count,lock_flag_value);
if(!(old_count&event_set_flag_value) && (old_count>offset))
// If someone is waiting to take the lock, set the event set flag and, if
// the event set flag hadn't already been set, send an event.
if(!(old_count&event_set_flag_value) && (old_count>lock_flag_value))
{
if(!win32::interlocked_bit_test_and_set(&active_count,event_set_flag_bit))
{
win32::SetEvent(get_event());
winapi::SetEvent(get_event());
}
}
}
private:
// Create an event in a thread-safe way
// The first thread to create the event wins and all other thread will use that event
void* get_event()
{
void* current_event=::boost::detail::interlocked_read_acquire(&event);
@@ -256,7 +274,7 @@ namespace boost
#endif
if(old_event!=0)
{
win32::CloseHandle(new_event);
winapi::CloseHandle(new_event);
return old_event;
}
else

View File

@@ -18,6 +18,7 @@
#include <boost/thread/thread_time.hpp>
#include <boost/thread/lock_guard.hpp>
#include <boost/thread/lock_types.hpp>
#include <boost/thread/detail/platform_time.hpp>
#include <boost/assert.hpp>
#include <boost/intrusive_ptr.hpp>
@@ -76,7 +77,7 @@ namespace boost
void release(unsigned count_to_release)
{
notified=true;
detail::win32::ReleaseSemaphore(semaphore,count_to_release,0);
winapi::ReleaseSemaphore(semaphore,count_to_release,0);
}
void release_waiters()
@@ -89,14 +90,14 @@ namespace boost
return notified;
}
bool wait(timeout abs_time)
bool interruptible_wait(detail::internal_platform_timepoint const &timeout)
{
return this_thread::interruptible_wait(semaphore,abs_time);
return this_thread::interruptible_wait(semaphore, timeout);
}
bool woken()
{
unsigned long const woken_result=detail::win32::WaitForSingleObjectEx(wake_sem,0,0);
unsigned long const woken_result=winapi::WaitForSingleObjectEx(wake_sem,0,0);
BOOST_ASSERT((woken_result==detail::win32::timeout) || (woken_result==0));
return woken_result==0;
}
@@ -135,39 +136,45 @@ namespace boost
void wake_waiters(long count_to_wake)
{
detail::interlocked_write_release(&total_count,total_count-count_to_wake);
detail::win32::ReleaseSemaphore(wake_sem,count_to_wake,0);
winapi::ReleaseSemaphore(wake_sem,count_to_wake,0);
}
template<typename lock_type>
struct relocker
{
BOOST_THREAD_NO_COPYABLE(relocker)
lock_type& lock;
bool unlocked;
lock_type& _lock;
bool _unlocked;
relocker(lock_type& lock_):
lock(lock_),unlocked(false)
_lock(lock_), _unlocked(false)
{}
void unlock()
{
lock.unlock();
unlocked=true;
if ( ! _unlocked )
{
_lock.unlock();
_unlocked=true;
}
}
~relocker()
void lock()
{
if(unlocked)
{
lock.lock();
}
if ( _unlocked )
{
_lock.lock();
_unlocked=false;
}
}
~relocker() BOOST_NOEXCEPT_IF(false)
{
lock();
}
};
entry_ptr get_wait_entry()
{
boost::lock_guard<boost::mutex> internal_lock(internal_mutex);
boost::lock_guard<boost::mutex> lk(internal_mutex);
if(!wake_sem)
{
wake_sem=detail::win32::create_anonymous_semaphore(0,LONG_MAX);
@@ -190,18 +197,32 @@ namespace boost
struct entry_manager
{
entry_ptr const entry;
entry_ptr entry;
boost::mutex& internal_mutex;
BOOST_THREAD_NO_COPYABLE(entry_manager)
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
entry_manager(entry_ptr&& entry_, boost::mutex& mutex_):
entry(static_cast< entry_ptr&& >(entry_)), internal_mutex(mutex_)
{}
#else
entry_manager(entry_ptr const& entry_, boost::mutex& mutex_):
entry(entry_), internal_mutex(mutex_)
{}
#endif
~entry_manager()
void remove_waiter_and_reset()
{
if (entry) {
boost::lock_guard<boost::mutex> internal_lock(internal_mutex);
entry->remove_waiter();
entry.reset();
}
}
~entry_manager() BOOST_NOEXCEPT_IF(false)
{
remove_waiter_and_reset();
}
list_entry* operator->()
@@ -210,41 +231,7 @@ namespace boost
}
};
protected:
template<typename lock_type>
bool do_wait(lock_type& lock,timeout abs_time)
{
relocker<lock_type> locker(lock);
entry_manager entry(get_wait_entry(), internal_mutex);
locker.unlock();
bool woken=false;
while(!woken)
{
if(!entry->wait(abs_time))
{
return false;
}
woken=entry->woken();
}
return woken;
}
template<typename lock_type,typename predicate_type>
bool do_wait(lock_type& m,timeout const& abs_time,predicate_type pred)
{
while (!pred())
{
if(!do_wait(m, abs_time))
return pred();
}
return true;
}
basic_condition_variable(const basic_condition_variable& other);
basic_condition_variable& operator=(const basic_condition_variable& other);
@@ -256,6 +243,38 @@ namespace boost
~basic_condition_variable()
{}
// When this function returns true:
// * A notification (or sometimes a spurious OS signal) has been received
// * Do not assume that the timeout has not been reached
// * Do not assume that the predicate has been changed
//
// When this function returns false:
// * The timeout has been reached
// * Do not assume that a notification has not been received
// * Do not assume that the predicate has not been changed
template<typename lock_type>
bool do_wait_until(lock_type& lock, detail::internal_platform_timepoint const &timeout)
{
relocker<lock_type> locker(lock);
entry_manager entry(get_wait_entry(), internal_mutex);
locker.unlock();
bool woken=false;
while(!woken)
{
if(!entry->interruptible_wait(timeout))
{
return false;
}
woken=entry->woken();
}
// do it here to avoid throwing on the destructor
entry.remove_waiter_and_reset();
locker.lock();
return true;
}
void notify_one() BOOST_NOEXCEPT
{
if(detail::interlocked_read_acquire(&total_count))
@@ -309,75 +328,115 @@ namespace boost
condition_variable()
{}
using detail::basic_condition_variable::do_wait_until;
using detail::basic_condition_variable::notify_one;
using detail::basic_condition_variable::notify_all;
void wait(unique_lock<mutex>& m)
{
do_wait(m,detail::timeout::sentinel());
do_wait_until(m, detail::internal_platform_timepoint::getMax());
}
template<typename predicate_type>
void wait(unique_lock<mutex>& m,predicate_type pred)
{
while(!pred()) wait(m);
while (!pred())
{
wait(m);
}
}
#if defined BOOST_THREAD_USES_DATETIME
bool timed_wait(unique_lock<mutex>& m,boost::system_time const& abs_time)
{
return do_wait(m,abs_time);
// The system time may jump while this function is waiting. To compensate for this and time
// out near the correct time, we could call do_wait_until() in a loop with a short timeout
// and recheck the time remaining each time through the loop. However, because we can't
// check the predicate each time do_wait_until() completes, this introduces the possibility
// of not exiting the function when a notification occurs, since do_wait_until() may report
// that it timed out even though a notification was received. The best this function can do
// is report correctly whether or not it reached the timeout time.
const detail::real_platform_timepoint ts(abs_time);
const detail::platform_duration d(ts - detail::real_platform_clock::now());
do_wait_until(m, detail::internal_platform_clock::now() + d);
return ts > detail::real_platform_clock::now();
}
bool timed_wait(unique_lock<mutex>& m,boost::xtime const& abs_time)
{
return do_wait(m,system_time(abs_time));
return timed_wait(m, system_time(abs_time));
}
template<typename duration_type>
bool timed_wait(unique_lock<mutex>& m,duration_type const& wait_duration)
{
if (wait_duration.is_pos_infinity())
{
wait(m); // or do_wait(m,detail::timeout::sentinel());
return true;
}
if (wait_duration.is_special())
{
return true;
}
return do_wait(m,wait_duration.total_milliseconds());
if (wait_duration.is_pos_infinity())
{
wait(m);
return true;
}
if (wait_duration.is_special())
{
return true;
}
const detail::platform_duration d(wait_duration);
return do_wait_until(m, detail::internal_platform_clock::now() + d);
}
template<typename predicate_type>
bool timed_wait(unique_lock<mutex>& m,boost::system_time const& abs_time,predicate_type pred)
{
return do_wait(m,abs_time,pred);
// The system time may jump while this function is waiting. To compensate for this
// and time out near the correct time, we call do_wait_until() in a loop with a
// short timeout and recheck the time remaining each time through the loop.
const detail::real_platform_timepoint ts(abs_time);
while (!pred())
{
detail::platform_duration d(ts - detail::real_platform_clock::now());
if (d <= detail::platform_duration::zero()) break; // timeout occurred
d = (std::min)(d, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
do_wait_until(m, detail::internal_platform_clock::now() + d);
}
return pred();
}
template<typename predicate_type>
bool timed_wait(unique_lock<mutex>& m,boost::xtime const& abs_time,predicate_type pred)
{
return do_wait(m,system_time(abs_time),pred);
return timed_wait(m, system_time(abs_time), pred);
}
template<typename duration_type,typename predicate_type>
bool timed_wait(unique_lock<mutex>& m,duration_type const& wait_duration,predicate_type pred)
{
if (wait_duration.is_pos_infinity())
{
while (!pred())
{
wait(m); // or do_wait(m,detail::timeout::sentinel());
}
return true;
while (!pred())
{
wait(m);
}
return true;
}
if (wait_duration.is_special())
{
return pred();
return pred();
}
return do_wait(m,wait_duration.total_milliseconds(),pred);
const detail::platform_duration d(wait_duration);
const detail::internal_platform_timepoint ts(detail::internal_platform_clock::now() + d);
while (!pred())
{
if (!do_wait_until(m, ts)) break; // timeout occurred
}
return pred();
}
#endif
#ifdef BOOST_THREAD_USES_CHRONO
template <class Duration>
cv_status
wait_until(
unique_lock<mutex>& lock,
const chrono::time_point<detail::internal_chrono_clock, Duration>& t)
{
const detail::internal_platform_timepoint ts(t);
if (do_wait_until(lock, ts)) return cv_status::no_timeout;
else return cv_status::timeout;
}
template <class Clock, class Duration>
cv_status
@@ -385,14 +444,18 @@ namespace boost
unique_lock<mutex>& lock,
const chrono::time_point<Clock, Duration>& t)
{
using namespace chrono;
chrono::time_point<Clock, Duration> now = Clock::now();
if (t<=now) {
return cv_status::timeout;
}
do_wait(lock, ceil<milliseconds>(t-now).count());
return Clock::now() < t ? cv_status::no_timeout :
cv_status::timeout;
// The system time may jump while this function is waiting. To compensate for this and time
// out near the correct time, we could call do_wait_until() in a loop with a short timeout
// and recheck the time remaining each time through the loop. However, because we can't
// check the predicate each time do_wait_until() completes, this introduces the possibility
// of not exiting the function when a notification occurs, since do_wait_until() may report
// that it timed out even though a notification was received. The best this function can do
// is report correctly whether or not it reached the timeout time.
typedef typename common_type<Duration, typename Clock::duration>::type common_duration;
common_duration d(t - Clock::now());
do_wait_until(lock, detail::internal_chrono_clock::now() + d);
if (t > Clock::now()) return cv_status::no_timeout;
else return cv_status::timeout;
}
template <class Rep, class Period>
@@ -401,15 +464,22 @@ namespace boost
unique_lock<mutex>& lock,
const chrono::duration<Rep, Period>& d)
{
using namespace chrono;
if (d<=chrono::duration<Rep, Period>::zero()) {
return cv_status::timeout;
}
return wait_until(lock, chrono::steady_clock::now() + d);
}
steady_clock::time_point c_now = steady_clock::now();
do_wait(lock, ceil<milliseconds>(d).count());
return steady_clock::now() - c_now < d ? cv_status::no_timeout :
cv_status::timeout;
template <class Duration, class Predicate>
bool
wait_until(
unique_lock<mutex>& lock,
const chrono::time_point<detail::internal_chrono_clock, Duration>& t,
Predicate pred)
{
const detail::internal_platform_timepoint ts(t);
while (!pred())
{
if (!do_wait_until(lock, ts)) break; // timeout occurred
}
return pred();
}
template <class Clock, class Duration, class Predicate>
@@ -419,13 +489,20 @@ namespace boost
const chrono::time_point<Clock, Duration>& t,
Predicate pred)
{
// The system time may jump while this function is waiting. To compensate for this
// and time out near the correct time, we call do_wait_until() in a loop with a
// short timeout and recheck the time remaining each time through the loop.
typedef typename common_type<Duration, typename Clock::duration>::type common_duration;
while (!pred())
{
if (wait_until(lock, t) == cv_status::timeout)
return pred();
common_duration d(t - Clock::now());
if (d <= common_duration::zero()) break; // timeout occurred
d = (std::min)(d, common_duration(chrono::milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS)));
do_wait_until(lock, detail::internal_platform_clock::now() + detail::platform_duration(d));
}
return true;
return pred();
}
template <class Rep, class Period, class Predicate>
bool
wait_for(
@@ -446,59 +523,122 @@ namespace boost
condition_variable_any()
{}
using detail::basic_condition_variable::do_wait_until;
using detail::basic_condition_variable::notify_one;
using detail::basic_condition_variable::notify_all;
template<typename lock_type>
void wait(lock_type& m)
{
do_wait(m,detail::timeout::sentinel());
do_wait_until(m, detail::internal_platform_timepoint::getMax());
}
template<typename lock_type,typename predicate_type>
void wait(lock_type& m,predicate_type pred)
{
while(!pred()) wait(m);
while (!pred())
{
wait(m);
}
}
#if defined BOOST_THREAD_USES_DATETIME
template<typename lock_type>
bool timed_wait(lock_type& m,boost::system_time const& abs_time)
{
return do_wait(m,abs_time);
// The system time may jump while this function is waiting. To compensate for this and time
// out near the correct time, we could call do_wait_until() in a loop with a short timeout
// and recheck the time remaining each time through the loop. However, because we can't
// check the predicate each time do_wait_until() completes, this introduces the possibility
// of not exiting the function when a notification occurs, since do_wait_until() may report
// that it timed out even though a notification was received. The best this function can do
// is report correctly whether or not it reached the timeout time.
const detail::real_platform_timepoint ts(abs_time);
const detail::platform_duration d(ts - detail::real_platform_clock::now());
do_wait_until(m, detail::internal_platform_clock::now() + d);
return ts > detail::real_platform_clock::now();
}
template<typename lock_type>
bool timed_wait(lock_type& m,boost::xtime const& abs_time)
{
return do_wait(m,system_time(abs_time));
return timed_wait(m, system_time(abs_time));
}
template<typename lock_type,typename duration_type>
bool timed_wait(lock_type& m,duration_type const& wait_duration)
{
return do_wait(m,wait_duration.total_milliseconds());
if (wait_duration.is_pos_infinity())
{
wait(m);
return true;
}
if (wait_duration.is_special())
{
return true;
}
const detail::platform_duration d(wait_duration);
return do_wait_until(m, detail::internal_platform_clock::now() + d);
}
template<typename lock_type,typename predicate_type>
bool timed_wait(lock_type& m,boost::system_time const& abs_time,predicate_type pred)
{
return do_wait(m,abs_time,pred);
// The system time may jump while this function is waiting. To compensate for this
// and time out near the correct time, we call do_wait_until() in a loop with a
// short timeout and recheck the time remaining each time through the loop.
const detail::real_platform_timepoint ts(abs_time);
while (!pred())
{
detail::platform_duration d(ts - detail::real_platform_clock::now());
if (d <= detail::platform_duration::zero()) break; // timeout occurred
d = (std::min)(d, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
do_wait_until(m, detail::internal_platform_clock::now() + d);
}
return pred();
}
template<typename lock_type,typename predicate_type>
bool timed_wait(lock_type& m,boost::xtime const& abs_time,predicate_type pred)
{
return do_wait(m,system_time(abs_time),pred);
return timed_wait(m, system_time(abs_time), pred);
}
template<typename lock_type,typename duration_type,typename predicate_type>
bool timed_wait(lock_type& m,duration_type const& wait_duration,predicate_type pred)
{
return do_wait(m,wait_duration.total_milliseconds(),pred);
if (wait_duration.is_pos_infinity())
{
while (!pred())
{
wait(m);
}
return true;
}
if (wait_duration.is_special())
{
return pred();
}
const detail::platform_duration d(wait_duration);
const detail::internal_platform_timepoint ts(detail::internal_platform_clock::now() + d);
while (!pred())
{
if (!do_wait_until(m, ts)) break; // timeout occurred
}
return pred();
}
#endif
#ifdef BOOST_THREAD_USES_CHRONO
template <class lock_type,class Duration>
cv_status
wait_until(
lock_type& lock,
const chrono::time_point<detail::internal_chrono_clock, Duration>& t)
{
const detail::internal_platform_timepoint ts(t);
if (do_wait_until(lock, ts)) return cv_status::no_timeout;
else return cv_status::timeout;
}
template <class lock_type, class Clock, class Duration>
cv_status
@@ -506,14 +646,18 @@ namespace boost
lock_type& lock,
const chrono::time_point<Clock, Duration>& t)
{
using namespace chrono;
chrono::time_point<Clock, Duration> now = Clock::now();
if (t<=now) {
return cv_status::timeout;
}
do_wait(lock, ceil<milliseconds>(t-now).count());
return Clock::now() < t ? cv_status::no_timeout :
cv_status::timeout;
// The system time may jump while this function is waiting. To compensate for this and time
// out near the correct time, we could call do_wait_until() in a loop with a short timeout
// and recheck the time remaining each time through the loop. However, because we can't
// check the predicate each time do_wait_until() completes, this introduces the possibility
// of not exiting the function when a notification occurs, since do_wait_until() may report
// that it timed out even though a notification was received. The best this function can do
// is report correctly whether or not it reached the timeout time.
typedef typename common_type<Duration, typename Clock::duration>::type common_duration;
common_duration d(t - Clock::now());
do_wait_until(lock, detail::internal_chrono_clock::now() + d);
if (t > Clock::now()) return cv_status::no_timeout;
else return cv_status::timeout;
}
template <class lock_type, class Rep, class Period>
@@ -522,14 +666,22 @@ namespace boost
lock_type& lock,
const chrono::duration<Rep, Period>& d)
{
using namespace chrono;
if (d<=chrono::duration<Rep, Period>::zero()) {
return cv_status::timeout;
}
steady_clock::time_point c_now = steady_clock::now();
do_wait(lock, ceil<milliseconds>(d).count());
return steady_clock::now() - c_now < d ? cv_status::no_timeout :
cv_status::timeout;
return wait_until(lock, chrono::steady_clock::now() + d);
}
template <class lock_type, class Clock, class Duration, class Predicate>
bool
wait_until(
lock_type& lock,
const chrono::time_point<detail::internal_chrono_clock, Duration>& t,
Predicate pred)
{
const detail::internal_platform_timepoint ts(t);
while (!pred())
{
if (!do_wait_until(lock, ts)) break; // timeout occurred
}
return pred();
}
template <class lock_type, class Clock, class Duration, class Predicate>
@@ -539,12 +691,18 @@ namespace boost
const chrono::time_point<Clock, Duration>& t,
Predicate pred)
{
// The system time may jump while this function is waiting. To compensate for this
// and time out near the correct time, we call do_wait_until() in a loop with a
// short timeout and recheck the time remaining each time through the loop.
typedef typename common_type<Duration, typename Clock::duration>::type common_duration;
while (!pred())
{
if (wait_until(lock, t) == cv_status::timeout)
return pred();
common_duration d(t - Clock::now());
if (d <= common_duration::zero()) break; // timeout occurred
d = (std::min)(d, common_duration(chrono::milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS)));
do_wait_until(lock, detail::internal_platform_clock::now() + detail::platform_duration(d));
}
return true;
return pred();
}
template <class lock_type, class Rep, class Period, class Predicate>

View File

@@ -87,9 +87,9 @@ namespace boost
{
void* const res=
#if defined(_M_ARM64)
__iso_volatile_load64((const volatile __int64*)x);
(void*)__iso_volatile_load64((const volatile __int64*)x);
#else
__iso_volatile_load32((const volatile __int32*)x);
(void*)__iso_volatile_load32((const volatile __int32*)x);
#endif
BOOST_THREAD_DETAIL_COMPILER_BARRIER();
__dmb(0xB); // _ARM_BARRIER_ISH, see armintr.h from MSVC 11 and later

View File

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

View File

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

View File

@@ -2,12 +2,13 @@
#define BOOST_THREAD_WIN32_SHARED_MUTEX_HPP
// (C) Copyright 2006-8 Anthony Williams
// (C) Copyright 2011-2012 Vicente J. Botet Escriba
// (C) Copyright 2011-2012,2017-2018 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <cstring>
#include <boost/assert.hpp>
#include <boost/detail/interlocked.hpp>
#include <boost/thread/win32/thread_primitives.hpp>
@@ -19,6 +20,7 @@
#include <boost/chrono/ceil.hpp>
#endif
#include <boost/thread/detail/delete.hpp>
#include <boost/thread/detail/platform_time.hpp>
#include <boost/config/abi_prefix.hpp>
@@ -29,7 +31,7 @@ namespace boost
private:
struct state_data
{
unsigned shared_count:11,
unsigned long shared_count:11,
shared_waiting:11,
exclusive:1,
upgrade:1,
@@ -38,19 +40,22 @@ namespace boost
friend bool operator==(state_data const& lhs,state_data const& rhs)
{
return *reinterpret_cast<unsigned const*>(&lhs)==*reinterpret_cast<unsigned const*>(&rhs);
return std::memcmp(&lhs, &rhs, sizeof(lhs)) == 0;
}
};
template<typename T>
T interlocked_compare_exchange(T* target,T new_value,T comparand)
static state_data interlocked_compare_exchange(state_data* target, state_data new_value, state_data comparand)
{
BOOST_STATIC_ASSERT(sizeof(T)==sizeof(long));
BOOST_STATIC_ASSERT(sizeof(state_data) == sizeof(long));
long new_val, comp;
std::memcpy(&new_val, &new_value, sizeof(new_value));
std::memcpy(&comp, &comparand, sizeof(comparand));
long const res=BOOST_INTERLOCKED_COMPARE_EXCHANGE(reinterpret_cast<long*>(target),
*reinterpret_cast<long*>(&new_value),
*reinterpret_cast<long*>(&comparand));
return *reinterpret_cast<T const*>(&res);
new_val,
comp);
state_data result;
std::memcpy(&result, &res, sizeof(result));
return result;
}
enum
@@ -67,19 +72,19 @@ namespace boost
{
if(old_state.exclusive_waiting)
{
BOOST_VERIFY(detail::win32::ReleaseSemaphore(semaphores[exclusive_sem],1,0)!=0);
BOOST_VERIFY(winapi::ReleaseSemaphore(semaphores[exclusive_sem],1,0)!=0);
}
if(old_state.shared_waiting || old_state.exclusive_waiting)
{
BOOST_VERIFY(detail::win32::ReleaseSemaphore(semaphores[unlock_sem],old_state.shared_waiting + (old_state.exclusive_waiting?1:0),0)!=0);
BOOST_VERIFY(winapi::ReleaseSemaphore(semaphores[unlock_sem],old_state.shared_waiting + (old_state.exclusive_waiting?1:0),0)!=0);
}
}
void release_shared_waiters(state_data old_state)
{
if(old_state.shared_waiting || old_state.exclusive_waiting)
{
BOOST_VERIFY(detail::win32::ReleaseSemaphore(semaphores[unlock_sem],old_state.shared_waiting + (old_state.exclusive_waiting?1:0),0)!=0);
BOOST_VERIFY(winapi::ReleaseSemaphore(semaphores[unlock_sem],old_state.shared_waiting + (old_state.exclusive_waiting?1:0),0)!=0);
}
}
@@ -107,9 +112,9 @@ namespace boost
~shared_mutex()
{
detail::win32::CloseHandle(upgrade_sem);
detail::win32::CloseHandle(semaphores[unlock_sem]);
detail::win32::CloseHandle(semaphores[exclusive_sem]);
winapi::CloseHandle(upgrade_sem);
winapi::CloseHandle(semaphores[unlock_sem]);
winapi::CloseHandle(semaphores[exclusive_sem]);
}
bool try_lock_shared()
@@ -139,21 +144,60 @@ namespace boost
void lock_shared()
{
for(;;)
{
state_data old_state=state;
for(;;)
{
state_data new_state=old_state;
if(new_state.exclusive || new_state.exclusive_waiting_blocked)
{
++new_state.shared_waiting;
if(!new_state.shared_waiting)
{
boost::throw_exception(boost::lock_error());
}
}
else
{
++new_state.shared_count;
if(!new_state.shared_count)
{
boost::throw_exception(boost::lock_error());
}
}
#if defined BOOST_THREAD_USES_DATETIME
BOOST_VERIFY(timed_lock_shared(::boost::detail::get_system_time_sentinel()));
#else
BOOST_VERIFY(try_lock_shared_until(chrono::steady_clock::now()));
#endif
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
if(current_state==old_state)
{
break;
}
old_state=current_state;
}
if(!(old_state.exclusive| old_state.exclusive_waiting_blocked))
{
return;
}
BOOST_VERIFY(winapi::WaitForSingleObjectEx(semaphores[unlock_sem],::boost::detail::win32::infinite,0)==0);
}
}
#if defined BOOST_THREAD_USES_DATETIME
template<typename TimeDuration>
bool timed_lock_shared(TimeDuration const & relative_time)
private:
unsigned long getMs(detail::platform_duration const& d)
{
return timed_lock_shared(get_system_time()+relative_time);
return static_cast<unsigned long>(d.getMs());
}
bool timed_lock_shared(boost::system_time const& wait_until)
template <typename Duration>
unsigned long getMs(Duration const& d)
{
return static_cast<unsigned long>(chrono::ceil<chrono::milliseconds>(d).count());
}
template <typename Clock, typename Timepoint, typename Duration>
bool do_lock_shared_until(Timepoint const& t, Duration const& max)
{
for(;;)
{
@@ -191,7 +235,30 @@ namespace boost
return true;
}
unsigned long const res=detail::win32::WaitForSingleObjectEx(semaphores[unlock_sem],::boost::detail::get_milliseconds_until(wait_until), 0);
// If the clock is the system clock, it may jump while this function
// is waiting. To compensate for this and time out near the correct
// time, we call WaitForSingleObjectEx() in a loop with a short
// timeout and recheck the time remaining each time through the loop.
unsigned long res=0;
for(;;)
{
Duration d(t - Clock::now());
if(d <= Duration::zero()) // timeout occurred
{
res=detail::win32::timeout;
break;
}
if(max != Duration::zero())
{
d = (std::min)(d, max);
}
res=winapi::WaitForSingleObjectEx(semaphores[unlock_sem],getMs(d),0);
if(res!=detail::win32::timeout) // semaphore released
{
break;
}
}
if(res==detail::win32::timeout)
{
for(;;)
@@ -231,114 +298,45 @@ namespace boost
BOOST_ASSERT(res==0);
}
}
public:
#if defined BOOST_THREAD_USES_DATETIME
template<typename TimeDuration>
bool timed_lock_shared(TimeDuration const & relative_time)
{
const detail::mono_platform_timepoint t(detail::mono_platform_clock::now() + detail::platform_duration(relative_time));
// The reference clock is steady and so no need to poll periodically, thus 0 ms max (i.e. no max)
return do_lock_shared_until<detail::mono_platform_clock>(t, detail::platform_duration::zero());
}
bool timed_lock_shared(boost::system_time const& wait_until)
{
const detail::real_platform_timepoint t(wait_until);
return do_lock_shared_until<detail::real_platform_clock>(t, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
}
#endif
#ifdef BOOST_THREAD_USES_CHRONO
template <class Rep, class Period>
bool try_lock_shared_for(const chrono::duration<Rep, Period>& rel_time)
{
return try_lock_shared_until(chrono::steady_clock::now() + rel_time);
const chrono::steady_clock::time_point t(chrono::steady_clock::now() + rel_time);
typedef typename chrono::duration<Rep, Period> Duration;
typedef typename common_type<Duration, typename chrono::steady_clock::duration>::type common_duration;
// The reference clock is steady and so no need to poll periodically, thus 0 ms max (i.e. no max)
return do_lock_shared_until<chrono::steady_clock>(t, common_duration::zero());
}
template <class Duration>
bool try_lock_shared_until(const chrono::time_point<chrono::steady_clock, Duration>& t)
{
typedef typename common_type<Duration, typename chrono::steady_clock::duration>::type common_duration;
// The reference clock is steady and so no need to poll periodically, thus 0 ms max (i.e. no max)
return do_lock_shared_until<chrono::steady_clock>(t, common_duration::zero());
}
template <class Clock, class Duration>
bool try_lock_shared_until(const chrono::time_point<Clock, Duration>& t)
{
using namespace chrono;
system_clock::time_point s_now = system_clock::now();
typename Clock::time_point c_now = Clock::now();
return try_lock_shared_until(s_now + ceil<system_clock::duration>(t - c_now));
}
template <class Duration>
bool try_lock_shared_until(const chrono::time_point<chrono::system_clock, Duration>& t)
{
using namespace chrono;
typedef time_point<chrono::system_clock, chrono::system_clock::duration> sys_tmpt;
return try_lock_shared_until(sys_tmpt(chrono::ceil<chrono::system_clock::duration>(t.time_since_epoch())));
}
bool try_lock_shared_until(const chrono::time_point<chrono::system_clock, chrono::system_clock::duration>& tp)
{
for(;;)
{
state_data old_state=state;
for(;;)
{
state_data new_state=old_state;
if(new_state.exclusive || new_state.exclusive_waiting_blocked)
{
++new_state.shared_waiting;
if(!new_state.shared_waiting)
{
boost::throw_exception(boost::lock_error());
}
}
else
{
++new_state.shared_count;
if(!new_state.shared_count)
{
boost::throw_exception(boost::lock_error());
}
}
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
if(current_state==old_state)
{
break;
}
old_state=current_state;
}
if(!(old_state.exclusive| old_state.exclusive_waiting_blocked))
{
return true;
}
chrono::system_clock::time_point n = chrono::system_clock::now();
unsigned long res;
if (tp>n) {
chrono::milliseconds rel_time= chrono::ceil<chrono::milliseconds>(tp-n);
res=detail::win32::WaitForSingleObjectEx(semaphores[unlock_sem],
static_cast<unsigned long>(rel_time.count()), 0);
} else {
res=detail::win32::timeout;
}
if(res==detail::win32::timeout)
{
for(;;)
{
state_data new_state=old_state;
if(new_state.exclusive || new_state.exclusive_waiting_blocked)
{
if(new_state.shared_waiting)
{
--new_state.shared_waiting;
}
}
else
{
++new_state.shared_count;
if(!new_state.shared_count)
{
return false;
}
}
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
if(current_state==old_state)
{
break;
}
old_state=current_state;
}
if(!(old_state.exclusive| old_state.exclusive_waiting_blocked))
{
return true;
}
return false;
}
BOOST_ASSERT(res==0);
}
typedef typename common_type<Duration, typename Clock::duration>::type common_duration;
return do_lock_shared_until<Clock>(t, common_duration(chrono::milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS)));
}
#endif
@@ -375,7 +373,7 @@ namespace boost
{
if(old_state.upgrade)
{
BOOST_VERIFY(detail::win32::ReleaseSemaphore(upgrade_sem,1,0)!=0);
BOOST_VERIFY(winapi::ReleaseSemaphore(upgrade_sem,1,0)!=0);
}
else
{
@@ -388,24 +386,6 @@ namespace boost
}
}
void lock()
{
#if defined BOOST_THREAD_USES_DATETIME
BOOST_VERIFY(timed_lock(::boost::detail::get_system_time_sentinel()));
#else
BOOST_VERIFY(try_lock_until(chrono::steady_clock::now()));
#endif
}
#if defined BOOST_THREAD_USES_DATETIME
template<typename TimeDuration>
bool timed_lock(TimeDuration const & relative_time)
{
return timed_lock(get_system_time()+relative_time);
}
#endif
bool try_lock()
{
state_data old_state=state;
@@ -431,14 +411,58 @@ namespace boost
return true;
}
#if defined BOOST_THREAD_USES_DATETIME
bool timed_lock(boost::system_time const& wait_until)
void lock()
{
for(;;)
{
state_data old_state=state;
for(;;)
{
state_data new_state=old_state;
if(new_state.shared_count || new_state.exclusive)
{
++new_state.exclusive_waiting;
if(!new_state.exclusive_waiting)
{
boost::throw_exception(boost::lock_error());
}
new_state.exclusive_waiting_blocked=true;
}
else
{
new_state.exclusive=true;
}
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
if(current_state==old_state)
{
break;
}
old_state=current_state;
}
if(!old_state.shared_count && !old_state.exclusive)
{
return;
}
#ifndef UNDER_CE
const bool wait_all = true;
#else
const bool wait_all = false;
#endif
BOOST_VERIFY(winapi::WaitForMultipleObjectsEx(2,semaphores,wait_all,::boost::detail::win32::infinite,0)<2);
}
}
private:
template <typename Clock, typename Timepoint, typename Duration>
bool do_lock_until(Timepoint const& t, Duration const& max)
{
for(;;)
{
state_data old_state=state;
for(;;)
{
state_data new_state=old_state;
@@ -469,12 +493,37 @@ namespace boost
{
return true;
}
#ifndef UNDER_CE
const bool wait_all = true;
#else
const bool wait_all = false;
#endif
unsigned long const wait_res=detail::win32::WaitForMultipleObjectsEx(2,semaphores,wait_all,::boost::detail::get_milliseconds_until(wait_until), 0);
// If the clock is the system clock, it may jump while this function
// is waiting. To compensate for this and time out near the correct
// time, we call WaitForMultipleObjectsEx() in a loop with a short
// timeout and recheck the time remaining each time through the loop.
unsigned long wait_res=0;
for(;;)
{
Duration d(t - Clock::now());
if(d <= Duration::zero()) // timeout occurred
{
wait_res=detail::win32::timeout;
break;
}
if(max != Duration::zero())
{
d = (std::min)(d, max);
}
#ifndef UNDER_CE
wait_res=winapi::WaitForMultipleObjectsEx(2,semaphores,true,getMs(d),0);
#else
wait_res=winapi::WaitForMultipleObjectsEx(2,semaphores,false,getMs(d),0);
#endif
//wait_res=winapi::WaitForMultipleObjectsEx(2,semaphores,wait_all,getMs(d), 0);
if(wait_res!=detail::win32::timeout) // semaphore released
{
break;
}
}
if(wait_res==detail::win32::timeout)
{
for(;;)
@@ -500,7 +549,7 @@ namespace boost
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
if (must_notify)
{
BOOST_VERIFY(detail::win32::ReleaseSemaphore(semaphores[unlock_sem],1,0)!=0);
BOOST_VERIFY(winapi::ReleaseSemaphore(semaphores[unlock_sem],1,0)!=0);
}
if(current_state==old_state)
@@ -515,123 +564,48 @@ namespace boost
}
return false;
}
BOOST_ASSERT(wait_res<2);
}
}
public:
#if defined BOOST_THREAD_USES_DATETIME
bool timed_lock(boost::system_time const& wait_until)
{
const detail::real_platform_timepoint t(wait_until);
return do_lock_until<detail::real_platform_clock>(t, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
}
template<typename TimeDuration>
bool timed_lock(TimeDuration const & relative_time)
{
const detail::mono_platform_timepoint t(detail::mono_platform_clock::now() + detail::platform_duration(relative_time));
// The reference clock is steady and so no need to poll periodically, thus 0 ms max (i.e. no max)
return do_lock_until<detail::mono_platform_clock>(t, detail::platform_duration::zero());
}
#endif
#ifdef BOOST_THREAD_USES_CHRONO
template <class Rep, class Period>
bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)
{
return try_lock_until(chrono::steady_clock::now() + rel_time);
const chrono::steady_clock::time_point t(chrono::steady_clock::now() + rel_time);
typedef typename chrono::duration<Rep, Period> Duration;
typedef typename common_type<Duration, typename chrono::steady_clock::duration>::type common_duration;
// The reference clock is steady and so no need to poll periodically, thus 0 ms max (i.e. no max)
return do_lock_until<chrono::steady_clock>(t, common_duration::zero());
}
template <class Duration>
bool try_lock_until(const chrono::time_point<chrono::steady_clock, Duration>& t)
{
typedef typename common_type<Duration, typename chrono::steady_clock::duration>::type common_duration;
// The reference clock is steady and so no need to poll periodically, thus 0 ms max (i.e. no max)
return do_lock_until<chrono::steady_clock>(t, common_duration::zero());
}
template <class Clock, class Duration>
bool try_lock_until(const chrono::time_point<Clock, Duration>& t)
{
using namespace chrono;
system_clock::time_point s_now = system_clock::now();
typename Clock::time_point c_now = Clock::now();
return try_lock_until(s_now + ceil<system_clock::duration>(t - c_now));
}
template <class Duration>
bool try_lock_until(const chrono::time_point<chrono::system_clock, Duration>& t)
{
using namespace chrono;
typedef time_point<chrono::system_clock, chrono::system_clock::duration> sys_tmpt;
return try_lock_until(sys_tmpt(chrono::ceil<chrono::system_clock::duration>(t.time_since_epoch())));
}
bool try_lock_until(const chrono::time_point<chrono::system_clock, chrono::system_clock::duration>& tp)
{
for(;;)
{
state_data old_state=state;
for(;;)
{
state_data new_state=old_state;
if(new_state.shared_count || new_state.exclusive)
{
++new_state.exclusive_waiting;
if(!new_state.exclusive_waiting)
{
boost::throw_exception(boost::lock_error());
}
new_state.exclusive_waiting_blocked=true;
}
else
{
new_state.exclusive=true;
}
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
if(current_state==old_state)
{
break;
}
old_state=current_state;
}
if(!old_state.shared_count && !old_state.exclusive)
{
return true;
}
#ifndef UNDER_CE
const bool wait_all = true;
#else
const bool wait_all = false;
#endif
chrono::system_clock::time_point n = chrono::system_clock::now();
unsigned long wait_res;
if (tp>n) {
chrono::milliseconds rel_time= chrono::ceil<chrono::milliseconds>(tp-chrono::system_clock::now());
wait_res=detail::win32::WaitForMultipleObjectsEx(2,semaphores,wait_all,
static_cast<unsigned long>(rel_time.count()), 0);
} else {
wait_res=detail::win32::timeout;
}
if(wait_res==detail::win32::timeout)
{
for(;;)
{
bool must_notify = false;
state_data new_state=old_state;
if(new_state.shared_count || new_state.exclusive)
{
if(new_state.exclusive_waiting)
{
if(!--new_state.exclusive_waiting)
{
new_state.exclusive_waiting_blocked=false;
must_notify = true;
}
}
}
else
{
new_state.exclusive=true;
}
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
if (must_notify)
{
BOOST_VERIFY(detail::win32::ReleaseSemaphore(semaphores[unlock_sem],1,0)!=0);
}
if(current_state==old_state)
{
break;
}
old_state=current_state;
}
if(!old_state.shared_count && !old_state.exclusive)
{
return true;
}
return false;
}
BOOST_ASSERT(wait_res<2);
}
typedef typename common_type<Duration, typename Clock::duration>::type common_duration;
return do_lock_until<Clock>(t, common_duration(chrono::milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS)));
}
#endif
@@ -698,7 +672,7 @@ namespace boost
return;
}
BOOST_VERIFY(!detail::win32::WaitForSingleObjectEx(semaphores[unlock_sem],detail::win32::infinite, 0));
BOOST_VERIFY(winapi::WaitForSingleObjectEx(semaphores[unlock_sem],winapi::infinite,0)==0);
}
}
@@ -790,7 +764,7 @@ namespace boost
{
if(!last_reader)
{
BOOST_VERIFY(!detail::win32::WaitForSingleObjectEx(upgrade_sem,detail::win32::infinite, 0));
BOOST_VERIFY(winapi::WaitForSingleObjectEx(upgrade_sem,detail::win32::infinite,0)==0);
}
break;
}
@@ -823,27 +797,6 @@ namespace boost
}
release_waiters(old_state);
}
// bool try_unlock_upgrade_and_lock()
// {
// return false;
// }
//#ifdef BOOST_THREAD_USES_CHRONO
// template <class Rep, class Period>
// bool
// try_unlock_upgrade_and_lock_for(
// const chrono::duration<Rep, Period>& rel_time)
// {
// return try_unlock_upgrade_and_lock_until(
// chrono::steady_clock::now() + rel_time);
// }
// template <class Clock, class Duration>
// bool
// try_unlock_upgrade_and_lock_until(
// const chrono::time_point<Clock, Duration>& abs_time)
// {
// return false;
// }
//#endif
void unlock_and_lock_shared()
{

View File

@@ -10,6 +10,7 @@
#include <boost/thread/thread_time.hpp>
#include <boost/thread/win32/thread_primitives.hpp>
#include <boost/thread/win32/thread_heap_alloc.hpp>
#include <boost/thread/detail/platform_time.hpp>
#include <boost/predef/platform.h>
@@ -79,12 +80,15 @@ namespace boost
struct thread_exit_callback_node;
struct tss_data_node
{
boost::shared_ptr<boost::detail::tss_cleanup_function> func;
typedef void(*cleanup_func_t)(void*);
typedef void(*cleanup_caller_t)(cleanup_func_t, void*);
cleanup_caller_t caller;
cleanup_func_t func;
void* value;
tss_data_node(boost::shared_ptr<boost::detail::tss_cleanup_function> func_,
void* value_):
func(func_),value(value_)
tss_data_node(cleanup_caller_t caller_,cleanup_func_t func_,void* value_):
caller(caller_),func(func_),value(value_)
{}
};
@@ -112,8 +116,10 @@ namespace boost
> notify_list_t;
notify_list_t notify;
//#ifndef BOOST_NO_EXCEPTIONS
typedef std::vector<shared_ptr<shared_state_base> > async_states_t;
async_states_t async_states_;
//#endif
//#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
// These data must be at the end so that the access to the other fields doesn't change
// when BOOST_THREAD_PROVIDES_INTERRUPTIONS is defined
@@ -128,8 +134,10 @@ namespace boost
thread_exit_callbacks(0),
id(0),
tss_data(),
notify(),
async_states_()
notify()
//#ifndef BOOST_NO_EXCEPTIONS
, async_states_()
//#endif
//#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
, interruption_handle(create_anonymous_event(detail::win32::manual_reset_event,detail::win32::event_initially_reset))
, interruption_enabled(true)
@@ -153,7 +161,7 @@ namespace boost
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
void interrupt()
{
BOOST_VERIFY(detail::win32::SetEvent(interruption_handle)!=0);
BOOST_VERIFY(winapi::SetEvent(interruption_handle)!=0);
}
#endif
typedef detail::win32::handle native_handle_type;
@@ -165,155 +173,121 @@ namespace boost
notify.push_back(std::pair<condition_variable*, mutex*>(cv, m));
}
//#ifndef BOOST_NO_EXCEPTIONS
void make_ready_at_thread_exit(shared_ptr<shared_state_base> as)
{
async_states_.push_back(as);
}
//#endif
};
BOOST_THREAD_DECL thread_data_base* get_current_thread_data();
typedef boost::intrusive_ptr<detail::thread_data_base> thread_data_ptr;
struct BOOST_SYMBOL_VISIBLE timeout
{
win32::ticks_type start;
uintmax_t milliseconds;
bool relative;
boost::system_time abs_time;
static unsigned long const max_non_infinite_wait=0xfffffffe;
timeout(uintmax_t milliseconds_):
start(win32::GetTickCount64_()()),
milliseconds(milliseconds_),
relative(true)
//,
// abs_time(boost::get_system_time())
{}
timeout(boost::system_time const& abs_time_):
start(win32::GetTickCount64_()()),
milliseconds(0),
relative(false),
abs_time(abs_time_)
{}
struct BOOST_SYMBOL_VISIBLE remaining_time
{
bool more;
unsigned long milliseconds;
remaining_time(uintmax_t remaining):
more(remaining>max_non_infinite_wait),
milliseconds(more?max_non_infinite_wait:(unsigned long)remaining)
{}
};
remaining_time remaining_milliseconds() const
{
if(is_sentinel())
{
return remaining_time(win32::infinite);
}
else if(relative)
{
win32::ticks_type const now=win32::GetTickCount64_()();
win32::ticks_type const elapsed=now-start;
return remaining_time((elapsed<milliseconds)?(milliseconds-elapsed):0);
}
else
{
system_time const now=get_system_time();
if(abs_time<=now)
{
return remaining_time(0);
}
return remaining_time((abs_time-now).total_milliseconds()+1);
}
}
bool is_sentinel() const
{
return milliseconds==~uintmax_t(0);
}
static timeout sentinel()
{
return timeout(sentinel_type());
}
private:
struct sentinel_type
{};
explicit timeout(sentinel_type):
start(0),milliseconds(~uintmax_t(0)),relative(true)
{}
};
inline uintmax_t pin_to_zero(intmax_t value)
{
return (value<0)?0u:(uintmax_t)value;
}
}
namespace this_thread
{
void BOOST_THREAD_DECL yield() BOOST_NOEXCEPT;
bool BOOST_THREAD_DECL interruptible_wait(detail::win32::handle handle_to_wait_for,detail::timeout target_time);
inline void interruptible_wait(uintmax_t milliseconds)
{
interruptible_wait(detail::win32::invalid_handle_value,milliseconds);
}
inline BOOST_SYMBOL_VISIBLE void interruptible_wait(system_time const& abs_time)
{
interruptible_wait(detail::win32::invalid_handle_value,abs_time);
}
bool BOOST_THREAD_DECL interruptible_wait(detail::win32::handle handle_to_wait_for, detail::internal_platform_timepoint const &timeout);
#if defined BOOST_THREAD_USES_DATETIME
template<typename TimeDuration>
inline BOOST_SYMBOL_VISIBLE void sleep(TimeDuration const& rel_time)
BOOST_SYMBOL_VISIBLE void sleep(TimeDuration const& rel_time)
{
interruptible_wait(detail::pin_to_zero(rel_time.total_milliseconds()));
interruptible_wait(detail::win32::invalid_handle_value, detail::internal_platform_clock::now() + detail::platform_duration(rel_time));
}
inline BOOST_SYMBOL_VISIBLE void sleep(system_time const& abs_time)
{
interruptible_wait(abs_time);
const detail::real_platform_timepoint ts(abs_time);
detail::platform_duration d(ts - detail::real_platform_clock::now());
while (d > detail::platform_duration::zero())
{
d = (std::min)(d, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
interruptible_wait(detail::win32::invalid_handle_value, detail::internal_platform_clock::now() + d);
d = ts - detail::real_platform_clock::now();
}
}
// #11322 sleep_for() nanoseconds overload will always return too early on windows
//#ifdef BOOST_THREAD_USES_CHRONO
// inline void BOOST_SYMBOL_VISIBLE sleep_for(const chrono::nanoseconds& ns)
// {
// interruptible_wait(chrono::duration_cast<chrono::milliseconds>(ns).count());
// }
//#endif
#endif
#ifdef BOOST_THREAD_USES_CHRONO
template <class Rep, class Period>
void sleep_for(const chrono::duration<Rep, Period>& d)
{
interruptible_wait(detail::win32::invalid_handle_value, detail::internal_platform_clock::now() + detail::platform_duration(d));
}
template <class Duration>
void sleep_until(const chrono::time_point<chrono::steady_clock, Duration>& t)
{
sleep_for(t - chrono::steady_clock::now());
}
template <class Clock, class Duration>
void sleep_until(const chrono::time_point<Clock, Duration>& t)
{
typedef typename common_type<Duration, typename Clock::duration>::type common_duration;
common_duration d(t - Clock::now());
while (d > common_duration::zero())
{
d = (std::min)(d, common_duration(chrono::milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS)));
sleep_for(d);
d = t - Clock::now();
}
}
#endif
namespace no_interruption_point
{
bool BOOST_THREAD_DECL non_interruptible_wait(detail::win32::handle handle_to_wait_for,detail::timeout target_time);
inline void non_interruptible_wait(uintmax_t milliseconds)
{
non_interruptible_wait(detail::win32::invalid_handle_value,milliseconds);
}
inline BOOST_SYMBOL_VISIBLE void non_interruptible_wait(system_time const& abs_time)
{
non_interruptible_wait(detail::win32::invalid_handle_value,abs_time);
}
bool BOOST_THREAD_DECL non_interruptible_wait(detail::win32::handle handle_to_wait_for, detail::internal_platform_timepoint const &timeout);
#if defined BOOST_THREAD_USES_DATETIME
template<typename TimeDuration>
inline BOOST_SYMBOL_VISIBLE void sleep(TimeDuration const& rel_time)
BOOST_SYMBOL_VISIBLE void sleep(TimeDuration const& rel_time)
{
non_interruptible_wait(detail::pin_to_zero(rel_time.total_milliseconds()));
non_interruptible_wait(detail::win32::invalid_handle_value, detail::internal_platform_clock::now() + detail::platform_duration(rel_time));
}
inline BOOST_SYMBOL_VISIBLE void sleep(system_time const& abs_time)
{
non_interruptible_wait(abs_time);
const detail::real_platform_timepoint ts(abs_time);
detail::platform_duration d(ts - detail::real_platform_clock::now());
while (d > detail::platform_duration::zero())
{
d = (std::min)(d, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
non_interruptible_wait(detail::win32::invalid_handle_value, detail::internal_platform_clock::now() + d);
d = ts - detail::real_platform_clock::now();
}
}
// #11322 sleep_for() nanoseconds overload will always return too early on windows
//#ifdef BOOST_THREAD_USES_CHRONO
// inline void BOOST_SYMBOL_VISIBLE sleep_for(const chrono::nanoseconds& ns)
// {
// non_interruptible_wait(chrono::duration_cast<chrono::milliseconds>(ns).count());
// }
//#endif
#endif
#ifdef BOOST_THREAD_USES_CHRONO
template <class Rep, class Period>
void sleep_for(const chrono::duration<Rep, Period>& d)
{
non_interruptible_wait(detail::win32::invalid_handle_value, detail::internal_platform_clock::now() + detail::platform_duration(d));
}
template <class Duration>
void sleep_until(const chrono::time_point<chrono::steady_clock, Duration>& t)
{
sleep_for(t - chrono::steady_clock::now());
}
template <class Clock, class Duration>
void sleep_until(const chrono::time_point<Clock, Duration>& t)
{
typedef typename common_type<Duration, typename Clock::duration>::type common_duration;
common_duration d(t - Clock::now());
while (d > common_duration::zero())
{
d = (std::min)(d, common_duration(chrono::milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS)));
sleep_for(d);
d = t - Clock::now();
}
}
#endif
}
}

View File

@@ -12,45 +12,7 @@
#include <boost/throw_exception.hpp>
#include <boost/core/no_exceptions_support.hpp>
#if defined( BOOST_USE_WINDOWS_H )
# include <windows.h>
namespace boost
{
namespace detail
{
namespace win32
{
using ::GetProcessHeap;
using ::HeapAlloc;
using ::HeapFree;
}
}
}
#else
# ifdef HeapAlloc
# undef HeapAlloc
# endif
namespace boost
{
namespace detail
{
namespace win32
{
extern "C"
{
__declspec(dllimport) handle __stdcall GetProcessHeap();
__declspec(dllimport) void* __stdcall HeapAlloc(handle,unsigned long,ulong_ptr);
__declspec(dllimport) int __stdcall HeapFree(handle,unsigned long,void*);
}
}
}
}
#endif
#include <boost/winapi/heap_memory.hpp>
#include <boost/config/abi_prefix.hpp>
@@ -60,7 +22,7 @@ namespace boost
{
inline void* allocate_raw_heap_memory(unsigned size)
{
void* const heap_memory=detail::win32::HeapAlloc(detail::win32::GetProcessHeap(),0,size);
void* const heap_memory=winapi::HeapAlloc(winapi::GetProcessHeap(),0,size);
if(!heap_memory)
{
boost::throw_exception(std::bad_alloc());
@@ -70,9 +32,26 @@ namespace boost
inline void free_raw_heap_memory(void* heap_memory)
{
BOOST_VERIFY(detail::win32::HeapFree(detail::win32::GetProcessHeap(),0,heap_memory)!=0);
BOOST_VERIFY(winapi::HeapFree(winapi::GetProcessHeap(),0,heap_memory)!=0);
}
#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) && ! defined (BOOST_NO_CXX11_RVALUE_REFERENCES)
template<typename T,typename... Args>
inline T* heap_new(Args&&... args)
{
void* const heap_memory=allocate_raw_heap_memory(sizeof(T));
BOOST_TRY
{
T* const data=new (heap_memory) T(static_cast<Args&&>(args)...);
return data;
}
BOOST_CATCH(...)
{
free_raw_heap_memory(heap_memory);
BOOST_RETHROW
}
BOOST_CATCH_END
}
#else
template<typename T>
inline T* heap_new()
{
@@ -225,6 +204,86 @@ namespace boost
}
BOOST_CATCH_END
}
template<typename T,typename A1,typename A2,typename A3,typename A4,typename A5>
inline T* heap_new_impl(A1 a1,A2 a2,A3 a3,A4 a4,A5 a5)
{
void* const heap_memory=allocate_raw_heap_memory(sizeof(T));
BOOST_TRY
{
T* const data=new (heap_memory) T(a1,a2,a3,a4,a5);
return data;
}
BOOST_CATCH(...)
{
free_raw_heap_memory(heap_memory);
BOOST_RETHROW
}
BOOST_CATCH_END
}
template<typename T,typename A1,typename A2,typename A3,typename A4,typename A5,typename A6>
inline T* heap_new_impl(A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6)
{
void* const heap_memory=allocate_raw_heap_memory(sizeof(T));
BOOST_TRY
{
T* const data=new (heap_memory) T(a1,a2,a3,a4,a5,a6);
return data;
}
BOOST_CATCH(...)
{
free_raw_heap_memory(heap_memory);
BOOST_RETHROW
}
BOOST_CATCH_END
}
template<typename T,typename A1,typename A2,typename A3,typename A4,typename A5,typename A6,typename A7>
inline T* heap_new_impl(A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6,A7 a7)
{
void* const heap_memory=allocate_raw_heap_memory(sizeof(T));
BOOST_TRY
{
T* const data=new (heap_memory) T(a1,a2,a3,a4,a5,a6,a7);
return data;
}
BOOST_CATCH(...)
{
free_raw_heap_memory(heap_memory);
BOOST_RETHROW
}
BOOST_CATCH_END
}
template<typename T,typename A1,typename A2,typename A3,typename A4,typename A5,typename A6,typename A7,typename A8>
inline T* heap_new_impl(A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6,A7 a7,A8 a8)
{
void* const heap_memory=allocate_raw_heap_memory(sizeof(T));
BOOST_TRY
{
T* const data=new (heap_memory) T(a1,a2,a3,a4,a5,a6,a7,a8);
return data;
}
BOOST_CATCH(...)
{
free_raw_heap_memory(heap_memory);
BOOST_RETHROW
}
BOOST_CATCH_END
}
template<typename T,typename A1,typename A2,typename A3,typename A4,typename A5,typename A6,typename A7,typename A8,typename A9>
inline T* heap_new_impl(A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6,A7 a7,A8 a8,A9 a9)
{
void* const heap_memory=allocate_raw_heap_memory(sizeof(T));
BOOST_TRY
{
T* const data=new (heap_memory) T(a1,a2,a3,a4,a5,a6,a7,a8,a9);
return data;
}
BOOST_CATCH(...)
{
free_raw_heap_memory(heap_memory);
BOOST_RETHROW
}
BOOST_CATCH_END
}
template<typename T,typename A1>
@@ -384,6 +443,7 @@ namespace boost
return heap_new_impl<T,A1&,A2&,A3&,A4&>(a1,a2,a3,a4);
}
#endif
#endif
template<typename T>
inline void heap_delete(T* data)

View File

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

View File

@@ -57,17 +57,17 @@ struct xtime
};
inline xtime get_xtime(boost::system_time const& abs_time)
inline ::boost::xtime get_xtime(boost::system_time const& abs_time)
{
xtime res;
::boost::xtime res;
boost::posix_time::time_duration const time_since_epoch=abs_time-boost::posix_time::from_time_t(0);
res.sec=static_cast<xtime::xtime_sec_t>(time_since_epoch.total_seconds());
res.nsec=static_cast<xtime::xtime_nsec_t>(time_since_epoch.fractional_seconds()*(1000000000/time_since_epoch.ticks_per_second()));
res.sec=static_cast< ::boost::xtime::xtime_sec_t>(time_since_epoch.total_seconds());
res.nsec=static_cast< ::boost::xtime::xtime_nsec_t>(time_since_epoch.fractional_seconds()*(1000000000/time_since_epoch.ticks_per_second()));
return res;
}
inline int xtime_get(struct xtime* xtp, int clock_type)
inline int xtime_get(struct ::boost::xtime* xtp, int clock_type)
{
if (clock_type == TIME_UTC_)
{
@@ -78,7 +78,7 @@ inline int xtime_get(struct xtime* xtp, int clock_type)
}
inline int xtime_cmp(const xtime& xt1, const xtime& xt2)
inline int xtime_cmp(const ::boost::xtime& xt1, const ::boost::xtime& xt2)
{
if (xt1.sec == xt2.sec)
return (int)(xt1.nsec - xt2.nsec);