diff --git a/include/boost/thread/detail/config.hpp b/include/boost/thread/detail/config.hpp index f984e7ebb..0669c1126 100644 --- a/include/boost/thread/detail/config.hpp +++ b/include/boost/thread/detail/config.hpp @@ -424,17 +424,32 @@ #if defined(BOOST_THREAD_CHRONO_WINDOWS_API) #define BOOST_THREAD_HAS_MONO_CLOCK #define BOOST_THREAD_INTERNAL_CLOCK_IS_MONO -#elif defined(BOOST_THREAD_CHRONO_MAC_API) - #define BOOST_THREAD_HAS_MONO_CLOCK -#elif defined(__ANDROID__) - #define BOOST_THREAD_HAS_MONO_CLOCK - #if defined(__ANDROID_API__) && __ANDROID_API__ >= 21 - #define BOOST_THREAD_INTERNAL_CLOCK_IS_MONO - #endif #else - #include // check for CLOCK_MONOTONIC - #if defined(CLOCK_MONOTONIC) + #if defined(__ANDROID__) && defined(__ANDROID_API__) && __ANDROID_API__ < 21 + #ifndef BOOST_PTHREAD_HAS_COND_TIMEDWAIT_MONOTONIC_NP + #define BOOST_PTHREAD_HAS_COND_TIMEDWAIT_MONOTONIC_NP + #endif + #endif + #if defined(__ANDROID__) && defined(__ANDROID_API__) && __ANDROID_API__ < 21 \ + || (defined(__APPLE__) && defined(__MACH__) \ + && ((defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1040) \ + || (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 20000))) + #ifndef BOOST_PTHREAD_HAS_COND_TIMEDWAIT_RELATIVE_NP + #define BOOST_PTHREAD_HAS_COND_TIMEDWAIT_RELATIVE_NP + #endif + #endif + #if defined(BOOST_THREAD_CHRONO_MAC_API) #define BOOST_THREAD_HAS_MONO_CLOCK + #else + #include // check for CLOCK_MONOTONIC + #if defined(CLOCK_MONOTONIC) + #define BOOST_THREAD_HAS_MONO_CLOCK + #endif + #endif + #if (defined(BOOST_THREAD_HAS_MONO_CLOCK) \ + && (defined(BOOST_PTHREAD_HAS_COND_TIMEDWAIT_MONOTONIC_NP) \ + || defined(CLOCK_MONOTONIC))) \ + || defined(BOOST_PTHREAD_HAS_COND_TIMEDWAIT_RELATIVE_NP) #define BOOST_THREAD_INTERNAL_CLOCK_IS_MONO #endif #endif @@ -447,6 +462,12 @@ || (defined(__ANDROID__) && defined(__ANDROID_API__) && __ANDROID_API__ >= 21) #define BOOST_THREAD_USES_PTHREAD_TIMEDLOCK #endif +#else +#if defined(BOOST_PTHREAD_HAS_COND_TIMEDWAIT_MONOTONIC_NP) +#define BOOST_THREAD_USES_PTHREAD_COND_TIMEDWAIT_MONOTONIC_NP +#elif defined(BOOST_PTHREAD_HAS_COND_TIMEDWAIT_RELATIVE_NP) +#define BOOST_THREAD_USES_PTHREAD_COND_TIMEDWAIT_RELATIVE_NP +#endif #endif // provided for backwards compatibility, since this diff --git a/include/boost/thread/pthread/pthread_helpers.hpp b/include/boost/thread/pthread/pthread_helpers.hpp index 680999416..5aae9b812 100644 --- a/include/boost/thread/pthread/pthread_helpers.hpp +++ b/include/boost/thread/pthread/pthread_helpers.hpp @@ -8,6 +8,9 @@ // http://www.boost.org/LICENSE_1_0.txt) #include +#ifdef BOOST_THREAD_USES_PTHREAD_COND_TIMEDWAIT_RELATIVE_NP +#include +#endif #include #include #include @@ -18,10 +21,42 @@ #define BOOST_THREAD_HAS_EINTR_BUG #endif +#ifdef __ANDROID__ +#if defined(BOOST_THREAD_USES_PTHREAD_COND_TIMEDWAIT_MONOTONIC_NP) +extern "C" int +pthread_cond_timedwait_monotonic_np(pthread_cond_t *cond, + pthread_mutex_t *mutex, + const struct timespec *abstime); +#elif defined(BOOST_THREAD_USES_PTHREAD_COND_TIMEDWAIT_RELATIVE_NP) +extern "C" int +pthread_cond_timedwait_relative_np(pthread_cond_t *cond, + pthread_mutex_t *mutex, + const struct timespec *reltime); +#endif +#endif + namespace boost { namespace posix { + namespace posix_detail + { + BOOST_FORCEINLINE BOOST_THREAD_DISABLE_THREAD_SAFETY_ANALYSIS + int pthread_cond_timedwait(pthread_cond_t* c, pthread_mutex_t* m, const struct timespec* t) + { +#if defined(BOOST_THREAD_USES_PTHREAD_COND_TIMEDWAIT_MONOTONIC_NP) + return ::pthread_cond_timedwait_monotonic_np(c, m, t); +#elif defined(BOOST_THREAD_USES_PTHREAD_COND_TIMEDWAIT_RELATIVE_NP) + using namespace boost; + + const detail::internal_platform_timepoint ts(*t); + const detail::platform_duration d(ts - detail::internal_platform_clock::now()); + return ::pthread_cond_timedwait_relative_np(c, m, &d.getTs()); +#else + return ::pthread_cond_timedwait(c, m, t); +#endif + } + } BOOST_FORCEINLINE BOOST_THREAD_DISABLE_THREAD_SAFETY_ANALYSIS int pthread_mutex_init(pthread_mutex_t* m, const pthread_mutexattr_t* attr = NULL) { @@ -31,7 +66,9 @@ namespace boost BOOST_FORCEINLINE BOOST_THREAD_DISABLE_THREAD_SAFETY_ANALYSIS int pthread_cond_init(pthread_cond_t* c) { -#ifdef BOOST_THREAD_INTERNAL_CLOCK_IS_MONO +#if defined(BOOST_THREAD_INTERNAL_CLOCK_IS_MONO) \ + && !(defined(BOOST_THREAD_USES_PTHREAD_COND_TIMEDWAIT_MONOTONIC_NP) \ + || defined(BOOST_THREAD_USES_PTHREAD_COND_TIMEDWAIT_RELATIVE_NP)) pthread_condattr_t attr; int res = pthread_condattr_init(&attr); if (res) @@ -120,7 +157,7 @@ namespace boost int ret; do { - ret = ::pthread_cond_timedwait(c, m, t); + ret = posix_detail::pthread_cond_timedwait(c, m, t); } while (ret == EINTR); return ret; } @@ -164,7 +201,7 @@ namespace boost BOOST_FORCEINLINE BOOST_THREAD_DISABLE_THREAD_SAFETY_ANALYSIS int pthread_cond_timedwait(pthread_cond_t* c, pthread_mutex_t* m, const struct timespec* t) { - return ::pthread_cond_timedwait(c, m, t); + return posix_detail::pthread_cond_timedwait(c, m, t); } #endif