Mir
posix_timestamp.h
Go to the documentation of this file.
1 /*
2  * Copyright © 2016 Canonical Ltd.
3  *
4  * This program is free software: you can redistribute it and/or modify it
5  * under the terms of the GNU Lesser General Public License version 2 or 3,
6  * as published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU Lesser General Public License for more details.
12  *
13  * You should have received a copy of the GNU Lesser General Public License
14  * along with this program. If not, see <http://www.gnu.org/licenses/>.
15  *
16  * Authored by: Daniel van Vugt <daniel.van.vugt@canonical.com>
17  */
18 
19 #ifndef MIR_TIME_POSIX_TIMESTAMP_H_
20 #define MIR_TIME_POSIX_TIMESTAMP_H_
21 
22 #include <chrono>
23 #include <ctime>
24 #include <stdexcept>
25 
26 namespace mir { namespace time {
27 
28 /*
29  * We need absolute precision here so sadly can't use high-level C++ clocks...
30  * - Graphics frame timing needs support for at least the kernel clocks
31  * CLOCK_REALTIME and CLOCK_MONOTONIC, to be selected at runtime, whereas
32  * std::chrono does not support CLOCK_REALTIME or easily switching clocks.
33  * - mir::time::Timestamp is relative to the (wrong) epoch of steady_clock,
34  * so converting to/from mir::time::Timestamp would be dangerously
35  * inaccurate at best.
36  */
37 
39 {
40  clockid_t clock_id;
41  std::chrono::nanoseconds nanoseconds;
42 
44  : clock_id{CLOCK_MONOTONIC}, nanoseconds{0} {}
45  PosixTimestamp(clockid_t clk, std::chrono::nanoseconds ns)
46  : clock_id{clk}, nanoseconds{ns} {}
47  PosixTimestamp(clockid_t clk, struct timespec const& ts)
48  : clock_id{clk}, nanoseconds{ts.tv_sec*1000000000LL + ts.tv_nsec} {}
49 
50  static PosixTimestamp now(clockid_t clock_id)
51  {
52  struct timespec ts;
53  clock_gettime(clock_id, &ts);
54  return PosixTimestamp(clock_id, ts);
55  }
56 };
57 
58 inline void assert_same_clock(PosixTimestamp const& a, PosixTimestamp const& b)
59 {
60  if (a.clock_id != b.clock_id)
61  throw std::logic_error("Can't compare different time domains");
62 }
63 
64 inline bool operator==(PosixTimestamp const& a, PosixTimestamp const& b)
65 {
66  return a.clock_id == b.clock_id && a.nanoseconds == b.nanoseconds;
67 }
68 
70  std::chrono::nanoseconds b)
71 {
72  return PosixTimestamp(a.clock_id, a.nanoseconds - b);
73 }
74 
75 inline std::chrono::nanoseconds operator-(PosixTimestamp const& a,
76  PosixTimestamp const& b)
77 {
78  assert_same_clock(a, b);
79  return a.nanoseconds - b.nanoseconds;
80 }
81 
83  std::chrono::nanoseconds b)
84 {
85  return PosixTimestamp(a.clock_id, a.nanoseconds + b);
86 }
87 
88 inline std::chrono::nanoseconds operator%(PosixTimestamp const& a,
89  std::chrono::nanoseconds b)
90 {
91  return std::chrono::nanoseconds(a.nanoseconds.count() % b.count());
92 }
93 
94 inline bool operator>(PosixTimestamp const& a, PosixTimestamp const& b)
95 {
96  assert_same_clock(a, b);
97  return a.nanoseconds > b.nanoseconds;
98 }
99 
100 inline bool operator<(PosixTimestamp const& a, PosixTimestamp const& b)
101 {
102  assert_same_clock(a, b);
103  return a.nanoseconds < b.nanoseconds;
104 }
105 
106 inline bool operator>=(PosixTimestamp const& a, PosixTimestamp const& b)
107 {
108  assert_same_clock(a, b);
109  return a.nanoseconds >= b.nanoseconds;
110 }
111 
112 inline bool operator<=(PosixTimestamp const& a, PosixTimestamp const& b)
113 {
114  assert_same_clock(a, b);
115  return a.nanoseconds <= b.nanoseconds;
116 }
117 
118 inline void sleep_until(PosixTimestamp const& t)
119 {
120  long long ns = t.nanoseconds.count();
121  struct timespec ts;
122  ts.tv_sec = ns / 1000000000LL;
123  ts.tv_nsec = ns % 1000000000LL;
124  while (EINTR == clock_nanosleep(t.clock_id, TIMER_ABSTIME, &ts, NULL)) {}
125 }
126 
127 }} // namespace mir::time
128 
129 #endif // MIR_TIME_POSIX_TIMESTAMP_H_
AutoUnblockThread is a helper thread class that can gracefully shutdown at destruction time...
Definition: blob.h:26
static PosixTimestamp now(clockid_t clock_id)
Definition: posix_timestamp.h:50
PosixTimestamp(clockid_t clk, std::chrono::nanoseconds ns)
Definition: posix_timestamp.h:45
void assert_same_clock(PosixTimestamp const &a, PosixTimestamp const &b)
Definition: posix_timestamp.h:58
PosixTimestamp(clockid_t clk, struct timespec const &ts)
Definition: posix_timestamp.h:47
PosixTimestamp()
Definition: posix_timestamp.h:43
clockid_t clock_id
Definition: posix_timestamp.h:40
std::chrono::nanoseconds nanoseconds
Definition: posix_timestamp.h:41
bool operator<(PosixTimestamp const &a, PosixTimestamp const &b)
Definition: posix_timestamp.h:100
void sleep_until(PosixTimestamp const &t)
Definition: posix_timestamp.h:118
PosixTimestamp operator+(PosixTimestamp const &a, std::chrono::nanoseconds b)
Definition: posix_timestamp.h:82
bool operator>(PosixTimestamp const &a, PosixTimestamp const &b)
Definition: posix_timestamp.h:94
bool operator<=(PosixTimestamp const &a, PosixTimestamp const &b)
Definition: posix_timestamp.h:112
std::chrono::nanoseconds operator%(PosixTimestamp const &a, std::chrono::nanoseconds b)
Definition: posix_timestamp.h:88
PosixTimestamp operator-(PosixTimestamp const &a, std::chrono::nanoseconds b)
Definition: posix_timestamp.h:69
bool operator>=(PosixTimestamp const &a, PosixTimestamp const &b)
Definition: posix_timestamp.h:106
Definition: posix_timestamp.h:38
bool operator==(PosixTimestamp const &a, PosixTimestamp const &b)
Definition: posix_timestamp.h:64

Copyright © 2012-2018 Canonical Ltd.
Generated on Sat Mar 31 14:22:42 UTC 2018