summaryrefslogtreecommitdiff
path: root/boost/thread/pthread
diff options
context:
space:
mode:
Diffstat (limited to 'boost/thread/pthread')
-rw-r--r--boost/thread/pthread/condition_variable.hpp171
-rw-r--r--boost/thread/pthread/condition_variable_fwd.hpp155
-rw-r--r--boost/thread/pthread/mutex.hpp100
-rw-r--r--boost/thread/pthread/once.hpp35
-rw-r--r--boost/thread/pthread/recursive_mutex.hpp97
-rw-r--r--boost/thread/pthread/shared_mutex.hpp252
-rw-r--r--boost/thread/pthread/thread_data.hpp57
7 files changed, 759 insertions, 108 deletions
diff --git a/boost/thread/pthread/condition_variable.hpp b/boost/thread/pthread/condition_variable.hpp
index 48ed8ff731..aa7100766e 100644
--- a/boost/thread/pthread/condition_variable.hpp
+++ b/boost/thread/pthread/condition_variable.hpp
@@ -4,11 +4,17 @@
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// (C) Copyright 2007-10 Anthony Williams
+// (C) Copyright 2011 Vicente J. Botet Escriba
#include <boost/thread/pthread/timespec.hpp>
#include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp>
#include <boost/thread/pthread/thread_data.hpp>
#include <boost/thread/pthread/condition_variable_fwd.hpp>
+#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/config/abi_prefix.hpp>
@@ -59,18 +65,22 @@ namespace boost
this_thread::interruption_point();
if(res)
{
- boost::throw_exception(condition_error());
+ boost::throw_exception(condition_error(res, "boost:: condition_variable constructor failed in pthread_cond_wait"));
}
}
- inline bool condition_variable::timed_wait(unique_lock<mutex>& m,boost::system_time const& wait_until)
+ inline bool condition_variable::do_timed_wait(
+ unique_lock<mutex>& m,
+ struct timespec const &timeout)
{
+ if (!m.owns_lock())
+ boost::throw_exception(condition_error(EPERM, "condition_variable do_timed_wait: mutex not locked"));
+
thread_cv_detail::lock_on_exit<unique_lock<mutex> > guard;
int cond_res;
{
detail::interruption_checker check_for_interruption(&internal_mutex,&cond);
guard.activate(m);
- struct timespec const timeout=detail::get_timespec(wait_until);
cond_res=pthread_cond_timedwait(&cond,&internal_mutex,&timeout);
}
this_thread::interruption_point();
@@ -80,18 +90,18 @@ namespace boost
}
if(cond_res)
{
- boost::throw_exception(condition_error());
+ boost::throw_exception(condition_error(cond_res, "condition_variable failed in pthread_cond_timedwait"));
}
return true;
}
- inline void condition_variable::notify_one()
+ inline void condition_variable::notify_one() BOOST_NOEXCEPT
{
boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex);
BOOST_VERIFY(!pthread_cond_signal(&cond));
}
- inline void condition_variable::notify_all()
+ inline void condition_variable::notify_all() BOOST_NOEXCEPT
{
boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex);
BOOST_VERIFY(!pthread_cond_broadcast(&cond));
@@ -102,22 +112,20 @@ namespace boost
pthread_mutex_t internal_mutex;
pthread_cond_t cond;
- condition_variable_any(condition_variable_any&);
- condition_variable_any& operator=(condition_variable_any&);
-
public:
+ BOOST_THREAD_NO_COPYABLE(condition_variable_any)
condition_variable_any()
{
int const res=pthread_mutex_init(&internal_mutex,NULL);
if(res)
{
- boost::throw_exception(thread_resource_error());
+ boost::throw_exception(thread_resource_error(res, "condition_variable_any failed in pthread_mutex_init"));
}
int const res2=pthread_cond_init(&cond,NULL);
if(res2)
{
BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex));
- boost::throw_exception(thread_resource_error());
+ boost::throw_exception(thread_resource_error(res, "condition_variable_any failed in pthread_cond_init"));
}
}
~condition_variable_any()
@@ -139,7 +147,7 @@ namespace boost
this_thread::interruption_point();
if(res)
{
- boost::throw_exception(condition_error());
+ boost::throw_exception(condition_error(res, "condition_variable_any failed in pthread_cond_wait"));
}
}
@@ -153,23 +161,7 @@ namespace boost
bool timed_wait(lock_type& m,boost::system_time const& wait_until)
{
struct timespec const timeout=detail::get_timespec(wait_until);
- int res=0;
- {
- thread_cv_detail::lock_on_exit<lock_type> guard;
- detail::interruption_checker check_for_interruption(&internal_mutex,&cond);
- guard.activate(m);
- res=pthread_cond_timedwait(&cond,&internal_mutex,&timeout);
- }
- this_thread::interruption_point();
- if(res==ETIMEDOUT)
- {
- return false;
- }
- if(res)
- {
- boost::throw_exception(condition_error());
- }
- return true;
+ return do_timed_wait(m, timeout);
}
template<typename lock_type>
bool timed_wait(lock_type& m,xtime const& wait_until)
@@ -206,17 +198,134 @@ namespace boost
return timed_wait(m,get_system_time()+wait_duration,pred);
}
- void notify_one()
+#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)
+ {
+ 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;
+ }
+
+ 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;
+ 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;
+ }
+
+ template <class lock_type, class Clock, class Duration, class Predicate>
+ bool
+ wait_until(
+ lock_type& lock,
+ const chrono::time_point<Clock, Duration>& t,
+ Predicate pred)
+ {
+ while (!pred())
+ {
+ if (wait_until(lock, t) == cv_status::timeout)
+ return pred();
+ }
+ return true;
+ }
+
+
+ template <class lock_type, class Rep, class Period>
+ cv_status
+ wait_for(
+ 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;
+
+ }
+
+
+ template <class lock_type, class Rep, class Period, class Predicate>
+ bool
+ wait_for(
+ lock_type& lock,
+ const chrono::duration<Rep, Period>& d,
+ Predicate pred)
+ {
+ while (!pred())
+ {
+ if (wait_for(lock, d) == cv_status::timeout)
+ return pred();
+ }
+ return true;
+ }
+
+ template <class lock_type>
+ inline void 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;
+ seconds s = duration_cast<seconds>(d);
+ ts.tv_sec = static_cast<long>(s.count());
+ ts.tv_nsec = static_cast<long>((d - s).count());
+ do_timed_wait(lk, ts);
+ }
+#endif
+
+ void notify_one() BOOST_NOEXCEPT
{
boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex);
BOOST_VERIFY(!pthread_cond_signal(&cond));
}
- void notify_all()
+ void notify_all() BOOST_NOEXCEPT
{
boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex);
BOOST_VERIFY(!pthread_cond_broadcast(&cond));
}
+ private: // used by boost::thread::try_join_until
+
+ template <class lock_type>
+ inline bool do_timed_wait(
+ lock_type& m,
+ struct timespec const &timeout)
+ {
+ int res=0;
+ {
+ thread_cv_detail::lock_on_exit<lock_type> guard;
+ detail::interruption_checker check_for_interruption(&internal_mutex,&cond);
+ guard.activate(m);
+ res=pthread_cond_timedwait(&cond,&internal_mutex,&timeout);
+ }
+ this_thread::interruption_point();
+ if(res==ETIMEDOUT)
+ {
+ return false;
+ }
+ if(res)
+ {
+ boost::throw_exception(condition_error(res, "condition_variable_any failed in pthread_cond_timedwait"));
+ }
+ return true;
+ }
+
+
};
}
diff --git a/boost/thread/pthread/condition_variable_fwd.hpp b/boost/thread/pthread/condition_variable_fwd.hpp
index f56bee4789..4f4bd881d9 100644
--- a/boost/thread/pthread/condition_variable_fwd.hpp
+++ b/boost/thread/pthread/condition_variable_fwd.hpp
@@ -4,41 +4,47 @@
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// (C) Copyright 2007-8 Anthony Williams
+// (C) Copyright 2011 Vicente J. Botet Escriba
#include <boost/assert.hpp>
#include <boost/throw_exception.hpp>
#include <pthread.h>
+#include <boost/thread/cv_status.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/locks.hpp>
#include <boost/thread/thread_time.hpp>
#include <boost/thread/xtime.hpp>
-
+#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/date_time/posix_time/posix_time_duration.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
+
class condition_variable
{
private:
pthread_mutex_t internal_mutex;
pthread_cond_t cond;
- condition_variable(condition_variable&);
- condition_variable& operator=(condition_variable&);
-
public:
+ BOOST_THREAD_NO_COPYABLE(condition_variable)
condition_variable()
{
int const res=pthread_mutex_init(&internal_mutex,NULL);
if(res)
{
- boost::throw_exception(thread_resource_error());
+ boost::throw_exception(thread_resource_error(res, "boost:: condition_variable constructor failed in pthread_mutex_init"));
}
int const res2=pthread_cond_init(&cond,NULL);
if(res2)
{
BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex));
- boost::throw_exception(thread_resource_error());
+ boost::throw_exception(thread_resource_error(res2, "boost:: condition_variable constructor failed in pthread_cond_init"));
}
}
~condition_variable()
@@ -59,21 +65,38 @@ namespace boost
while(!pred()) wait(m);
}
- inline bool timed_wait(unique_lock<mutex>& m,
- boost::system_time const& wait_until);
- bool timed_wait(unique_lock<mutex>& m,xtime const& wait_until)
+
+ inline bool timed_wait(
+ unique_lock<mutex>& m,
+ boost::system_time const& wait_until)
+ {
+#if defined BOOST_THREAD_WAIT_BUG
+ struct timespec const timeout=detail::get_timespec(wait_until + BOOST_THREAD_WAIT_BUG);
+ return do_timed_wait(m, timeout);
+#else
+ struct timespec const timeout=detail::get_timespec(wait_until);
+ return do_timed_wait(m, timeout);
+#endif
+ }
+ bool timed_wait(
+ unique_lock<mutex>& m,
+ xtime const& wait_until)
{
return timed_wait(m,system_time(wait_until));
}
template<typename duration_type>
- bool timed_wait(unique_lock<mutex>& m,duration_type const& wait_duration)
+ bool timed_wait(
+ unique_lock<mutex>& m,
+ duration_type const& wait_duration)
{
return timed_wait(m,get_system_time()+wait_duration);
}
template<typename predicate_type>
- bool timed_wait(unique_lock<mutex>& m,boost::system_time const& wait_until,predicate_type pred)
+ bool timed_wait(
+ unique_lock<mutex>& m,
+ boost::system_time const& wait_until,predicate_type pred)
{
while (!pred())
{
@@ -84,25 +107,127 @@ namespace boost
}
template<typename predicate_type>
- bool timed_wait(unique_lock<mutex>& m,xtime const& wait_until,predicate_type pred)
+ bool timed_wait(
+ unique_lock<mutex>& m,
+ xtime const& wait_until,predicate_type pred)
{
return timed_wait(m,system_time(wait_until),pred);
}
template<typename duration_type,typename predicate_type>
- bool timed_wait(unique_lock<mutex>& m,duration_type const& wait_duration,predicate_type pred)
+ bool timed_wait(
+ unique_lock<mutex>& m,
+ duration_type const& wait_duration,predicate_type pred)
{
return timed_wait(m,get_system_time()+wait_duration,pred);
}
+#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)
+ {
+ 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;
+ }
+
+ template <class Clock, class Duration>
+ cv_status
+ wait_until(
+ 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;
+ }
+
+ template <class Clock, class Duration, class Predicate>
+ bool
+ wait_until(
+ unique_lock<mutex>& lock,
+ const chrono::time_point<Clock, Duration>& t,
+ Predicate pred)
+ {
+ while (!pred())
+ {
+ if (wait_until(lock, t) == cv_status::timeout)
+ return pred();
+ }
+ return true;
+ }
+
+
+ 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;
+
+ }
+
+
+ template <class Rep, class Period, class Predicate>
+ bool
+ wait_for(
+ unique_lock<mutex>& lock,
+ const chrono::duration<Rep, Period>& d,
+ Predicate pred)
+ {
+ while (!pred())
+ {
+ if (wait_for(lock, d) == cv_status::timeout)
+ return pred();
+ }
+ return true;
+ }
+#endif
+
+#define BOOST_THREAD_DEFINES_CONDITION_VARIABLE_NATIVE_HANDLE
typedef pthread_cond_t* native_handle_type;
native_handle_type native_handle()
{
return &cond;
}
- void notify_one();
- void notify_all();
+ void notify_one() BOOST_NOEXCEPT;
+ void notify_all() BOOST_NOEXCEPT;
+
+#ifdef BOOST_THREAD_USES_CHRONO
+ inline void 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;
+ seconds s = duration_cast<seconds>(d);
+ ts.tv_sec = static_cast<long>(s.count());
+ ts.tv_nsec = static_cast<long>((d - s).count());
+ do_timed_wait(lk, ts);
+ }
+#endif
+ //private: // used by boost::thread::try_join_until
+
+ inline bool do_timed_wait(
+ unique_lock<mutex>& lock,
+ struct timespec const &timeout);
};
}
diff --git a/boost/thread/pthread/mutex.hpp b/boost/thread/pthread/mutex.hpp
index fc7c9cdfad..2c5af92b8a 100644
--- a/boost/thread/pthread/mutex.hpp
+++ b/boost/thread/pthread/mutex.hpp
@@ -1,12 +1,12 @@
#ifndef BOOST_THREAD_PTHREAD_MUTEX_HPP
#define BOOST_THREAD_PTHREAD_MUTEX_HPP
// (C) Copyright 2007-8 Anthony Williams
+// (C) Copyright 2011-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 <pthread.h>
-#include <boost/utility.hpp>
#include <boost/throw_exception.hpp>
#include <boost/thread/exceptions.hpp>
#include <boost/thread/locks.hpp>
@@ -16,6 +16,11 @@
#include <errno.h>
#include <boost/thread/pthread/timespec.hpp>
#include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp>
+#ifdef BOOST_THREAD_USES_CHRONO
+#include <boost/chrono/system_clocks.hpp>
+#include <boost/chrono/ceil.hpp>
+#endif
+#include <boost/thread/detail/delete.hpp>
#ifdef _POSIX_TIMEOUTS
#if _POSIX_TIMEOUTS >= 0 && _POSIX_C_SOURCE>=200112L
@@ -30,16 +35,16 @@ namespace boost
class mutex
{
private:
- mutex(mutex const&);
- mutex& operator=(mutex const&);
pthread_mutex_t m;
public:
+ BOOST_THREAD_NO_COPYABLE(mutex)
+
mutex()
{
int const res=pthread_mutex_init(&m,NULL);
if(res)
{
- boost::throw_exception(thread_resource_error());
+ boost::throw_exception(thread_resource_error(res, "boost:: mutex constructor failed in pthread_mutex_init"));
}
}
~mutex()
@@ -58,9 +63,9 @@ namespace boost
{
res = pthread_mutex_lock(&m);
} while (res == EINTR);
- if(res)
+ if (res)
{
- boost::throw_exception(lock_error(res));
+ boost::throw_exception(lock_error(res,"boost: mutex lock failed in pthread_mutex_lock"));
}
}
@@ -83,12 +88,17 @@ namespace boost
} while (res == EINTR);
if(res && (res!=EBUSY))
{
- boost::throw_exception(lock_error(res));
+ // The following throw_exception has been replaced by an assertion and just return false,
+ // as this is an internal error and the user can do nothing with the exception.
+ //boost::throw_exception(lock_error(res,"boost: mutex try_lock failed in pthread_mutex_trylock"));
+ BOOST_ASSERT_MSG(false ,"boost: mutex try_lock failed in pthread_mutex_trylock");
+ return false;
}
return !res;
}
+#define BOOST_THREAD_DEFINES_MUTEX_NATIVE_HANDLE
typedef pthread_mutex_t* native_handle_type;
native_handle_type native_handle()
{
@@ -104,28 +114,26 @@ namespace boost
class timed_mutex
{
private:
- timed_mutex(timed_mutex const&);
- timed_mutex& operator=(timed_mutex const&);
- private:
pthread_mutex_t m;
#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK
pthread_cond_t cond;
bool is_locked;
#endif
public:
+ BOOST_THREAD_NO_COPYABLE(timed_mutex)
timed_mutex()
{
int const res=pthread_mutex_init(&m,NULL);
if(res)
{
- boost::throw_exception(thread_resource_error());
+ 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);
if(res2)
{
BOOST_VERIFY(!pthread_mutex_destroy(&m));
- boost::throw_exception(thread_resource_error());
+ boost::throw_exception(thread_resource_error(res2, "boost:: timed_mutex constructor failed in pthread_cond_init"));
}
is_locked=false;
#endif
@@ -165,19 +173,16 @@ namespace boost
BOOST_ASSERT(!res || res==EBUSY);
return !res;
}
- bool timed_lock(system_time const & abs_time)
- {
- struct timespec const timeout=detail::get_timespec(abs_time);
- int const res=pthread_mutex_timedlock(&m,&timeout);
- BOOST_ASSERT(!res || res==ETIMEDOUT);
- return !res;
- }
- typedef pthread_mutex_t* native_handle_type;
- native_handle_type native_handle()
+
+ private:
+ bool do_try_lock_until(struct timespec const &timeout)
{
- return &m;
+ int const res=pthread_mutex_timedlock(&m,&timeout);
+ BOOST_ASSERT(!res || res==ETIMEDOUT);
+ return !res;
}
+ public:
#else
void lock()
@@ -208,9 +213,9 @@ namespace boost
return true;
}
- bool timed_lock(system_time const & abs_time)
+ private:
+ bool do_try_lock_until(struct timespec const &timeout)
{
- struct timespec const timeout=detail::get_timespec(abs_time);
boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
while(is_locked)
{
@@ -224,8 +229,55 @@ namespace boost
is_locked=true;
return true;
}
+ public:
+#endif
+
+ bool timed_lock(system_time const & abs_time)
+ {
+ struct timespec const ts=detail::get_timespec(abs_time);
+ return do_try_lock_until(ts);
+ }
+
+#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>& 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));
+ }
+ template <class Duration>
+ bool try_lock_until(const chrono::time_point<chrono::system_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;
+ nanoseconds d = tp.time_since_epoch();
+ timespec ts;
+ seconds s = duration_cast<seconds>(d);
+ ts.tv_sec = static_cast<long>(s.count());
+ ts.tv_nsec = static_cast<long>((d - s).count());
+ return do_try_lock_until(ts);
+ }
#endif
+#define BOOST_THREAD_DEFINES_TIMED_MUTEX_NATIVE_HANDLE
+ typedef pthread_mutex_t* native_handle_type;
+ native_handle_type native_handle()
+ {
+ return &m;
+ }
+
typedef unique_lock<timed_mutex> scoped_timed_lock;
typedef detail::try_lock_wrapper<timed_mutex> scoped_try_lock;
typedef scoped_timed_lock scoped_lock;
diff --git a/boost/thread/pthread/once.hpp b/boost/thread/pthread/once.hpp
index 81e744e645..80aa09ee12 100644
--- a/boost/thread/pthread/once.hpp
+++ b/boost/thread/pthread/once.hpp
@@ -4,29 +4,52 @@
// once.hpp
//
// (C) Copyright 2007-8 Anthony Williams
+// (C) Copyright 2011-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/config.hpp>
#include <pthread.h>
#include <boost/assert.hpp>
#include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp>
#include <boost/cstdint.hpp>
+#include <boost/thread/detail/delete.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
+#define BOOST_ONCE_INITIAL_FLAG_VALUE 0
+
+#ifdef BOOST_THREAD_PROVIDES_ONCE_CXX11
+
+ struct once_flag
+ {
+ BOOST_THREAD_NO_COPYABLE(once_flag)
+ BOOST_CONSTEXPR once_flag() BOOST_NOEXCEPT
+ : epoch(BOOST_ONCE_INITIAL_FLAG_VALUE)
+ {}
+ private:
+ boost::uintmax_t epoch;
+ template<typename Function>
+ friend
+ void call_once(once_flag& flag,Function f);
+ };
+
+#else // BOOST_THREAD_PROVIDES_ONCE_CXX11
+
struct once_flag
{
boost::uintmax_t epoch;
};
+#define BOOST_ONCE_INIT {BOOST_ONCE_INITIAL_FLAG_VALUE}
+#endif // BOOST_THREAD_PROVIDES_ONCE_CXX11
+
namespace detail
{
BOOST_THREAD_DECL boost::uintmax_t& get_once_per_thread_epoch();
@@ -35,10 +58,6 @@ namespace boost
BOOST_THREAD_DECL extern pthread_cond_t once_epoch_cv;
}
-#define BOOST_ONCE_INITIAL_FLAG_VALUE 0
-#define BOOST_ONCE_INIT {BOOST_ONCE_INITIAL_FLAG_VALUE}
-
-
// Based on Mike Burrows fast_pthread_once algorithm as described in
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2444.html
template<typename Function>
@@ -59,18 +78,18 @@ namespace boost
{
flag.epoch=being_initialized;
#ifndef BOOST_NO_EXCEPTIONS
- try
+ try // BOOST_NO_EXCEPTIONS protected
{
#endif
pthread::pthread_mutex_scoped_unlock relocker(&detail::once_epoch_mutex);
f();
#ifndef BOOST_NO_EXCEPTIONS
}
- catch(...)
+ catch(...) // BOOST_NO_EXCEPTIONS protected
{
flag.epoch=uninitialized_flag;
BOOST_VERIFY(!pthread_cond_broadcast(&detail::once_epoch_cv));
- throw;
+ throw; // BOOST_NO_EXCEPTIONS protected
}
#endif
flag.epoch=--detail::once_global_epoch;
diff --git a/boost/thread/pthread/recursive_mutex.hpp b/boost/thread/pthread/recursive_mutex.hpp
index 113a0ac15e..22acf41fa2 100644
--- a/boost/thread/pthread/recursive_mutex.hpp
+++ b/boost/thread/pthread/recursive_mutex.hpp
@@ -1,12 +1,12 @@
#ifndef BOOST_THREAD_PTHREAD_RECURSIVE_MUTEX_HPP
#define BOOST_THREAD_PTHREAD_RECURSIVE_MUTEX_HPP
// (C) Copyright 2007-8 Anthony Williams
+// (C) Copyright 2011-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 <pthread.h>
-#include <boost/utility.hpp>
#include <boost/throw_exception.hpp>
#include <boost/thread/exceptions.hpp>
#include <boost/thread/locks.hpp>
@@ -19,6 +19,11 @@
#include <errno.h>
#include <boost/thread/pthread/timespec.hpp>
#include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp>
+#ifdef BOOST_THREAD_USES_CHRONO
+#include <boost/chrono/system_clocks.hpp>
+#include <boost/chrono/ceil.hpp>
+#endif
+#include <boost/thread/detail/delete.hpp>
#ifdef _POSIX_TIMEOUTS
#if _POSIX_TIMEOUTS >= 0
@@ -37,8 +42,6 @@ namespace boost
class recursive_mutex
{
private:
- recursive_mutex(recursive_mutex const&);
- recursive_mutex& operator=(recursive_mutex const&);
pthread_mutex_t m;
#ifndef BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE
pthread_cond_t cond;
@@ -47,6 +50,7 @@ namespace boost
unsigned count;
#endif
public:
+ BOOST_THREAD_NO_COPYABLE(recursive_mutex)
recursive_mutex()
{
#ifdef BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE
@@ -55,33 +59,33 @@ namespace boost
int const init_attr_res=pthread_mutexattr_init(&attr);
if(init_attr_res)
{
- boost::throw_exception(thread_resource_error());
+ boost::throw_exception(thread_resource_error(init_attr_res, "boost:: recursive_mutex constructor failed in pthread_mutexattr_init"));
}
int const set_attr_res=pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE);
if(set_attr_res)
{
BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));
- boost::throw_exception(thread_resource_error());
+ boost::throw_exception(thread_resource_error(set_attr_res, "boost:: recursive_mutex constructor failed in pthread_mutexattr_settype"));
}
int const res=pthread_mutex_init(&m,&attr);
if(res)
{
BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));
- boost::throw_exception(thread_resource_error());
+ boost::throw_exception(thread_resource_error(res, "boost:: recursive_mutex constructor failed in pthread_mutex_init"));
}
BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));
#else
int const res=pthread_mutex_init(&m,NULL);
if(res)
{
- boost::throw_exception(thread_resource_error());
+ boost::throw_exception(thread_resource_error(res, "boost:: recursive_mutex constructor failed in pthread_mutex_init"));
}
int const res2=pthread_cond_init(&cond,NULL);
if(res2)
{
BOOST_VERIFY(!pthread_mutex_destroy(&m));
- boost::throw_exception(thread_resource_error());
+ boost::throw_exception(thread_resource_error(res2, "boost:: recursive_mutex constructor failed in pthread_cond_init"));
}
is_locked=false;
count=0;
@@ -112,6 +116,7 @@ namespace boost
BOOST_ASSERT(!res || res==EBUSY);
return !res;
}
+#define BOOST_THREAD_DEFINES_RECURSIVE_MUTEX_NATIVE_HANDLE
typedef pthread_mutex_t* native_handle_type;
native_handle_type native_handle()
{
@@ -171,9 +176,6 @@ namespace boost
class recursive_timed_mutex
{
private:
- recursive_timed_mutex(recursive_timed_mutex const&);
- recursive_timed_mutex& operator=(recursive_timed_mutex const&);
- private:
pthread_mutex_t m;
#ifndef BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK
pthread_cond_t cond;
@@ -182,6 +184,7 @@ namespace boost
unsigned count;
#endif
public:
+ BOOST_THREAD_NO_COPYABLE(recursive_timed_mutex)
recursive_timed_mutex()
{
#ifdef BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK
@@ -190,32 +193,32 @@ namespace boost
int const init_attr_res=pthread_mutexattr_init(&attr);
if(init_attr_res)
{
- boost::throw_exception(thread_resource_error());
+ boost::throw_exception(thread_resource_error(init_attr_res, "boost:: recursive_timed_mutex constructor failed in pthread_mutexattr_init"));
}
int const set_attr_res=pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE);
if(set_attr_res)
{
- boost::throw_exception(thread_resource_error());
+ boost::throw_exception(thread_resource_error(set_attr_res, "boost:: recursive_timed_mutex constructor failed in pthread_mutexattr_settype"));
}
int const res=pthread_mutex_init(&m,&attr);
if(res)
{
BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));
- boost::throw_exception(thread_resource_error());
+ boost::throw_exception(thread_resource_error(res, "boost:: recursive_timed_mutex constructor failed in pthread_mutex_init"));
}
BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));
#else
int const res=pthread_mutex_init(&m,NULL);
if(res)
{
- boost::throw_exception(thread_resource_error());
+ 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);
if(res2)
{
BOOST_VERIFY(!pthread_mutex_destroy(&m));
- boost::throw_exception(thread_resource_error());
+ boost::throw_exception(thread_resource_error(res2, "boost:: recursive_timed_mutex constructor failed in pthread_cond_init"));
}
is_locked=false;
count=0;
@@ -252,19 +255,15 @@ namespace boost
BOOST_ASSERT(!res || res==EBUSY);
return !res;
}
- bool timed_lock(system_time const & abs_time)
+ private:
+ bool do_try_lock_until(struct timespec const &timeout)
{
- struct timespec const timeout=detail::get_timespec(abs_time);
int const res=pthread_mutex_timedlock(&m,&timeout);
BOOST_ASSERT(!res || res==ETIMEDOUT);
return !res;
}
- typedef pthread_mutex_t* native_handle_type;
- native_handle_type native_handle()
- {
- return &m;
- }
+ public:
#else
void lock()
@@ -308,9 +307,9 @@ namespace boost
return true;
}
- bool timed_lock(system_time const & abs_time)
+ private:
+ bool do_try_lock_until(struct timespec const &timeout)
{
- struct timespec const timeout=detail::get_timespec(abs_time);
boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
if(is_locked && pthread_equal(owner,pthread_self()))
{
@@ -331,8 +330,56 @@ namespace boost
owner=pthread_self();
return true;
}
+ public:
+
+#endif
+
+ bool timed_lock(system_time const & abs_time)
+ {
+ struct timespec const ts=detail::get_timespec(abs_time);
+ return do_try_lock_until(ts);
+ }
+
+#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>& 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));
+ }
+ template <class Duration>
+ bool try_lock_until(const chrono::time_point<chrono::system_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;
+ nanoseconds d = tp.time_since_epoch();
+ timespec ts;
+ seconds s = duration_cast<seconds>(d);
+ ts.tv_sec = static_cast<long>(s.count());
+ ts.tv_nsec = static_cast<long>((d - s).count());
+ return do_try_lock_until(ts);
+ }
#endif
+#define BOOST_THREAD_DEFINES_RECURSIVE_TIMED_MUTEX_NATIVE_HANDLE
+ typedef pthread_mutex_t* native_handle_type;
+ native_handle_type native_handle()
+ {
+ return &m;
+ }
+
typedef unique_lock<recursive_timed_mutex> scoped_timed_lock;
typedef detail::try_lock_wrapper<recursive_timed_mutex> scoped_try_lock;
typedef scoped_timed_lock scoped_lock;
diff --git a/boost/thread/pthread/shared_mutex.hpp b/boost/thread/pthread/shared_mutex.hpp
index 56e209acf3..cf45188606 100644
--- a/boost/thread/pthread/shared_mutex.hpp
+++ b/boost/thread/pthread/shared_mutex.hpp
@@ -2,6 +2,7 @@
#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
@@ -12,6 +13,11 @@
#include <boost/thread/mutex.hpp>
#include <boost/thread/condition_variable.hpp>
#include <boost/thread/detail/thread_interruption.hpp>
+#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/config/abi_prefix.hpp>
@@ -42,8 +48,9 @@ namespace boost
shared_cond.notify_all();
}
-
public:
+ BOOST_THREAD_NO_COPYABLE(shared_mutex)
+
shared_mutex()
{
state_data state_={0,0,0,0};
@@ -102,7 +109,29 @@ namespace boost
{
return timed_lock_shared(get_system_time()+relative_time);
}
-
+#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)
+ {
+ boost::this_thread::disable_interruption do_not_disturb;
+ boost::mutex::scoped_lock lk(state_change);
+
+ while(state.exclusive || state.exclusive_waiting_blocked)
+ {
+ if(cv_status::timeout==shared_cond.wait_until(lk,abs_time))
+ {
+ return false;
+ }
+ }
+ ++state.shared_count;
+ return true;
+ }
+#endif
void unlock_shared()
{
boost::mutex::scoped_lock lk(state_change);
@@ -166,6 +195,37 @@ namespace boost
return timed_lock(get_system_time()+relative_time);
}
+#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)
+ {
+ boost::this_thread::disable_interruption do_not_disturb;
+ boost::mutex::scoped_lock lk(state_change);
+
+ while(state.shared_count || state.exclusive)
+ {
+ 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=true;
+ return true;
+ }
+#endif
+
bool try_lock()
{
boost::mutex::scoped_lock lk(state_change);
@@ -228,6 +288,33 @@ namespace boost
return timed_lock_upgrade(get_system_time()+relative_time);
}
+#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)
+ {
+ boost::this_thread::disable_interruption do_not_disturb;
+ boost::mutex::scoped_lock lk(state_change);
+ while(state.exclusive || state.exclusive_waiting_blocked || state.upgrade)
+ {
+ if(cv_status::timeout == shared_cond.wait_until(lk,abs_time))
+ {
+ if(state.exclusive || state.exclusive_waiting_blocked || state.upgrade)
+ {
+ return false;
+ }
+ break;
+ }
+ }
+ ++state.shared_count;
+ state.upgrade=true;
+ return true;
+ }
+#endif
bool try_lock_upgrade()
{
boost::mutex::scoped_lock lk(state_change);
@@ -253,9 +340,12 @@ namespace boost
{
state.exclusive_waiting_blocked=false;
release_waiters();
+ } else {
+ shared_cond.notify_all();
}
}
+ // Upgrade <-> Exclusive
void unlock_upgrade_and_lock()
{
boost::this_thread::disable_interruption do_not_disturb;
@@ -279,6 +369,57 @@ namespace boost
release_waiters();
}
+ bool try_unlock_upgrade_and_lock()
+ {
+ boost::mutex::scoped_lock lk(state_change);
+ if( !state.exclusive
+ && !state.exclusive_waiting_blocked
+ && state.upgrade
+ && state.shared_count==1)
+ {
+ state.shared_count=0;
+ state.exclusive=true;
+ state.upgrade=false;
+ 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)
+ {
+ boost::this_thread::disable_interruption do_not_disturb;
+ boost::mutex::scoped_lock lk(state_change);
+ if (state.shared_count != 1)
+ {
+ for (;;)
+ {
+ cv_status status = shared_cond.wait_until(lk,abs_time);
+ if (state.shared_count == 1)
+ break;
+ if(status == cv_status::timeout)
+ return false;
+ }
+ }
+ state.upgrade=false;
+ state.exclusive=true;
+ state.exclusive_waiting_blocked=false;
+ state.shared_count=0;
+ return true;
+ }
+#endif
+
+ // Shared <-> Exclusive
void unlock_and_lock_shared()
{
boost::mutex::scoped_lock lk(state_change);
@@ -288,6 +429,58 @@ namespace boost
release_waiters();
}
+#ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
+ bool try_unlock_shared_and_lock()
+ {
+ boost::mutex::scoped_lock lk(state_change);
+ if( !state.exclusive
+ && !state.exclusive_waiting_blocked
+ && !state.upgrade
+ && state.shared_count==1)
+ {
+ state.shared_count=0;
+ state.exclusive=true;
+ 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)
+ {
+ boost::this_thread::disable_interruption do_not_disturb;
+ boost::mutex::scoped_lock lk(state_change);
+ if (state.shared_count != 1)
+ {
+ for (;;)
+ {
+ cv_status status = shared_cond.wait_until(lk,abs_time);
+ if (state.shared_count == 1)
+ break;
+ if(status == cv_status::timeout)
+ return false;
+ }
+ }
+ state.upgrade=false;
+ state.exclusive=true;
+ state.exclusive_waiting_blocked=false;
+ state.shared_count=0;
+ return true;
+ }
+#endif
+#endif
+
+ // Shared <-> Upgrade
void unlock_upgrade_and_lock_shared()
{
boost::mutex::scoped_lock lk(state_change);
@@ -295,7 +488,62 @@ namespace boost
state.exclusive_waiting_blocked=false;
release_waiters();
}
+
+#ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
+ bool try_unlock_shared_and_lock_upgrade()
+ {
+ boost::mutex::scoped_lock lk(state_change);
+ if( !state.exclusive
+ && !state.exclusive_waiting_blocked
+ && !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)
+ {
+ boost::this_thread::disable_interruption do_not_disturb;
+ boost::mutex::scoped_lock lk(state_change);
+ if( state.exclusive
+ || state.exclusive_waiting_blocked
+ || state.upgrade
+ )
+ {
+ 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;
+ }
+ }
+ state.upgrade=true;
+ return true;
+ }
+#endif
+#endif
};
+
+ typedef shared_mutex upgrade_mutex;
}
#include <boost/config/abi_suffix.hpp>
diff --git a/boost/thread/pthread/thread_data.hpp b/boost/thread/pthread/thread_data.hpp
index 3de9b41b17..5f84799f85 100644
--- a/boost/thread/pthread/thread_data.hpp
+++ b/boost/thread/pthread/thread_data.hpp
@@ -4,6 +4,7 @@
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// (C) Copyright 2007 Anthony Williams
+// (C) Copyright 2011-2012 Vicente J. Botet Escriba
#include <boost/thread/detail/config.hpp>
#include <boost/thread/exceptions.hpp>
@@ -15,11 +16,56 @@
#include <boost/assert.hpp>
#include <boost/thread/pthread/condition_variable_fwd.hpp>
#include <map>
-
+#include <unistd.h>
+#ifdef BOOST_THREAD_USES_CHRONO
+#include <boost/chrono/system_clocks.hpp>
+#endif
#include <boost/config/abi_prefix.hpp>
namespace boost
{
+ class thread_attributes {
+ public:
+ thread_attributes() BOOST_NOEXCEPT {
+ int res = pthread_attr_init(&val_);
+ BOOST_VERIFY(!res && "pthread_attr_init failed");
+ }
+ ~thread_attributes() {
+ int res = pthread_attr_destroy(&val_);
+ BOOST_VERIFY(!res && "pthread_attr_destroy failed");
+ }
+ // stack
+ void set_stack_size(std::size_t size) BOOST_NOEXCEPT {
+ if (size==0) return;
+ std::size_t page_size = getpagesize();
+#ifdef PTHREAD_STACK_MIN
+ if (size<PTHREAD_STACK_MIN) size=PTHREAD_STACK_MIN;
+#endif
+ size = ((size+page_size-1)/page_size)*page_size;
+ int res = pthread_attr_setstacksize(&val_, size);
+ BOOST_VERIFY(!res && "pthread_attr_setstacksize failed");
+ }
+
+ std::size_t get_stack_size() const BOOST_NOEXCEPT {
+ std::size_t size;
+ int res = pthread_attr_getstacksize(&val_, &size);
+ BOOST_VERIFY(!res && "pthread_attr_getstacksize failed");
+ return size;
+ }
+#define BOOST_THREAD_DEFINES_THREAD_ATTRIBUTES_NATIVE_HANDLE
+
+ typedef pthread_attr_t native_handle_type;
+ native_handle_type* native_handle() BOOST_NOEXCEPT {
+ return &val_;
+ }
+ const native_handle_type* native_handle() const BOOST_NOEXCEPT {
+ return &val_;
+ }
+
+ private:
+ pthread_attr_t val_;
+ };
+
class thread;
namespace detail
@@ -83,11 +129,13 @@ namespace boost
void check_for_interruption()
{
+#ifndef BOOST_NO_EXCEPTIONS
if(thread_info->interrupt_requested)
{
thread_info->interrupt_requested=false;
- throw thread_interrupted();
+ throw thread_interrupted(); // BOOST_NO_EXCEPTIONS protected
}
+#endif
}
void operator=(interruption_checker&);
@@ -128,7 +176,10 @@ namespace boost
namespace this_thread
{
- void BOOST_THREAD_DECL yield();
+#ifdef BOOST_THREAD_USES_CHRONO
+ void BOOST_SYMBOL_VISIBLE sleep_for(const chrono::nanoseconds& ns);
+#endif
+ void BOOST_THREAD_DECL yield() BOOST_NOEXCEPT;
#ifdef __DECXXX
/// Workaround of DECCXX issue of incorrect template substitution