Skip to content

Commit cb0bb1a

Browse files
committed
Add the QNX clock CLOCK_SOFTTIME
Also made the result of the clock testing clearer so that one can see the result for each clock test when compiling the header file. Signed-off-by: Ted Lyngmo <ted@lyncon.se>
1 parent 834af83 commit cb0bb1a

File tree

4 files changed

+38
-24
lines changed

4 files changed

+38
-24
lines changed

README.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ make
1515
static constexpr clockid_t clock_id;
1616

1717
// If this clock can use TIMER_ABSTIME in clock_nanosleep:
18-
static constexpr bool can_sleep_until_abstime;
18+
static constexpr bool can_clock_nanosleep;
1919
```
20-
While the "steadyness" of each clock is hardcoded in the recipe file, if the clock can sleep until an absolute time is determined while generating the header file. Drop-in replacement functions for `std::this_thread::sleep_for` and `std::this_thread::sleep_until` are available in `lyn::this_thread` that sleeps until an absolute time if the clock supports it. Note that `lyn::this_thread::sleep_for` has a `Clock` template parameter that can be used to specify what clock to use for sleeping.
20+
While the "steadyness" of each clock is hardcoded in the recipe file, if the clock can use `clock_nanosleep` is determined while generating the header file. Drop-in replacement functions for `std::this_thread::sleep_for` and `std::this_thread::sleep_until` are available in `lyn::this_thread` that sleeps until an absolute time if the clock supports `clock_nanosleep`. Note that `lyn::this_thread::sleep_for` has a `Clock` template parameter that can be used to specify what clock to use for sleeping.
2121
```c++
2222
template<class Clock = std::chrono::steady_clock, class Rep, class Period>
2323
void sleep_for(const std::chrono::duration<Rep, Period>& dur);
@@ -26,7 +26,7 @@ template<class Clock, class Duration>
2626
void sleep_until(const std::chrono::time_point<Clock, Duration>& tp);
2727
```
2828
29-
**Note:** The header file will only function correctly when used on the platform where it was generated. Cross-compilation is not supported. Create the file on each individual platform where you want it.
29+
**Note:** The header file will only function correctly when used on the platform for which it was generated. Create the file for each individual platform where you want it. If your code is supposed to work on multiple platforms, select clocks that exists on all of them. Do not copy a generated `clocxx.hpp` file generated for one platform to another platform. Time as you know it may come to an end.
3030
3131
### Example clocks that may be generated:
3232
```c++
@@ -53,7 +53,7 @@ struct monotonic_raw_clock :
5353
All clocks share the same base implementation:
5454
```c++
5555
namespace detail {
56-
template<class Clock, bool IsSteady, bool CanClockUseAbsTime, clockid_t CLOCK_ID>
56+
template<class Clock, bool IsSteady, bool CanClockNanoSleep, clockid_t CLOCK_ID>
5757
struct clock_base {
5858
using duration = std::chrono::nanoseconds;
5959
using rep = duration::rep;
@@ -62,7 +62,7 @@ namespace detail {
6262
static constexpr bool is_steady = IsSteady;
6363

6464
static constexpr clockid_t clock_id = CLOCK_ID;
65-
static constexpr bool can_sleep_until_abstime = CanClockUseAbsTime;
65+
static constexpr bool can_clock_nanosleep = CanClockNanoSleep;
6666

6767
static time_point now() noexcept {
6868
using namespace std;

base.hpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,16 +39,16 @@ For more information, please refer to <https://unlicense.org>
3939
namespace lyn {
4040
namespace chrono {
4141
template<class Clock>
42-
struct can_sleep_until_abstime {
42+
struct can_clock_nanosleep {
4343
static std::false_type test(...);
4444

4545
template<class C>
46-
static auto test(C) -> std::bool_constant<C::can_sleep_until_abstime>;
46+
static auto test(C) -> std::bool_constant<C::can_clock_nanosleep>;
4747

4848
static constexpr bool value = decltype(test(std::declval<Clock>()))::value;
4949
};
5050
template<class Clock>
51-
static constexpr bool can_sleep_until_abstime_v = can_sleep_until_abstime<Clock>::value;
51+
static constexpr bool can_clock_nanosleep_v = can_clock_nanosleep<Clock>::value;
5252
}
5353

5454
namespace this_thread {
@@ -58,7 +58,7 @@ namespace this_thread {
5858
template<class Clock = std::chrono::steady_clock, class Rep, class Period>
5959
void sleep_for(const std::chrono::duration<Rep, Period>& dur) {
6060
if(dur <= dur.zero()) return;
61-
if constexpr(chrono::can_sleep_until_abstime_v<Clock>) {
61+
if constexpr(chrono::can_clock_nanosleep_v<Clock>) {
6262
sleep_until(Clock::now() + dur);
6363
} else {
6464
auto s = std::chrono::duration_cast<std::chrono::seconds>(dur);
@@ -71,7 +71,7 @@ namespace this_thread {
7171

7272
template<class Clock, class Duration>
7373
void sleep_until(const std::chrono::time_point<Clock, Duration>& tp) {
74-
if constexpr(chrono::can_sleep_until_abstime_v<Clock>) {
74+
if constexpr(chrono::can_clock_nanosleep_v<Clock>) {
7575
auto dur = tp.time_since_epoch();
7676
auto s = std::chrono::duration_cast<std::chrono::seconds>(dur);
7777
auto ns = std::chrono::duration_cast<std::chrono::nanoseconds>(dur - s);
@@ -87,7 +87,7 @@ namespace this_thread {
8787

8888
namespace chrono {
8989
namespace detail {
90-
template<class Clock, bool IsSteady, bool CanClockUseAbsTime, clockid_t CLOCK_ID>
90+
template<class Clock, bool IsSteady, bool CanClockNanoSleep, clockid_t CLOCK_ID>
9191
struct clock_base {
9292
using duration = std::chrono::nanoseconds;
9393
using rep = duration::rep;
@@ -96,7 +96,7 @@ namespace chrono {
9696
static constexpr bool is_steady = IsSteady;
9797

9898
static constexpr clockid_t clock_id = CLOCK_ID;
99-
static constexpr bool can_sleep_until_abstime = CanClockUseAbsTime;
99+
static constexpr bool can_clock_nanosleep = CanClockNanoSleep;
100100

101101
static time_point now() noexcept {
102102
using namespace std;

mkclocxx.cpp

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@
1212
#include <filesystem>
1313
#include <fstream>
1414
#include <iostream>
15+
#include <iterator>
1516
#include <optional>
1617
#include <sstream>
1718
#include <string>
19+
#include <vector>
1820

1921
// #macro, steady(true/false), description
2022
struct clockdef {
@@ -40,13 +42,13 @@ enum result { UNSUPP, CLOCK_GETTIME, CLOCK_NANOSLEEP };
4042
std::ostream& operator<<(std::ostream& os, result r) {
4143
switch(r) {
4244
case UNSUPP:
43-
os << "UNSUPP";
45+
os << "UNSUPPORTED";
4446
break;
4547
case CLOCK_GETTIME:
46-
os << "CLOCK_GETTIME";
48+
os << "Exists - Can clock_nanosleep(): NO";
4749
break;
4850
case CLOCK_NANOSLEEP:
49-
os << "CLOCK_NANOSLEEP";
51+
os << "Exists - Can clock_nanosleep(): YES";
5052
break;
5153
}
5254
return os;
@@ -71,8 +73,8 @@ std::optional<pres> command(std::string command) {
7173
return pres{::pclose(pip), std::move(buf)};
7274
}
7375

74-
result test(const clockdef& cd) {
75-
std::cout << "Clock under test: " << cd.macro << '\n';
76+
result test(const clockdef& cd, int width) {
77+
std::cout << "Clock under test: " << std::setw(width) << cd.macro;
7678
auto res = command("make clock_test_driver CLOCK_TO_TEST=" + cd.macro);
7779
if(not res || (*res).exitstatus) return UNSUPP;
7880

@@ -92,25 +94,35 @@ std::string mkname(std::string macro) {
9294
}
9395

9496
int createit() {
97+
auto& seen_file = "seen_clockid_t";
9598
std::cout << std::boolalpha;
96-
std::ifstream cids("seen_clockid_t");
99+
std::ifstream cids(seen_file);
97100
if(not cids) {
98-
std::cerr << std::strerror(errno) << '\n';
101+
std::cerr << seen_file << ": " << std::strerror(errno) << '\n';
99102
return 1;
100103
}
104+
std::vector<clockdef> cds(std::istream_iterator<clockdef>(cids), std::istream_iterator<clockdef>{});
105+
if(cds.empty()) {
106+
std::cerr << seen_file << ": No valid clock definitions read\n";
107+
return 1;
108+
}
109+
int maxwidth = std::max_element(cds.begin(), cds.end(), [](const clockdef& lhs, const clockdef& rhs) {
110+
return lhs.macro.size() < rhs.macro.size();
111+
})->macro.size();
101112

102113
std::filesystem::copy("base.hpp", "clocxx.hpp", std::filesystem::copy_options::overwrite_existing);
103114

104-
std::ofstream ofs("clocxx.hpp", std::ios::app);
115+
auto& target = "clocxx.hpp";
116+
std::ofstream ofs(target, std::ios::app);
105117
if(not ofs) {
106-
std::cerr << std::strerror(errno) << '\n';
118+
std::cerr << target << ": " << std::strerror(errno) << '\n';
107119
return 1;
108120
}
109121
ofs << std::boolalpha;
110122

111-
clockdef cd;
112-
while(cids >> cd) {
113-
auto rv = test(cd);
123+
for(auto& cd : cds) {
124+
auto rv = test(cd, maxwidth);
125+
std::cout << ": " << rv << '\n';
114126
if(rv != UNSUPP) {
115127
auto clname = mkname(cd.macro);
116128
ofs << "/*\n * " << clname << " - " << cd.description << "\n */\n";

seen_clockid_t

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,5 @@ CLOCK_BOOTTIME_ALARM, true, Like CLOCK_BOOTTIME. See timer_create(2) for further
2121
CLOCK_PROCESS_CPUTIME_ID, true, This is a clock that measures CPU time consumed by this process (i.e., CPU time consumed by all threads in the process). On Linux, this clock is not settable.
2222

2323
CLOCK_THREAD_CPUTIME_ID, true, This is a clock that measures CPU time consumed by this thread. On Linux, this clock is not settable.
24+
25+
CLOCK_SOFTTIME, false, This clock (a QNX Neutrino extension) is active only when the processor isn't in a power-saving mode. For example, an application using a CLOCK_SOFTTIME timer to sleep wouldn't wake up the processor when the application was due to wake up. This will allow the processor to enter a power-saving mode.

0 commit comments

Comments
 (0)