implement a basic time/clock datastructure
[libi2ncommon] / src / timefunc.cpp
index e8b1917..cab9469 100644 (file)
@@ -771,3 +771,125 @@ bool realtime_clock_gettime(long int& seconds, long int& nano_seconds)
 } // 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] */
+