2
0
mirror of https://github.com/boostorg/thread.git synced 2026-02-03 09:42:16 +00:00

Compare commits

...

36 Commits

Author SHA1 Message Date
Vicente J. Botet Escriba
748fdee203 #130 - Bug in boost::condition_variable on Windows. 2017-08-28 22:07:02 +02:00
Vicente J. Botet Escriba
db6de8fd42 #130 - Bug in boost::condition_variable on Windows. 2017-08-28 22:06:53 +02:00
Vicente J. Botet Escriba
32229388f5 make use of timespec_now_realtime to fix issues with timespec_now. 2017-08-16 23:14:06 +02:00
Vicente J. Botet Escriba
333365aefe Merge branch 'develop' 2017-06-11 11:33:12 +02:00
Vicente J. Botet Escriba
d4cff01c72 #12519. 2017-06-11 11:30:59 +02:00
Vicente J. Botet Escriba
5f7dc381c7 Merge pull request #125 from vslavik/fix-comparison
Don't compare shared_ptr<> to 0
2017-06-07 17:57:21 +02:00
Václav Slavík
ea0bc01400 Don't compare shared_ptr<> to 0
Update the code to consistently use a check for .get() == 0, as was
already done in most, but not all, places, to avoid issues with
ambiguous overloaded operator== and operator!=.
2017-06-07 17:24:40 +02:00
Vicente J. Botet Escriba
3bc883d114 Merge pull request #124 from florianbehrens/patch-1
Fixed future::then template argument in documentation.
2017-05-24 12:18:21 +02:00
Florian Behrens
2e2850ff94 Fixed future::then template argument in documentation. 2017-05-24 12:03:38 +02:00
Vicente J. Botet Escriba
1a8019f499 Merge pull request #123 from Lastique/fix_entry_manager
Fix entry_manager constructor not accepting entry_ptr rvalue
2017-05-23 21:54:30 +02:00
Andrey Semashev
bf4b38b0af Fixed entry_manager constructor not accepting entry_ptr rvalue. This resolves compilation failures with MinGW. 2017-05-22 13:11:11 +03:00
Vicente J. Botet Escriba
f78b10a450 Merge pull request #122 from vincenthsu/develop
Fix sync_bounded_queue<>::size()
2017-05-11 01:33:43 +02:00
Vincent Hsu
603689372c Fix sync_bounded_queue<>::size() 2017-05-10 13:12:01 +08:00
Vicente J. Botet Escriba
5b05d6a8c8 fix compile error. 2017-05-07 16:01:10 +02:00
Vicente J. Botet Escriba
12c0fe14cd fix compile error. 2017-05-07 09:05:12 +02:00
Vicente J. Botet Escriba
ace2b8f89e rollback and use RAII. 2017-05-06 23:04:52 +02:00
Vicente J. Botet Escriba
24188f295c fix missing remove aiter while return. 2017-05-06 22:53:41 +02:00
Vicente J. Botet Escriba
653671bc0e fix compilation error. 2017-05-06 14:43:49 +02:00
Vicente J. Botet Escriba
c251497758 Avoid throwing on destructor: condition_variable. 2017-05-06 12:09:23 +02:00
Vicente J. Botet Escriba
69435fa44e try to fix lock on destructor issues. 2017-05-06 03:58:13 +02:00
Vicente J. Botet Escriba
6bc6fcab9a fix compilation error :( 2017-05-04 19:16:04 +02:00
Vicente J. Botet Escriba
50bac8c0eb fix compilation error :( 2017-05-04 07:58:58 +02:00
Vicente J. Botet Escriba
d709d4707c comment failing test. It is surely a bad test. 2017-05-01 03:39:53 +02:00
Vicente J. Botet Escriba
879db6841d try to fix compilation error on windows condition_variable.hpp. 2017-05-01 02:58:45 +02:00
Vicente J. Botet Escriba
2ce385b949 Add missing iostream. 2017-04-29 18:19:02 +02:00
Vicente J. Botet Escriba
21458fcc67 Add missing iostream. 2017-04-29 17:56:32 +02:00
Vicente J. Botet Escriba
d83b7ddc0f Merge branch 'develop' of github.com:boostorg/thread into develop 2017-04-29 17:35:01 +02:00
Vicente J. Botet Escriba
5ee3e8d04b manage with #12888. 2017-04-29 16:17:07 +02:00
Vicente J. Botet Escriba
dcafe1e17d Add noexcept(false) in destructor that could throw in C++11. 2017-04-29 16:15:57 +02:00
Vicente J. Botet Escriba
8dfa7c2e42 fix issue throw() noexcept issue. 2017-04-29 16:14:41 +02:00
Vicente J. Botet Escriba
c83d30f526 manage with #12874. 2017-04-29 16:13:52 +02:00
Vicente J. Botet Escriba
51b367df53 manage with 12958. 2017-04-29 16:12:35 +02:00
Vicente J. Botet Escriba
da83662e1a added test for 12949. 2017-04-29 16:11:31 +02:00
Vicente J. Botet Escriba
36861e5b67 Comment error. Need to be fixed. 2017-04-29 16:10:43 +02:00
Vicente J. Botet Escriba
67df4dd84e Merge pull request #120 from MarcelRaad/patch-2
Remove wrong MSVC version check
2017-04-21 02:10:19 +02:00
Marcel Raad
676521808d Remove wrong MSVC version check
There is no compiler with (_MSC_VER > 2000) and taking the legacy codepath would probably break compilation again when there is. As (_MSC_VER < 1300) (that would be MSVC up to 6.0 from 1998) is not supported by Boost anymore anyway and cannot compile Boost.Thread, this codepath can just be removed completely.
2017-03-24 22:28:41 +01:00
27 changed files with 380 additions and 217 deletions

View File

@@ -358,7 +358,7 @@ The object's `name` virtual function returns a pointer to the string "future".]]
template<typename F>
__unique_future__<typename boost::result_of<F(__unique_future__)>::type>
then(F&& func); // EXTENSION
template<typename S, typename F>
template<typename Ex, typename F>
__unique_future__<typename boost::result_of<F(__unique_future__)>::type>
then(Ex& executor, F&& func); // EXTENSION
template<typename F>
@@ -898,7 +898,7 @@ associated with `*this` is ready for retrieval, __waiting__ otherwise.]]
template<typename F>
__unique_future__<typename boost::result_of<F(__unique_future__)>::type>
then(F&& func); // EXTENSION
template<typename S, typename F>
template<typename Ex, typename F>
__unique_future__<typename boost::result_of<F(__unique_future__)>::type>
then(Ex& executor, F&& func); // EXTENSION
template<typename F>
@@ -1387,7 +1387,7 @@ associated with `*this` is ready for retrieval, __waiting__ otherwise.]]
template<typename F>
__unique_future__<typename boost::result_of<F(shared_future)>::type>
then(F&& func) const; // EXTENSION
template<typename S, typename F>
template<typename Ex, typename F>
__unique_future__<typename boost::result_of<F(shared_future)>::type>
then(Ex& executor, F&& func) const; // EXTENSION
template<typename F>

