2
0
mirror of https://github.com/boostorg/thread.git synced 2026-01-21 17:32:18 +00:00

Merge branch 'develop'

This commit is contained in:
Vicente J. Botet Escriba
2017-08-26 11:00:33 +02:00
14 changed files with 225 additions and 63 deletions

View File

@@ -1,6 +1,6 @@
[/
(C) Copyright 2007-11 Anthony Williams.
(C) Copyright 2011-16 Vicente J. Botet Escriba.
(C) Copyright 2011-17 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).
@@ -8,6 +8,49 @@
[section:changes History]
[heading Version 4.8.0 - boost 1.66]
[*Know Bugs:]
* [@http://svn.boost.org/trac/boost/ticket/3926 #3926] thread_specific_ptr + dlopen library causes a SIGSEGV.
* [@http://svn.boost.org/trac/boost/ticket/10964 #10964] future<future<T>>::unwrap().then() Deadlocks
Please take a look at [@https://svn.boost.org/trac/boost/query?status=assigned&status=new&status=reopened&component=thread&type=!Feature+Requests&col=id&col=summary&order=id thread Know Bugs] to see the current state.
Please take a look at [@http://www.boost.org/development/tests/master/developer/thread.html thread master regression test] to see the last regression test snapshot.
[*Fixed Bugs:]
* [@http://svn.boost.org/trac/boost/ticket/12949 #12949] using sleep_for in a thread context without including boost/thread/thread.hpp yields incorrect behaviour when BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC is defined
* [@http://svn.boost.org/trac/boost/ticket/13019 #13019] ABI compatibility for BOOST_THREAD_PROVIDES_INTERRUPTIONS incomplete
* [@http://svn.boost.org/trac/boost/ticket/13163 #13163] boost::detail::heap_new does not have a variadic variant
* [@https://github.com/boostorg/thread/issues/130 #130] windows: Bug in boost::condition_variable on Windows
[heading Version 4.7.4 - boost 1.65]
[*Fixed Bugs:]
* [@http://svn.boost.org/trac/boost/ticket/6787 #6787] boost::thread::sleep() hangs if system time is rolled back
* [@http://svn.boost.org/trac/boost/ticket/12519 #12519] boost::thread::try_join_for does not return after timeout
* [@http://svn.boost.org/trac/boost/ticket/12874 #12874] future<> extension constructor must be under BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
* [@http://svn.boost.org/trac/boost/ticket/12888 #12888] Linking with boost thread does not work on mingw/gcc 4.4
* [@http://svn.boost.org/trac/boost/ticket/12958 #12958] sync_bounded_queue::wait_pull_front( lve ) might throw
* [@http://svn.boost.org/trac/boost/ticket/13077 #13077] Linking to static 64bit libboost_thread fails DLL initialization
* [@http://svn.boost.org/trac/boost/ticket/13155 #13155] log doesn't build on a system with pthreads
* [@https://github.com/boostorg/thread/issues/121 #121] on_tls_prepare is broken under VS2017
[heading Version 4.7.3 - boost 1.64]
[*Fixed Bugs:]
* [@https://github.com/boostorg/thread/issues/113 #113] Add a Thread template on all the scoped thread and thread guard classes
* [@https://github.com/boostorg/thread/issues/117 #117] loop_executor should block on it's work_queue instead of polling
* [@https://github.com/boostorg/thread/issues/119 #119] basic_condition_variable::relocker::~relocker can throw an exception
[heading Version 4.7.2 - boost 1.63]
[*Fixed Bugs:]
@@ -27,7 +70,7 @@ Please define BOOST_THREAD_PATCH to apply the patch that could unfortunately res
Please take a look at [@https://svn.boost.org/trac/boost/query?status=assigned&status=new&status=reopened&component=thread&type=!Feature+Requests&col=id&col=summary&order=id thread Know Bugs] to see the current state.
Please take a look at [@http://www.boost.org/development/tests/master/developer/thread.html thread trunk regression test] to see the last regression test snapshot.
Please take a look at [@http://www.boost.org/development/tests/master/developer/thread.html thread master regression test] to see the last regression test snapshot.
[*Fixed Bugs:]

View File

@@ -8,10 +8,10 @@
[library Thread
[quickbook 1.5]
[version 4.7.2]
[version 4.8.0]
[authors [Williams, Anthony] [Botet Escriba, Vicente J.]]
[copyright 2007-11 Anthony Williams]
[copyright 2011-16 Vicente J. Botet Escriba]
[copyright 2011-17 Vicente J. Botet Escriba]
[purpose C++ Library for launching threads and synchronizing data between them]
[category text]
[license

View File

@@ -12,21 +12,19 @@
#include <boost/detail/workaround.hpp>
#include <boost/thread/detail/platform.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__))
#else
#define BOOST_THREAD_ATTRIBUTE_MAY_ALIAS
#endif
#define BOOST_THREAD_ATTRIBUTE_MAY_ALIAS BOOST_MAY_ALIAS
#if defined BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED

View File

@@ -157,7 +157,7 @@ namespace boost
}
namespace thread_detail {
#ifdef BOOST_THREAD_USES_CHRONO
#if defined(BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC) && defined(BOOST_THREAD_USEFIXES_TIMESPEC)
#if defined(BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC)
typedef chrono::steady_clock internal_clock_t;
#else
typedef chrono::system_clock internal_clock_t;
@@ -299,7 +299,7 @@ namespace thread_detail {
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

View File

@@ -299,7 +299,7 @@ namespace boost
}
do_continuation(lock);
}
void make_ready()
void notify_deferred()
{
boost::unique_lock<boost::mutex> lock(this->mutex);
mark_finished_internal(lock);

View File

@@ -53,9 +53,9 @@ namespace boost
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:
@@ -69,16 +69,8 @@ namespace boost
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));
#if defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
return do_wait_until(lock, boost::detail::timespec_plus(timeout, boost::detail::timespec_now_monotonic()));
#else
// old behavior was fine for monotonic
return do_wait_until(lock, boost::detail::timespec_plus(timeout, boost::detail::timespec_now_realtime()));
@@ -90,31 +82,37 @@ namespace boost
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
//#endif
res = detail::monotonic_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
//#endif
boost::throw_exception(thread_resource_error(res, "boost::condition_variable::condition_variable() constructor failed in detail::monotonic_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);

View File

@@ -20,7 +20,6 @@
#include <boost/chrono/ceil.hpp>
#endif
#include <boost/thread/detail/delete.hpp>
#include <boost/assert.hpp>
#include <boost/config/abi_prefix.hpp>

View File

@@ -50,7 +50,11 @@ 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();
#else
std::size_t page_size = ::sysconf( _SC_PAGESIZE);
#endif
#ifdef PTHREAD_STACK_MIN
if (size<PTHREAD_STACK_MIN) size=PTHREAD_STACK_MIN;
#endif
@@ -240,10 +244,12 @@ namespace boost
namespace hidden
{
void BOOST_THREAD_DECL sleep_for(const timespec& ts);
void BOOST_THREAD_DECL sleep_until(const timespec& ts);
void BOOST_THREAD_DECL sleep_until_realtime(const timespec& ts);
}
#ifdef BOOST_THREAD_USES_CHRONO
template <class Rep, class Period>
void sleep_for(const chrono::duration<Rep, Period>& d);
#ifdef BOOST_THREAD_SLEEP_FOR_IS_STEADY
inline
@@ -259,10 +265,12 @@ namespace boost
namespace hidden
{
void BOOST_THREAD_DECL sleep_for(const timespec& ts);
void BOOST_THREAD_DECL sleep_until(const timespec& ts);
void BOOST_THREAD_DECL sleep_until_realtime(const timespec& ts);
}
#ifdef BOOST_THREAD_USES_CHRONO
template <class Rep, class Period>
void sleep_for(const chrono::duration<Rep, Period>& d);
#ifdef BOOST_THREAD_SLEEP_FOR_IS_STEADY
inline
@@ -284,7 +292,7 @@ namespace boost
#endif
inline void sleep(system_time const& abs_time)
{
return boost::this_thread::hidden::sleep_until(boost::detail::to_timespec(abs_time));
return boost::this_thread::hidden::sleep_until_realtime(boost::detail::to_timespec(abs_time));
}
template<typename TimeDuration>

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

@@ -71,32 +71,21 @@ namespace boost
{
return (ts.tv_sec >= 0) || (ts.tv_nsec >= 0);
}
inline timespec timespec_now()
#if defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
inline timespec timespec_now_monotonic()
{
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;
}
#endif
inline timespec timespec_now_realtime()
{

View File

@@ -211,7 +211,7 @@ namespace boost
{}
#endif
void remove_waiter()
void remove_waiter_and_reset()
{
if (entry) {
boost::lock_guard<boost::mutex> internal_lock(internal_mutex);
@@ -221,7 +221,7 @@ namespace boost
}
~entry_manager() BOOST_NOEXCEPT_IF(false)
{
remove_waiter();
remove_waiter_and_reset();
}
list_entry* operator->()
@@ -250,7 +250,7 @@ namespace boost
woken=entry->woken();
}
// do it here to avoid throwing on the destructor
entry->remove_waiter();
entry.remove_waiter_and_reset();
locker.lock();
return woken;
}

View File

@@ -72,7 +72,24 @@ namespace boost
{
BOOST_VERIFY(detail::win32::HeapFree(detail::win32::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 +242,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 +481,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

@@ -52,7 +52,7 @@ namespace boost
for (async_states_t::iterator i = async_states_.begin(), e = async_states_.end();
i != e; ++i)
{
(*i)->make_ready();
(*i)->notify_deferred();
}
}
@@ -457,7 +457,7 @@ namespace boost
}
}
void BOOST_THREAD_DECL sleep_until(const timespec& ts)
void BOOST_THREAD_DECL sleep_until_realtime(const timespec& ts)
{
timespec now = boost::detail::timespec_now_realtime();
if (boost::detail::timespec_gt(ts, now))
@@ -487,7 +487,6 @@ namespace boost
}
}
}
}
}
namespace hidden
@@ -507,7 +506,7 @@ namespace boost
}
}
void BOOST_THREAD_DECL sleep_until(const timespec& ts)
void BOOST_THREAD_DECL sleep_until_realtime(const timespec& ts)
{
boost::detail::thread_data_base* const thread_info=boost::detail::get_current_thread_data();
@@ -518,7 +517,7 @@ namespace boost
}
else
{
boost::this_thread::no_interruption_point::hidden::sleep_until(ts);
boost::this_thread::no_interruption_point::hidden::sleep_until_realtime(ts);
}
}
} // hidden

View File

@@ -57,7 +57,7 @@ namespace boost
for (async_states_t::iterator i = async_states_.begin(), e = async_states_.end();
i != e; ++i)
{
(*i)->make_ready();
(*i)->notify_deferred();
}
}
}