QWaitCondition/Unix: do check for pthread_condattr_setclock()
Instead of guessing that Apple systems don't have it. Because of this, we properly split the clockid_t constants in qcore_unix_p.h between what the std::chrono::steady_clock uses and what QWaitCondition will use. The difference is on Apple systems and on QNX. Therefore, amends 5642b999754e75a9db3585b97ffbddac761f21b3. Change-Id: Ibf5439b6cb4c332b0f24fffde43452e8ccd4e9c9 Reviewed-by: Ahmad Samir <a.samirh78@gmail.com>
This commit is contained in:
parent
b6ca35f653
commit
2a7cacb5e3
@ -446,6 +446,20 @@ int main()
|
|||||||
}
|
}
|
||||||
")
|
")
|
||||||
|
|
||||||
|
# pthread_condattr_setclock
|
||||||
|
qt_config_compile_test(pthread_condattr_setclock
|
||||||
|
LABEL "pthread_condattr_setclock()"
|
||||||
|
LIBRARIES Threads::Threads
|
||||||
|
CODE
|
||||||
|
"#include <pthread.h>
|
||||||
|
#include <time.h>
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
pthread_condattr_t condattr;
|
||||||
|
return pthread_condattr_setclock(&condattr, CLOCK_REALTIME);
|
||||||
|
}
|
||||||
|
")
|
||||||
|
|
||||||
# pthread_timedjoin
|
# pthread_timedjoin
|
||||||
qt_config_compile_test(pthread_timedjoin
|
qt_config_compile_test(pthread_timedjoin
|
||||||
LABEL "pthread_timedjoin()"
|
LABEL "pthread_timedjoin()"
|
||||||
@ -730,6 +744,11 @@ qt_feature("pthread_clockjoin" PRIVATE
|
|||||||
AUTODETECT UNIX
|
AUTODETECT UNIX
|
||||||
CONDITION UNIX AND QT_FEATURE_thread AND TEST_pthread_clockjoin
|
CONDITION UNIX AND QT_FEATURE_thread AND TEST_pthread_clockjoin
|
||||||
)
|
)
|
||||||
|
qt_feature("pthread_condattr_setclock" PRIVATE
|
||||||
|
LABEL "pthread_condattr_setclock() function"
|
||||||
|
AUTODETECT UNIX
|
||||||
|
CONDITION UNIX AND QT_FEATURE_thread AND TEST_pthread_condattr_setclock
|
||||||
|
)
|
||||||
qt_feature("pthread_timedjoin" PRIVATE
|
qt_feature("pthread_timedjoin" PRIVATE
|
||||||
LABEL "pthread_timedjoin() function"
|
LABEL "pthread_timedjoin() function"
|
||||||
AUTODETECT UNIX
|
AUTODETECT UNIX
|
||||||
|
@ -75,14 +75,12 @@ static inline constexpr clockid_t SteadyClockClockId =
|
|||||||
#elif defined(__GLIBCXX__) && !defined(_GLIBCXX_USE_CLOCK_MONOTONIC)
|
#elif defined(__GLIBCXX__) && !defined(_GLIBCXX_USE_CLOCK_MONOTONIC)
|
||||||
// libstdc++ falling back to system_clock
|
// libstdc++ falling back to system_clock
|
||||||
CLOCK_REALTIME
|
CLOCK_REALTIME
|
||||||
#elif defined(Q_OS_DARWIN)
|
#elif defined(_LIBCPP_VERSION) && defined(Q_OS_DARWIN)
|
||||||
// Darwin lacks pthread_condattr_setclock()
|
// on Apple systems, libc++ uses CLOCK_MONOTONIC_RAW since LLVM 11
|
||||||
CLOCK_REALTIME
|
// https://github.com/llvm/llvm-project/blob/llvmorg-11.0.0/libcxx/src/chrono.cpp#L117-L129
|
||||||
#elif defined(Q_OS_QNX)
|
CLOCK_MONOTONIC_RAW
|
||||||
// unknown why
|
|
||||||
CLOCK_REALTIME
|
|
||||||
#elif defined(__GLIBCXX__) || defined(_LIBCPP_VERSION)
|
#elif defined(__GLIBCXX__) || defined(_LIBCPP_VERSION)
|
||||||
// both libstdc++ and libc++ do use CLOCK_MONOTONIC
|
// both libstdc++ and libc++ otherwise use CLOCK_MONOTONIC
|
||||||
CLOCK_MONOTONIC
|
CLOCK_MONOTONIC
|
||||||
#else
|
#else
|
||||||
# warning "Unknown C++ Standard Library implementation - code may be sub-optimal"
|
# warning "Unknown C++ Standard Library implementation - code may be sub-optimal"
|
||||||
@ -90,6 +88,21 @@ static inline constexpr clockid_t SteadyClockClockId =
|
|||||||
#endif
|
#endif
|
||||||
;
|
;
|
||||||
|
|
||||||
|
static inline constexpr clockid_t QWaitConditionClockId =
|
||||||
|
#if !QT_CONFIG(thread)
|
||||||
|
// bootstrap mode, there are no wait conditions
|
||||||
|
CLOCK_REALTIME
|
||||||
|
#elif !QT_CONFIG(pthread_condattr_setclock)
|
||||||
|
// OSes that lack pthread_condattr_setclock() (e.g., Darwin)
|
||||||
|
CLOCK_REALTIME
|
||||||
|
#elif defined(Q_OS_QNX)
|
||||||
|
// unknown why use of the monotonic clock causes failures
|
||||||
|
CLOCK_REALTIME
|
||||||
|
#else
|
||||||
|
SteadyClockClockId;
|
||||||
|
#endif
|
||||||
|
;
|
||||||
|
|
||||||
static constexpr auto OneSecAsNsecs = std::chrono::nanoseconds(std::chrono::seconds{ 1 }).count();
|
static constexpr auto OneSecAsNsecs = std::chrono::nanoseconds(std::chrono::seconds{ 1 }).count();
|
||||||
|
|
||||||
inline timespec durationToTimespec(std::chrono::nanoseconds timeout) noexcept
|
inline timespec durationToTimespec(std::chrono::nanoseconds timeout) noexcept
|
||||||
@ -205,13 +218,14 @@ inline timespec qAbsTimespec(timespec ts)
|
|||||||
return normalizedTimespec(ts);
|
return normalizedTimespec(ts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <clockid_t ClockId = SteadyClockClockId>
|
||||||
inline timespec deadlineToAbstime(QDeadlineTimer deadline)
|
inline timespec deadlineToAbstime(QDeadlineTimer deadline)
|
||||||
{
|
{
|
||||||
using namespace std::chrono;
|
using namespace std::chrono;
|
||||||
using Clock =
|
using Clock =
|
||||||
std::conditional_t<SteadyClockClockId == CLOCK_REALTIME, system_clock, steady_clock>;
|
std::conditional_t<ClockId == CLOCK_REALTIME, system_clock, steady_clock>;
|
||||||
auto timePoint = deadline.deadline<Clock>();
|
auto timePoint = deadline.deadline<Clock>();
|
||||||
if (timePoint < Clock::time_point{})
|
if (timePoint < typename Clock::time_point{})
|
||||||
return {};
|
return {};
|
||||||
return durationToTimespec(timePoint.time_since_epoch());
|
return durationToTimespec(timePoint.time_since_epoch());
|
||||||
}
|
}
|
||||||
|
@ -95,7 +95,7 @@ enum { ThreadPriorityResetFlag = 0x80000000 };
|
|||||||
//
|
//
|
||||||
// To support this scenario, we start the thread in detached state.
|
// To support this scenario, we start the thread in detached state.
|
||||||
static constexpr bool UsingPThreadTimedJoin = QT_CONFIG(pthread_clockjoin)
|
static constexpr bool UsingPThreadTimedJoin = QT_CONFIG(pthread_clockjoin)
|
||||||
|| (QT_CONFIG(pthread_timedjoin) && SteadyClockClockId == CLOCK_REALTIME);
|
|| (QT_CONFIG(pthread_timedjoin) && QWaitConditionClockId == CLOCK_REALTIME);
|
||||||
#if !QT_CONFIG(pthread_clockjoin)
|
#if !QT_CONFIG(pthread_clockjoin)
|
||||||
int pthread_clockjoin_np(...) { return ENOSYS; } // pretend
|
int pthread_clockjoin_np(...) { return ENOSYS; } // pretend
|
||||||
#endif
|
#endif
|
||||||
|
@ -30,14 +30,14 @@ static void qt_initialize_pthread_cond(pthread_cond_t *cond, const char *where)
|
|||||||
{
|
{
|
||||||
pthread_condattr_t *attrp = nullptr;
|
pthread_condattr_t *attrp = nullptr;
|
||||||
|
|
||||||
#if defined(CLOCK_MONOTONIC) && !defined(Q_OS_DARWIN)
|
#if QT_CONFIG(pthread_condattr_setclock)
|
||||||
pthread_condattr_t condattr;
|
pthread_condattr_t condattr;
|
||||||
attrp = &condattr;
|
attrp = &condattr;
|
||||||
|
|
||||||
pthread_condattr_init(&condattr);
|
pthread_condattr_init(&condattr);
|
||||||
auto destroy = qScopeGuard([&] { pthread_condattr_destroy(&condattr); });
|
auto destroy = qScopeGuard([&] { pthread_condattr_destroy(&condattr); });
|
||||||
if (SteadyClockClockId != CLOCK_REALTIME)
|
if (QWaitConditionClockId != CLOCK_REALTIME)
|
||||||
pthread_condattr_setclock(&condattr, SteadyClockClockId);
|
pthread_condattr_setclock(&condattr, QWaitConditionClockId);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
qt_report_pthread_error(pthread_cond_init(cond, attrp), where, "cv init");
|
qt_report_pthread_error(pthread_cond_init(cond, attrp), where, "cv init");
|
||||||
@ -53,7 +53,7 @@ public:
|
|||||||
|
|
||||||
int wait_relative(QDeadlineTimer deadline)
|
int wait_relative(QDeadlineTimer deadline)
|
||||||
{
|
{
|
||||||
timespec ti = deadlineToAbstime(deadline);
|
timespec ti = deadlineToAbstime<QWaitConditionClockId>(deadline);
|
||||||
return pthread_cond_timedwait(&cond, &mutex, &ti);
|
return pthread_cond_timedwait(&cond, &mutex, &ti);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user