View File

@@ -17,6 +17,7 @@
#include <boost/thread/future.hpp>
#include <boost/assert.hpp>
#include <string>
#include <iostream>
#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
int p1()

View File

@@ -63,6 +63,7 @@ int main()
else
do_something_in_current_thread();
}
#if 0
{
int some_local_state=0;
boost::thread t(( func(some_local_state) ));
@@ -72,6 +73,7 @@ int main()
do_something_in_current_thread();
}
#endif
{
boost::scoped_thread<> g( &f, 1, 2 );
do_something_in_current_thread();

View File

@@ -84,7 +84,7 @@ int main()
else
do_something_in_current_thread();
}
#if ! defined __clang__
#if 0
try
{
int some_local_state=1;

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

@@ -12,7 +12,7 @@
#include <boost/detail/workaround.hpp>
#include <boost/thread/detail/platform.hpp>
//#define BOOST_THREAD_USEFIXES_TIMESPEC
#define BOOST_THREAD_USEFIXES_TIMESPEC
//#define BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
//#define BOOST_THREAD_DONT_PROVIDE_INTERRUPTIONS
// ATTRIBUTE_MAY_ALIAS

View File

@@ -155,7 +155,15 @@ namespace boost
};
#endif
}
namespace thread_detail {
#ifdef BOOST_THREAD_USES_CHRONO
#if defined(BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC) && defined(BOOST_THREAD_USEFIXES_TIMESPEC)
typedef chrono::steady_clock internal_clock_t;
#else
typedef chrono::system_clock internal_clock_t;
#endif
#endif
}
class BOOST_THREAD_DECL thread
{
public:
@@ -483,19 +491,13 @@ namespace boost
}
#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();
thread_detail::internal_clock_t::time_point s_now = thread_detail::internal_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);
@@ -503,10 +505,10 @@ namespace boost
return true;
}
template <class Duration>
bool try_join_until(const chrono::time_point<my_clock_t, Duration>& t)
bool try_join_until(const chrono::time_point<thread_detail::internal_clock_t, Duration>& t)
{
using namespace chrono;
typedef time_point<my_clock_t, nanoseconds> nano_sys_tmpt;
typedef time_point<thread_detail::internal_clock_t, nanoseconds> nano_sys_tmpt;
return try_join_until(nano_sys_tmpt(ceil<nanoseconds>(t.time_since_epoch())));
}
#endif
@@ -521,7 +523,7 @@ namespace boost
//}
#ifdef BOOST_THREAD_USES_CHRONO
bool try_join_until(const chrono::time_point<my_clock_t, chrono::nanoseconds>& tp)
bool try_join_until(const chrono::time_point<thread_detail::internal_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());
@@ -542,7 +544,7 @@ namespace boost
}
#endif
#ifdef BOOST_THREAD_USES_CHRONO
bool try_join_until(const chrono::time_point<chrono::system_clock, chrono::nanoseconds>& tp)
bool try_join_until(const chrono::time_point<thread_detail::internal_clock_t, chrono::nanoseconds>& tp)
{
using namespace chrono;
nanoseconds d = tp.time_since_epoch();

View File

@@ -1335,7 +1335,7 @@ namespace boost
bool valid() const BOOST_NOEXCEPT
{
return future_ != 0 && future_->valid();
return future_.get() != 0 && future_->valid();
}
void wait() const
@@ -1639,7 +1639,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 +1682,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 +1702,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 +1728,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 +1943,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 +1959,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 +1978,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());
}
@@ -4747,7 +4749,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_);
@@ -4811,7 +4813,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 +4837,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 +4867,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 +4941,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 +4967,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 +4997,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 +5066,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 +5087,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 +5259,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

