DUDS
Distributed Update of Data from Something
PosixClock.hpp
Go to the documentation of this file.
1 /*
2  * This file is part of the DUDS project. It is subject to the BSD-style
3  * license terms in the LICENSE file found in the top-level directory of this
4  * distribution and at https://github.com/jjackowski/duds/blob/master/LICENSE.
5  * No part of DUDS, including this file, may be copied, modified, propagated,
6  * or distributed except according to the terms contained in the LICENSE file.
7  *
8  * Copyright (C) 2017 Jeff Jackowski
9  */
10 #ifndef POSIXCLOCK_HPP
11 #define POSIXCLOCK_HPP
12 
14 #include <time.h>
15 
16 #ifndef CLOCK_TAI
17 
23 #define CLOCK_TAI 11
24 #endif
25 
26 namespace duds { namespace hardware { namespace devices { namespace clocks {
27 
33 
37 typedef boost::error_info<struct Info_posixclockid, clockid_t> PosixClockId;
38 
42 constexpr boost::uuids::uuid PosixClockDeviceId = {
43  0x41, 0xba, 0xe3, 0x09,
44  0xc2, 0xe9,
45  0x4c, 0x02,
46  0xb4, 0xd5,
47  0x5b, 0x24, 0xc3, 0x99, 0xc7, 0xeb
48 };
49 
70 template<class SVT, class SQT, class TVT, class TQT>
71 class GenericPosixClock : public GenericClock<SVT, SQT, TVT, TQT> {
72 public:
74 private:
89  int offset;
90 
91  // are seconds ok? maybe TVT would work better. might work better for using
92  // CLOCK_MONOTONIC, although it cannot be corrected over time.
93  // for leap seconds, store a duds::time::interstellar::SecondTime with when
94  // leap seconds should be inspected again. when now becomes that time value,
95  // query for leap seconds, update the offset and the time to do this again.
96  // maybe don't use duds::time::interstellar::SecondTime; use something
97  // in the form of the data from the clock for a faster comparison.
98 
102  clockid_t clk;
109  static duds::data::int128_t sum(const timespec &ts) {
110  return duds::data::int128_t(
111  duds::data::int128_t(ts.tv_sec) * std::nano::den +
112  duds::data::int128_t(ts.tv_nsec)
113  );
114  }
121  timespec ts;
122  int res = clock_gettime(clk, &ts);
123  if (res) {
125  }
126  ts.tv_sec += offset;
127  return sum(ts);
128  }
136  template <class Sample>
137  void setSample(Sample &dest, const duds::data::int128_t &time) const {
138  // two resolutions are stored; select one based on type
139  if (std::is_same<SQT, typename Sample::Quality>::value) {
140  dest.resolution = sampleResolution;
141  } else {
142  dest.resolution = timeResolution;
143  }
144  // not all quality values are reported
145  dest.accuracy = dest.estError = dest.precision =
146  duds::data::unspecified<typename Sample::Quality>();
147  // set the time
149  dest.value, time);
150  }
151  struct Token { };
154 public:
168  GenericPosixClock(clockid_t id, int os, Token) :
169  GenericClock<SVT, SQT, TVT, TQT>(PosixClockDeviceId), clk(id), offset(os) {
170  // query the clock for its resolution
171  timespec ts;
172  int res = clock_getres(clk, &ts);
173  if (res) {
175  }
176  // put the resolution into a single value
177  duds::data::int128_t rez = sum(ts);
178  // convert the resolution into the two quality types found
179  // in a Measurement
181  sampleResolution, rez);
183  timeResolution, rez);
184  }
197  static std::shared_ptr< GenericPosixClock <SVT, SQT, TVT, TQT> > make(
198  clockid_t id = CLOCK_REALTIME, int os = 0
199  ) {
200  return std::make_shared< GenericPosixClock <SVT, SQT, TVT, TQT> >(
201  id, os, Token()
202  );
203  }
204  virtual void sampleTime(typename Measurement::TimeSample &time) {
205  duds::data::int128_t sum = doSample();
206  setSample(time, sum);
207  }
208  virtual void sample() {
209  std::shared_ptr<Measurement> m =
210  std::make_shared<Measurement>();
211  duds::data::int128_t sum = doSample();
212  setSample(m->measured, sum);
213  // no timestamp
214  m->timestamp.clear();
215  // store the measurement
216  setMeasurement(std::move(m));
217  }
218  virtual void sample(const ClockSptr &clock) {
219  std::shared_ptr<Measurement> m =
220  std::make_shared<Measurement>();
221  duds::data::int128_t sum = doSample();
222  setSample(m->measured, sum);
223  // if the supplied clock driver is this clock driver . . .
224  if (this == clock.get()) {
225  // sample the clock just once
226  setSample(m->timestamp, sum);
227  } else if (clock) {
228  // sample the other clock
229  clock->sampleTime(m->timestamp);
230  } else {
231  // no timestamp
232  m->timestamp.clear();
233  }
234  // store the measurement
235  setMeasurement(std::move(m));
236  }
237  virtual bool unambiguous() const noexcept {
238  return false;
239  }
240 };
241 
245 typedef GenericPosixClock<
247  double,
249  float
251 
252 typedef std::shared_ptr<PosixClock> PosixClockSptr;
253 
254 } } } }
255 
256 
257 #endif // #ifndef POSIXCLOCK_HPP
boost::variant< std::string, duds::general::LanguageTaggedString, std::array< std::int32_t, 4 >, std::array< std::int64_t, 2 >, duds::data::int128_w, std::array< float, 4 >, std::array< double, 2 >, double, duds::data::Quantity, boost::recursive_wrapper< duds::data::QuantityNddArray >, duds::time::interstellar::Femtoseconds, duds::time::interstellar::Nanoseconds, duds::time::interstellar::FemtoTime, duds::time::interstellar::NanoTime, boost::uuids::uuid, boost::recursive_wrapper< duds::data::GenericValueTable >, std::shared_ptr< std::vector< char > >> GenericValue
A general value of a type can be serialized for transmission over a network and can be used with a re...
GenericPosixClock< duds::data::GenericValue, double, duds::time::interstellar::NanoTime, float > PosixClock
General use POSIX clock driver type.
Definition: PosixClock.hpp:250
An attempt was made to use a POSIX clock that is not supported by the system.
Definition: PosixClock.hpp:32
boost::multiprecision::int128_t int128_t
The type used for 128-bit integers.
Definition: Int128.hpp:66
boost::error_info< struct Info_posixclockid, clockid_t > PosixClockId
Indicates the POSIX clockid_t in an error involving a POSIX clock.
Definition: PosixClock.hpp:37
The base type for errors from clocks.
Definition: Clock.hpp:64
move_impl move(unsigned int c, unsigned int r)
Display stream manipulator that moves the display cursor to the given location.
A clock driver to use clocks through the POSIX interface.
Definition: PosixClock.hpp:71
virtual void sample(const ClockSptr &clock)
Samples the time from this clock and the given clock, then stores the measurement.
Definition: PosixClock.hpp:218
std::shared_ptr< PosixClock > PosixClockSptr
Definition: PosixClock.hpp:252
GenericPosixClock(clockid_t id, int os, Token)
Construct a clock device for the given POSIX clock.
Definition: PosixClock.hpp:168
Represents something with one or more sensors that are sampled through the same hardware.
Definition: Device.hpp:34
TQT timeResolution
The clock&#39;s resolution for use with time stamps.
Definition: PosixClock.hpp:85
GenericSample< GenericValue, double > Sample
A sample type that is good for general purpose use.
Definition: Sample.hpp:166
static duds::data::int128_t sum(const timespec &ts)
Sums the second and nanosecond fields given by the POSIX functions into a large integer.
Definition: PosixClock.hpp:109
int offset
An offset in seconds that is applied to the time provided by the clock.
Definition: PosixClock.hpp:89
std::shared_ptr< GenericClock< SVT, SQT, TVT, TQT > > ClockSptr
Definition: Clock.hpp:84
virtual bool unambiguous() const noexcept
Returns true if the clock properly reports the time during a leap second.
Definition: PosixClock.hpp:237
duds::data::GenericMeasurement< SVT, SQT, TVT, TQT > Measurement
Definition: PosixClock.hpp:73
void setSample(Sample &dest, const duds::data::int128_t &time) const
Sets the sample values based on the time sample.
Definition: PosixClock.hpp:137
The foundation to a clock driver.
Definition: Clock.hpp:78
SQT sampleResolution
The clock&#39;s resolution for use with samples.
Definition: PosixClock.hpp:80
virtual void sampleTime(typename Measurement::TimeSample &time)
Samples the time from the clock device without storing the result in the clock&#39;s sensor object...
Definition: PosixClock.hpp:204
Stores a sample of something along with a timestamp stored as a sample from a clock.
Definition: Measurement.hpp:24
duds::data::int128_t doSample() const
Samples the time and adds in an offset.
Definition: PosixClock.hpp:120
virtual void sample()
Samples the time from this clock stores it in the measured field of the Measurement object of the dev...
Definition: PosixClock.hpp:208
static std::shared_ptr< GenericPosixClock< SVT, SQT, TVT, TQT > > make(clockid_t id=CLOCK_REALTIME, int os=0)
Makes a new clock device for a POSIX clock.
Definition: PosixClock.hpp:197
constexpr boost::uuids::uuid PosixClockDeviceId
The UUID for the POSIX clock device.
Definition: PosixClock.hpp:42
#define DUDS_THROW_EXCEPTION(x)
Works like BOOST_THROW_EXCEPTION, but includes a stack trace if DUDS_ERRORS_VERBOSE is defined...
Definition: Errors.hpp:48
NanoClock::time_point NanoTime
A point in time in Interstellar Time stored in Nanoseconds.