} // eo realtime_clock_gettime(long int&,long int&)
+namespace I2n {
+
+namespace clock {
+
+ namespace {
+
+ static inline clockid_t
+ clockid_of_flags (const enum type::id id,
+ const enum type::variant var)
+ {
+ clockid_t cid = CLOCK_MONOTONIC_COARSE;
+
+ switch (id) {
+
+ default:
+ case type::mono: {
+ switch (var) {
+ default: {
+ break;
+ }
+ case type::raw: {
+ cid = CLOCK_MONOTONIC_RAW;
+ break;
+ }
+ case type::exact: {
+ cid = CLOCK_MONOTONIC;
+ break;
+ }
+ }
+ break;
+ }
+
+ case type::real: {
+ if (var == type::exact) {
+ cid = CLOCK_REALTIME;
+ } else {
+ cid = CLOCK_REALTIME_COARSE;
+ }
+ break;
+ }
+
+ case type::boot: {
+ if (var & type::exact) {
+ cid = CLOCK_BOOTTIME;
+ }
+ break;
+ }
+
+ case type::cpu: {
+ if (var == type::thread) {
+ cid = CLOCK_THREAD_CPUTIME_ID;
+ } else {
+ cid = CLOCK_PROCESS_CPUTIME_ID;
+ }
+ break;
+ }
+ } /* [switch id] */
+
+ return cid;
+ }
+
+ static const struct timespec zero_time = { 0, 0 };
+
+# define NANO (1000L * 1000 * 1000)
+
+ } /* [namespace] */
+
+ Time::Time (const enum type::id id, const enum type::variant var)
+ : value (zero_time)
+ , id (id)
+ , variant (var)
+ , err (0)
+ { }
+
+ int64_t
+ Time::as_nanosec (void)
+ { return int64_t (this->value.tv_sec) * NANO + this->value.tv_nsec; }
+
+ long
+ Time::as_nanosec_L (void) /* likely to overflow */
+ { return static_cast<long>(this->as_nanosec ()); }
+
+ void
+ Time::unset (void)
+ { this->value = zero_time; }
+
+ bool
+ Time::set (void)
+ {
+ struct timespec now;
+
+ errno = 0;
+ if (clock_gettime (clockid_of_flags (this->id, this->variant), &now)
+ == -1)
+ {
+ this->err = errno;
+ this->unset ();
+
+ return false;
+ }
+ this->err = 0;
+ this->value = now;
+
+ return true;
+ }
+
+ boost::optional<Time>
+ now (const enum type::id id, const enum type::variant var)
+ {
+ Time ret (id);
+
+ if (!ret.set ()) {
+ return boost::none;
+ }
+
+ return ret;
+ }
+
+} /* [namespace clock] */
+
+} /* [namespace I2n] */
+
#ifndef __TIMEFUNC_HXX
#define __TIMEFUNC_HXX
+#include <errno.h>
#include <string>
#include <list>
+#include <boost/optional.hpp>
+
#include <week.hpp>
double prec_time(void);
bool realtime_clock_gettime(long int& seconds, long int& nano_seconds);
+namespace I2n {
+
+namespace clock {
+
+ namespace type {
+ /*
+ * represent the clock id options from clock_gettime(2) as
+ * a pair of enums. by default, CLOCK_MONOTONIC_COARSE is used
+ * everywhere since that’s what we want in most cases.
+ */
+ enum id {
+ mono, /* CLOCK_MONOTONIC_COARSE */
+ real, /* CLOCK_REALIME_COARSE */
+ boot, /* CLOCK_BOOTTIME */
+ cpu, /* CLOCK_CPUTIME_* */
+ };
+
+ /*
+ * for clocks that support it: non-coarse or raw variants; if a variant
+ * does not apply to a given clock, it is ignored
+ */
+ enum variant {
+ dflt, /* all */
+ exact, /* mono, real: not (*_COARSE) */
+ raw, /* mono: _RAW */
+ process, /* cpu: *_PROCESS_* */
+ thread, /* cpu: *_THREAD_* */
+ };
+
+ } /* [namespace type] */
+
+
+ class Time {
+
+ private:
+ struct timespec value;
+
+ public:
+ const enum type::id id;
+ const enum type::variant variant;
+ int err;
+
+ /* ctors *************************************************************/
+ public:
+
+ Time (const enum type::id id = type::mono,
+ const enum type::variant var = type::dflt);
+
+ /* value access ******************************************************/
+ public:
+
+ inline const struct timespec &get_time (void)
+ { return this->value; }
+
+ inline const time_t &get_sec (void)
+ { return this->value.tv_sec; };
+
+ inline const long &get_nsec (void)
+ { return this->value.tv_nsec; }
+
+ int64_t as_nanosec (void);
+
+ long as_nanosec_L (void);
+
+ /* setting time ******************************************************/
+ public:
+
+ inline void
+ set (const struct timespec &ts)
+ { this->value = ts; };
+
+ inline void
+ set (const time_t sec, const long nsec)
+ {
+ this->value.tv_sec = sec;
+ this->value.tv_nsec = nsec;
+ };
+
+ bool set (void);
+
+ void unset (void);
+
+ }; /* [class Time] */
+
+ boost::optional<Time>
+ now (const enum type::id id = type::mono,
+ const enum type::variant var = type::dflt);
+
+} /* [namespace clock] */
+
+} /* [namespace I2n] */
#endif
BOOST_CHECK_EQUAL(1341093600, date_to_seconds("2012-07-01"));
}
+BOOST_AUTO_TEST_SUITE(Clock)
+
+ BOOST_AUTO_TEST_CASE(ctor_simple)
+ {
+ I2n::clock::Time t;
+
+ BOOST_CHECK_EQUAL(t.get_sec (), 0);
+ BOOST_CHECK_EQUAL(t.get_nsec (), 0);
+ }
+
+ BOOST_AUTO_TEST_CASE(ctor_type)
+ {
+ I2n::clock::Time t (I2n::clock::type::real);
+
+ BOOST_CHECK_EQUAL(t.get_sec (), 0);
+ BOOST_CHECK_EQUAL(t.get_nsec (), 0);
+ }
+
+ BOOST_AUTO_TEST_CASE(ctor_variant)
+ {
+ I2n::clock::Time t (I2n::clock::type::cpu,
+ I2n::clock::type::thread);
+
+ BOOST_CHECK_EQUAL(t.get_sec (), 0);
+ BOOST_CHECK_EQUAL(t.get_nsec (), 0);
+ }
+
+ BOOST_AUTO_TEST_CASE(initializer_now)
+ {
+ boost::optional<I2n::clock::Time> t = I2n::clock::now ();
+
+ BOOST_CHECK(t);
+ BOOST_CHECK_GT(t->get_sec (), 0);
+ BOOST_CHECK_EQUAL(t->err, 0);
+ }
+
+BOOST_AUTO_TEST_SUITE_END()
BOOST_AUTO_TEST_SUITE_END()