@@ -45,9 +45,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 +78,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.check();
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();
@@ -101,10 +112,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);
check_for_interruption.check();
guard.deactivate();
#else
pthread_mutex_t* the_mutex = m.mutex()->native_handle();
#endif
cond_res=pthread_cond_timedwait(&cond,the_mutex,&timeout);
#endif
}
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
this_thread::interruption_point();
@@ -176,6 +190,8 @@ namespace boost
#endif
guard.activate(m);
res=pthread_cond_wait(&cond,&internal_mutex);
check_for_interruption.check();
guard.deactivate();
}
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
this_thread::interruption_point();
@@ -404,6 +420,8 @@ namespace boost
#endif
guard.activate(m);
res=pthread_cond_timedwait(&cond,&internal_mutex,&timeout);
check_for_interruption.check();
guard.deactivate();
}
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
this_thread::interruption_point();

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
@@ -20,41 +20,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));
}
void unlock()
void unlock() BOOST_NOEXCEPT
{
BOOST_VERIFY(!pthread_mutex_unlock(m));
locked=false;
}
~pthread_mutex_scoped_lock()
void check() 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));
}
~pthread_mutex_scoped_unlock()
~pthread_mutex_scoped_unlock() BOOST_NOEXCEPT
{
BOOST_VERIFY(!pthread_mutex_lock(m));
}
};
}
}

View File

@@ -177,6 +177,7 @@ namespace boost
thread_data_base* const thread_info;
pthread_mutex_t* m;
bool set;
bool done;
void check_for_interruption()
{
@@ -193,7 +194,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)
{
@@ -208,9 +209,10 @@ namespace boost
BOOST_VERIFY(!pthread_mutex_lock(m));
}
}
~interruption_checker()
void check()
{
if(set)
if ( ! done) {
if (set)
{
BOOST_VERIFY(!pthread_mutex_unlock(m));
lock_guard<mutex> guard(thread_info->data_mutex);
@@ -221,6 +223,13 @@ namespace boost
{
BOOST_VERIFY(!pthread_mutex_unlock(m));
}
done = true;
}
}
~interruption_checker() BOOST_NOEXCEPT_IF(false)
{
check();
}
};
#endif

View File

