Stroika Library 3.0d16
 
Loading...
Searching...
No Matches
Sleep.inl
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2025. All rights reserved
3 */
4#if qStroika_Foundation_Common_Platform_Windows
5#include <windows.h>
6#elif qStroika_Foundation_Common_Platform_POSIX
7#include <time.h>
8#include <unistd.h>
9#endif
10#include <cerrno>
11
13
15
16 //redeclare to avoid having to include Thread code
17 namespace Thread {
19 }
20
21 /*
22 ********************************************************************************
23 ******************************** Execution::Sleep ******************************
24 ********************************************************************************
25 */
26 inline void Sleep (Time::Duration seconds2Wait, Time::DurationSeconds* remainingInSleep)
27 {
28 Require (seconds2Wait >= 0.0s);
29 RequireNotNull (remainingInSleep); // else call the one-argument overload
31 // @todo lose if the #if stuff and use just if constexpr (but not working on msvc - complains about nanosleep undefined)
32#if qStroika_Foundation_Common_Platform_POSIX
33 if constexpr (qStroika_Foundation_Common_Platform_POSIX) {
34 constexpr long kNanoSecondsPerSecond = 1000L * 1000L * 1000L;
35 timespec ts;
36 ts.tv_sec = seconds2Wait.As<time_t> ();
37 ts.tv_nsec = static_cast<long> (kNanoSecondsPerSecond * (seconds2Wait.As<double> () - ts.tv_sec));
38 Assert (0 <= ts.tv_sec);
39 Assert (0 <= ts.tv_nsec and ts.tv_nsec < kNanoSecondsPerSecond);
40 timespec nextTS;
41 int nanoSleepResult = ::nanosleep (&ts, &nextTS);
42
43 // See https://github.com/microsoft/WSL/issues/4898 - workaround nanosleep EINVAL on Windows/WSL 1 with newer libc (like with ubuntu 20.04)
44#if _POSIX_C_SOURCE >= 200809L
45 if (nanoSleepResult < 0 and errno == EINVAL) {
46 if ((errno = ::clock_nanosleep (CLOCK_MONOTONIC, 0, &ts, &nextTS)) == 0) {
47 nanoSleepResult = 0;
48 }
49 }
50#endif
51 if (nanoSleepResult == 0) {
52 *remainingInSleep = 0s;
53 }
54 else {
55 Assert (errno == EINTR); // only in this case do they guarantee nextTS set properly
56 // https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/time.h.html doesn't clearly document allowed range for timespec
57 // https://pubs.opengroup.org/onlinepubs/9699919799/functions/nanosleep.html doesn't clearly document allowed range for output timespec (can results go negative)
58 WeakAssert (0 <= nextTS.tv_nsec and nextTS.tv_nsec < kNanoSecondsPerSecond); // docs not clear but I think this should always be true (on EINTR)... -- LGP 2020-05-29
59 WeakAssert (nextTS.tv_sec >= 0); // ""
60 *remainingInSleep =
61 Time::DurationSeconds{nextTS.tv_sec + static_cast<Time::DurationSeconds::rep> (nextTS.tv_nsec) / kNanoSecondsPerSecond};
62 }
63 }
64#elif qStroika_Foundation_Common_Platform_Windows
65 if constexpr (qStroika_Foundation_Common_Platform_Windows) {
66 Time::TimePointSeconds tc = Time::GetTickCount ();
67 if (::SleepEx (static_cast<int> (seconds2Wait.count () * 1000), true) == 0) {
68 *remainingInSleep = 0s;
69 }
70 else {
71 Time::DurationSeconds remaining = (tc + seconds2Wait) - Time::GetTickCount ();
72 if (remaining < 0s) {
73 remaining = 0s;
74 }
75 *remainingInSleep = remaining;
76 }
77 }
78#else
80#endif
81 Ensure (*remainingInSleep <= seconds2Wait);
82 Ensure (*remainingInSleep >= 0s);
84 }
85
86 /*
87 ********************************************************************************
88 *************************** Execution::SleepUntil ******************************
89 ********************************************************************************
90 */
91 inline void SleepUntil (Time::TimePointSeconds untilTickCount)
92 {
93 Time::DurationSeconds waitMoreSeconds = untilTickCount - Time::GetTickCount ();
94 if (waitMoreSeconds <= 0s) {
96 }
97 else {
98 Sleep (waitMoreSeconds);
99 }
100 }
101
102}
#define AssertNotImplemented()
Definition Assertions.h:401
#define RequireNotNull(p)
Definition Assertions.h:347
#define WeakAssert(c)
A WeakAssert() is for things that aren't guaranteed to be true, but are overwhelmingly likely to be t...
Definition Assertions.h:438
time_point< RealtimeClock, DurationSeconds > TimePointSeconds
TimePointSeconds is a simpler approach to chrono::time_point, which doesn't require using templates e...
Definition Realtime.h:82
chrono::duration< double > DurationSeconds
chrono::duration<double> - a time span (length of time) measured in seconds, but high precision.
Definition Realtime.h:57
void Sleep(Time::Duration seconds2Wait)
Definition Sleep.cpp:18
void SleepUntil(Time::TimePointSeconds untilTickCount)
Definition Sleep.inl:91