@@ -142,32 +142,38 @@ namespace boost
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 +196,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->()
@@ -215,23 +235,24 @@ namespace boost
template<typename lock_type>
bool do_wait(lock_type& lock,timeout abs_time)
{
relocker<lock_type> locker(lock);
relocker<lock_type> locker(lock);
entry_manager entry(get_wait_entry(), internal_mutex);
locker.unlock();
entry_manager entry(get_wait_entry(), internal_mutex);
bool woken=false;
while(!woken)
{
if(!entry->wait(abs_time))
{
return false;
}
locker.unlock();
bool woken=false;
while(!woken)
{
if(!entry->wait(abs_time))
{
return false;
}
woken=entry->woken();
}
return woken;
woken=entry->woken();
}
// do it here to avoid throwing on the destructor
entry.remove_waiter_and_reset();
locker.lock();
return woken;
}
template<typename lock_type,typename predicate_type>

View File

@@ -459,7 +459,7 @@ namespace boost
void BOOST_THREAD_DECL sleep_until(const timespec& ts)
{
timespec now = boost::detail::timespec_now();
timespec now = boost::detail::timespec_now_realtime();
if (boost::detail::timespec_gt(ts, now))
{
for (int foo=0; foo < 5; ++foo)
@@ -479,7 +479,7 @@ namespace boost
condition_variable cond;
cond.do_wait_until(lock, ts);
# endif
timespec now2 = boost::detail::timespec_now();
timespec now2 = boost::detail::timespec_now_realtime();
if (boost::detail::timespec_ge(now2, ts))
{
return;

View File

@@ -10,7 +10,7 @@
#include <boost/detail/winapi/config.hpp>
#include <boost/thread/detail/config.hpp>
#if defined(BOOST_HAS_WINTHREADS) && defined(BOOST_THREAD_BUILD_LIB)
#if defined(BOOST_HAS_WINTHREADS) && defined(BOOST_THREAD_BUILD_LIB)
#if (defined(__MINGW32__) && !defined(_WIN64)) || defined(__MINGW64__) || (__MINGW64_VERSION_MAJOR)
@@ -39,7 +39,7 @@ namespace {
}
}
#if defined(__MINGW64__) || (__MINGW64_VERSION_MAJOR) || (__MINGW32_MAJOR_VERSION >3) || \
#if defined(__MINGW64__) || (__MINGW64_VERSION_MAJOR) || (__MINGW32__) || (__MINGW32_MAJOR_VERSION >3) || \
((__MINGW32_MAJOR_VERSION==3) && (__MINGW32_MINOR_VERSION>=18))
extern "C"
{
@@ -112,15 +112,9 @@ extern BOOL (WINAPI * const _pDefaultRawDllMainOrig)(HANDLE, DWORD, LPVOID) = NU
//Definitions required by implementation
#if (_MSC_VER < 1300) || (_MSC_VER > 2000) // 1300 == VC++ 7.0, 1900 == VC++ 14.0
typedef void (__cdecl *_PVFV)();
#define INIRETSUCCESS
#define PVAPI void __cdecl
#else
typedef int (__cdecl *_PVFV)();
#define INIRETSUCCESS 0
#define PVAPI int __cdecl
#endif
typedef int (__cdecl *_PVFV)();
#define INIRETSUCCESS 0
#define PVAPI int __cdecl
typedef void (NTAPI* _TLSCB)(HINSTANCE, DWORD, PVOID);

View File

@@ -964,10 +964,11 @@ rule thread-compile ( sources : reqs * : name )
#[ thread-run test_11256.cpp ]
#[ thread-run test_11256.cpp ]
#[ thread-run test_11499.cpp ]
[ thread-run test_11611.cpp ]
#[ thread-run test_11611.cpp ]
#[ thread-run test_11818.cpp ]
#[ thread-run test_11796.cpp ]
[ thread-run test_12293.cpp ]
#[ thread-run test_12293.cpp ]
[ thread-run test_12949.cpp ]
;

View File

@@ -22,6 +22,7 @@
#include <boost/thread/mutex.hpp>
#include <boost/thread/thread.hpp>
#include <boost/detail/lightweight_test.hpp>
#include <cassert>
#if defined BOOST_THREAD_USES_CHRONO
@@ -35,33 +36,39 @@ int runs = 0;
void f()
{
typedef boost::chrono::steady_clock Clock;
typedef boost::chrono::milliseconds milliseconds;
boost::unique_lock<boost::mutex> lk(mut);
BOOST_TEST(test2 == 0);
test1 = 1;
cv.notify_one();
Clock::time_point t0 = Clock::now();
int count=0;
while (test2 == 0 && cv.wait_for(lk, milliseconds(250)) == boost::cv_status::no_timeout)
count++;
Clock::time_point t1 = Clock::now();
if (runs == 0)
{
BOOST_TEST(t1 - t0 < milliseconds(250));
BOOST_TEST(test2 != 0);
try {
typedef boost::chrono::steady_clock Clock;
typedef boost::chrono::milliseconds milliseconds;
boost::unique_lock<boost::mutex> lk(mut);
assert(test2 == 0);
test1 = 1;
cv.notify_one();
Clock::time_point t0 = Clock::now();
int count=0;
while (test2 == 0 && cv.wait_for(lk, milliseconds(250)) == boost::cv_status::no_timeout)
count++;
Clock::time_point t1 = Clock::now();
if (runs == 0)
{
assert(t1 - t0 < milliseconds(250));
assert(test2 != 0);
}
else
{
// This test is spurious as it depends on the time the thread system switches the threads
assert(t1 - t0 - milliseconds(250) < milliseconds(count*250+5+1000));
assert(test2 == 0);
}
++runs;
} catch(...) {
std::cout << "ERROR exception" << __LINE__ << std::endl;
assert(false);
}
else
{
// This test is spurious as it depends on the time the thread system switches the threads
BOOST_TEST(t1 - t0 - milliseconds(250) < milliseconds(count*250+5+1000));
BOOST_TEST(test2 == 0);
}
++runs;
}
int main()
{
try
{
boost::unique_lock<boost::mutex> lk(mut);
boost::thread t(f);
@@ -73,9 +80,13 @@ int main()
lk.unlock();
cv.notify_one();
t.join();
} catch(...) {
std::cout << "ERROR exception" << __LINE__ << std::endl;
BOOST_TEST(false);
}
test1 = 0;
test2 = 0;
try
{
boost::unique_lock<boost::mutex> lk(mut);
boost::thread t(f);
@@ -85,8 +96,10 @@ int main()
BOOST_TEST(test1 != 0);
lk.unlock();
t.join();
} catch(...) {
BOOST_TEST(false);
std::cout << "ERROR exception" << __LINE__ << std::endl;
}
return boost::report_errors();
}
#else

View File

@@ -21,6 +21,8 @@
#include <boost/thread/mutex.hpp>
#include <boost/thread/thread.hpp>
#include <boost/detail/lightweight_test.hpp>
#include <cassert>
#include <iostream>
#if defined BOOST_THREAD_USES_CHRONO
@@ -49,34 +51,40 @@ int runs = 0;
void f()
{
typedef boost::chrono::system_clock Clock;
typedef boost::chrono::milliseconds milliseconds;
boost::unique_lock < boost::mutex > lk(mut);
BOOST_TEST(test2 == 0);
test1 = 1;
cv.notify_one();
Clock::time_point t0 = Clock::now();
int count=0;
//bool r =
(void)cv.wait_for(lk, milliseconds(250), Pred(test2));
count++;
Clock::time_point t1 = Clock::now();
if (runs == 0)
{
// This test is spurious as it depends on the time the thread system switches the threads
BOOST_TEST(t1 - t0 < milliseconds(250+1000));
BOOST_TEST(test2 != 0);
try {
typedef boost::chrono::system_clock Clock;
typedef boost::chrono::milliseconds milliseconds;
boost::unique_lock < boost::mutex > lk(mut);
assert(test2 == 0);
test1 = 1;
cv.notify_one();
Clock::time_point t0 = Clock::now();
int count=0;
//bool r =
(void)cv.wait_for(lk, milliseconds(250), Pred(test2));
count++;
Clock::time_point t1 = Clock::now();
if (runs == 0)
{
// This test is spurious as it depends on the time the thread system switches the threads
assert(t1 - t0 < milliseconds(250+1000));
assert(test2 != 0);
}
else
{
assert(t1 - t0 - milliseconds(250) < milliseconds(count*250+2));
assert(test2 == 0);
}
++runs;
} catch(...) {
std::cout << "ERROR exception" << __LINE__ << std::endl;
assert(false);
}
else
{
BOOST_TEST(t1 - t0 - milliseconds(250) < milliseconds(count*250+2));
BOOST_TEST(test2 == 0);
}
++runs;
}
int main()
{
try
{
boost::unique_lock < boost::mutex > lk(mut);
boost::thread t(f);
@@ -88,9 +96,13 @@ int main()
lk.unlock();
cv.notify_one();
t.join();
} catch(...) {
BOOST_TEST(false);
std::cout << "ERROR exception" << __LINE__ << std::endl;
}
test1 = 0;
test2 = 0;
try
{
boost::unique_lock < boost::mutex > lk(mut);
boost::thread t(f);
@@ -100,6 +112,9 @@ int main()
BOOST_TEST(test1 != 0);
lk.unlock();
t.join();
} catch(...) {
BOOST_TEST(false);
std::cout << "ERROR exception" << __LINE__ << std::endl;
}
return boost::report_errors();

View File

@@ -17,11 +17,13 @@
// void wait(unique_lock<mutex>& lock);
#include <iostream>
#include <boost/thread/condition_variable.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/thread.hpp>
#include <boost/detail/lightweight_test.hpp>
#include <cassert>
#include <iostream>
#if defined BOOST_THREAD_USES_CHRONO
@@ -35,31 +37,40 @@ int runs = 0;
void f()
{
boost::unique_lock<boost::mutex> lk(mut);
BOOST_TEST(test2 == 0);
test1 = 1;
cv.notify_one();
while (test2 == 0) {
cv.wait(lk);
try {
boost::unique_lock<boost::mutex> lk(mut);
assert(test2 == 0);
test1 = 1;
cv.notify_one();
while (test2 == 0) {
cv.wait(lk);
}
assert(test2 != 0);
} catch(...) {
std::cout << "ERROR exception" << __LINE__ << std::endl;
assert(false);
}
BOOST_TEST(test2 != 0);
}
int main()
{
boost::unique_lock<boost::mutex>lk(mut);
boost::thread t(f);
BOOST_TEST(test1 == 0);
while (test1 == 0)
{
cv.wait(lk);
try {
boost::unique_lock<boost::mutex>lk(mut);
boost::thread t(f);
BOOST_TEST(test1 == 0);
while (test1 == 0)
{
cv.wait(lk);
}
BOOST_TEST(test1 != 0);
test2 = 1;
lk.unlock();
cv.notify_one();
t.join();
} catch(...) {
BOOST_TEST(false);
std::cout << "ERROR exception" << __LINE__ << std::endl;
}
BOOST_TEST(test1 != 0);
test2 = 1;
lk.unlock();
cv.notify_one();
t.join();
return boost::report_errors();
}
#else

View File

@@ -21,6 +21,8 @@
#include <boost/thread/mutex.hpp>
#include <boost/thread/thread.hpp>
#include <boost/detail/lightweight_test.hpp>
#include <iostream>
#include <cassert>
#if defined BOOST_THREAD_USES_CHRONO
@@ -49,32 +51,38 @@ int runs = 0;
void f()
{
boost::unique_lock < boost::mutex > lk(mut);
BOOST_TEST(test2 == 0);
test1 = 1;
cv.notify_one();
Clock::time_point t0 = Clock::now();
Clock::time_point t = t0 + Clock::duration(250);
int count=0;
while (test2 == 0 && cv.wait_until(lk, t) == boost::cv_status::no_timeout)
count++;
Clock::time_point t1 = Clock::now();
if (runs == 0)
{
BOOST_TEST(t1 - t0 < Clock::duration(250));
BOOST_TEST(test2 != 0);
try {
boost::unique_lock < boost::mutex > lk(mut);
assert(test2 == 0);
test1 = 1;
cv.notify_one();
Clock::time_point t0 = Clock::now();
Clock::time_point t = t0 + Clock::duration(250);
int count=0;
while (test2 == 0 && cv.wait_until(lk, t) == boost::cv_status::no_timeout)
count++;
Clock::time_point t1 = Clock::now();
if (runs == 0)
{
assert(t1 - t0 < Clock::duration(250));
assert(test2 != 0);
}
else
{
// This test is spurious as it depends on the time the thread system switches the threads
assert(t1 - t0 - Clock::duration(250) < Clock::duration(count*250+5+1000));
assert(test2 == 0);
}
++runs;
} catch(...) {
assert(false);
std::cout << "ERROR exception" << __LINE__ << std::endl;
}
else
{
// This test is spurious as it depends on the time the thread system switches the threads
BOOST_TEST(t1 - t0 - Clock::duration(250) < Clock::duration(count*250+5+1000));
BOOST_TEST(test2 == 0);
}
++runs;
}
int main()
{
try
{
boost::unique_lock < boost::mutex > lk(mut);
boost::thread t(f);
@@ -86,9 +94,14 @@ int main()
lk.unlock();
cv.notify_one();
t.join();
} catch(...) {
BOOST_TEST(false);
std::cout << "ERROR exception" << __LINE__ << std::endl;
}
test1 = 0;
test2 = 0;
try
{
boost::unique_lock < boost::mutex > lk(mut);
boost::thread t(f);
@@ -98,6 +111,9 @@ int main()
BOOST_TEST(test1 != 0);
lk.unlock();
t.join();
} catch(...) {
BOOST_TEST(false);
std::cout << "ERROR exception" << __LINE__ << std::endl;
}
return boost::report_errors();

View File

@@ -21,6 +21,8 @@
#include <boost/thread/mutex.hpp>
#include <boost/thread/thread.hpp>
#include <boost/detail/lightweight_test.hpp>
#include <cassert>
#include <iostream>
#if defined BOOST_THREAD_USES_CHRONO
@@ -64,31 +66,37 @@ int runs = 0;
void f()
{
boost::unique_lock<boost::mutex> lk(mut);
BOOST_TEST(test2 == 0);
test1 = 1;
cv.notify_one();
Clock::time_point t0 = Clock::now();
Clock::time_point t = t0 + Clock::duration(250);
bool r = cv.wait_until(lk, t, Pred(test2));
Clock::time_point t1 = Clock::now();
if (runs == 0)
{
BOOST_TEST(t1 - t0 < Clock::duration(250));
BOOST_TEST(test2 != 0);
BOOST_TEST(r);
try {
boost::unique_lock<boost::mutex> lk(mut);
assert(test2 == 0);
test1 = 1;
cv.notify_one();
Clock::time_point t0 = Clock::now();
Clock::time_point t = t0 + Clock::duration(250);
bool r = cv.wait_until(lk, t, Pred(test2));
Clock::time_point t1 = Clock::now();
if (runs == 0)
{
assert(t1 - t0 < Clock::duration(250));
assert(test2 != 0);
assert(r);
}
else
{
assert(t1 - t0 - Clock::duration(250) < Clock::duration(250+2));
assert(test2 == 0);
assert(!r);
}
++runs;
} catch(...) {
std::cout << "ERROR exception" << __LINE__ << std::endl;
assert(false);
}
else
{
BOOST_TEST(t1 - t0 - Clock::duration(250) < Clock::duration(250+2));
BOOST_TEST(test2 == 0);
BOOST_TEST(!r);
}
++runs;
}
int main()
{
try
{
boost::unique_lock<boost::mutex> lk(mut);
boost::thread t(f);
@@ -100,9 +108,13 @@ int main()
lk.unlock();
cv.notify_one();
t.join();
} catch(...) {
BOOST_TEST(false);
std::cout << "ERROR exception" << __LINE__ << std::endl;
}
test1 = 0;
test2 = 0;
try
{
boost::unique_lock<boost::mutex> lk(mut);
boost::thread t(f);
@@ -112,6 +124,9 @@ int main()
BOOST_TEST(test1 != 0);
lk.unlock();
t.join();
} catch(...) {
BOOST_TEST(false);
std::cout << "ERROR exception" << __LINE__ << std::endl;
}
return boost::report_errors();

View File

@@ -89,12 +89,15 @@ int main()
}
{
// empty queue push rvalue succeeds
boost::sync_bounded_queue<int> q(2);
boost::sync_bounded_queue<int> q(3);
q.push(1);
BOOST_TEST_EQ(q.size(), 1u);
q.push(2);
BOOST_TEST_EQ(q.size(), 2u);
q.push(2);
BOOST_TEST_EQ(q.size(), 3u);
BOOST_TEST(! q.empty());
BOOST_TEST( q.full());
BOOST_TEST_EQ(q.size(), 2u);
BOOST_TEST(! q.closed());
}
{
@@ -317,12 +320,15 @@ int main()
}
{
// empty queue push rvalue succeeds
boost::sync_bounded_queue<int> q(2);
boost::sync_bounded_queue<int> q(3);
q.push_back(1);
BOOST_TEST_EQ(q.size(), 1u);
q.push_back(2);
BOOST_TEST_EQ(q.size(), 2u);
q.push_back(3);
BOOST_TEST_EQ(q.size(), 3u);
BOOST_TEST(! q.empty());
BOOST_TEST( q.full());
BOOST_TEST_EQ(q.size(), 2u);
BOOST_TEST(! q.closed());
}
{

21
test/test_12949.cpp Normal file
View File

@@ -0,0 +1,21 @@
// Copyright (C) 2017 Vicente Botet
//
// 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)
#define BOOST_THREAD_VERSION 4
//#define BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
//#include <boost/thread/thread.hpp>
#include <boost/thread/condition_variable.hpp>
void f()
{
boost::this_thread::sleep_for(boost::chrono::milliseconds(10)); // **
}
int main()
{
return 0;
}

View File

@@ -11,6 +11,7 @@
#include <boost/thread/thread.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/once.hpp>
#include <iostream>
#define LOG \
if (false) {} else std::cout << std::endl << __FILE__ << "[" << __LINE__ << "]"

View File

@@ -12,6 +12,7 @@
#include <boost/thread/xtime.hpp>
#include "./util.inl"
#include "./shared_mutex_locking_thread.hpp"
#include <iostream>
#define CHECK_LOCKED_VALUE_EQUAL(mutex_name,value,expected_value) \
{ \

View File

@@ -26,9 +26,11 @@
unsigned throw_one = 0xFFFF;
#if defined _GLIBCXX_THROW
inline void* operator new(std::size_t s) _GLIBCXX_THROW (std::bad_alloc)
void* operator new(std::size_t s) _GLIBCXX_THROW (std::bad_alloc)
#elif defined BOOST_MSVC
inline void* operator new(std::size_t s)
void* operator new(std::size_t s)
#elif __cplusplus > 201402L
void* operator new(std::size_t s)
#else
void* operator new(std::size_t s) throw (std::bad_alloc)
#endif
@@ -40,9 +42,9 @@ void* operator new(std::size_t s) throw (std::bad_alloc)
}
#if defined BOOST_MSVC
inline void operator delete(void* p)
void operator delete(void* p)
#else
inline void operator delete(void* p) throw ()
void operator delete(void* p) BOOST_NOEXCEPT_OR_NOTHROW
#endif
{
//std::cout << __FILE__ << ":" << __LINE__ << std::endl;

View File

@@ -29,6 +29,8 @@ unsigned throw_one = 0xFFFF;
void* operator new(std::size_t s) _GLIBCXX_THROW (std::bad_alloc)
#elif defined BOOST_MSVC
void* operator new(std::size_t s)
#elif __cplusplus > 201402L
void* operator new(std::size_t s)
#else
void* operator new(std::size_t s) throw (std::bad_alloc)
#endif
@@ -42,7 +44,7 @@ void* operator new(std::size_t s) throw (std::bad_alloc)
#if defined BOOST_MSVC
void operator delete(void* p)
#else
void operator delete(void* p) throw ()
void operator delete(void* p) BOOST_NOEXCEPT_OR_NOTHROW
#endif
{
//std::cout << __FILE__ << ":" << __LINE__ << std::endl;

View File

@@ -28,9 +28,11 @@
unsigned throw_one = 0xFFFF;
#if defined _GLIBCXX_THROW
inline void* operator new(std::size_t s) _GLIBCXX_THROW (std::bad_alloc)
void* operator new(std::size_t s) _GLIBCXX_THROW (std::bad_alloc)
#elif defined BOOST_MSVC
inline void* operator new(std::size_t s)
void* operator new(std::size_t s)
#elif __cplusplus > 201402L
void* operator new(std::size_t s)
#else
void* operator new(std::size_t s) throw (std::bad_alloc)
#endif
@@ -41,9 +43,9 @@ void* operator new(std::size_t s) throw (std::bad_alloc)
}
#if defined BOOST_MSVC
inline void operator delete(void* p)
void operator delete(void* p)
#else
inline void operator delete(void* p) throw ()
void operator delete(void* p) BOOST_NOEXCEPT_OR_NOTHROW
#endif
{
std::free(p);