DPsim
Loading...
Searching...
No Matches
Timer.h
1/* Copyright 2017-2021 Institute for Automation of Complex Power Systems,
2 * EONERC, RWTH Aachen University
3 *
4 * This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
7 *********************************************************************************/
8
9#pragma once
10
11#include <chrono>
12
13#include <dpsim-models/Logger.h>
14#include <dpsim/Config.h>
15
16namespace DPsim {
17
18class Timer {
19public:
21 uint64_t overruns;
22 };
23
24 using Ticks = std::chrono::nanoseconds;
25
26 using StartClock = std::chrono::system_clock;
27 using IntervalClock = std::chrono::steady_clock;
28
29 using StartTimePoint = std::chrono::time_point<StartClock, Ticks>;
30 using IntervalTimePoint = std::chrono::time_point<IntervalClock, Ticks>;
31
32protected:
33 enum State { running, stopped } mState;
34
35 StartTimePoint mStartAt;
36 IntervalTimePoint mNextTick;
37 Ticks mTickInterval;
38
39#ifdef HAVE_TIMERFD
40 int mTimerFd;
41#endif
42 long long mOverruns;
43 long long mTicks;
44 int mFlags;
45
47 CPS::Logger::Level mLogLevel;
49 CPS::Logger::Log mSLog;
50
51public:
52 enum Flags : int { fail_on_overrun = 1 };
53
54 Timer(int flags = 0, CPS::Logger::Level logLevel = CPS::Logger::Level::debug);
55
56 ~Timer();
57
58 void start(const StartTimePoint &startAt);
59
61 void start();
62
64 void stop();
65
67 void sleep();
68
69 // Getter
70 const long long &overruns() { return mOverruns; }
71
72 long long ticks() { return mTicks; }
73
74 Ticks interval() { return mTickInterval; }
75
76 // Setter
77 void setStartTime(const StartTimePoint &start) { mStartAt = start; }
78
79 void setInterval(const Ticks &intv) { mTickInterval = intv; }
80
81 void setInterval(double dt) {
82 mTickInterval = Timer::Ticks((uintmax_t)(dt * 1e9));
83 }
84};
85
86#ifdef HAVE_TIMERFD
87template <class Rep, class Period>
88struct timespec to_timespec(std::chrono::duration<Rep, Period> dur) {
89 auto nsDur = std::chrono::duration_cast<std::chrono::nanoseconds>(dur);
90
91 struct timespec ts;
92
93 ts.tv_sec = nsDur.count() / 1000000000;
94 ts.tv_nsec = nsDur.count() % 1000000000;
95
96 return ts;
97}
98#endif
99
100} // namespace DPsim
101
102#include <ctime>
103#include <iomanip>
104#include <iostream>
105
106template <typename Clock, typename Duration>
107std::ostream &
108operator<<(std::ostream &stream,
109 const std::chrono::time_point<Clock, Duration> &time_point) {
110 const auto sys_time_point =
111 std::chrono::time_point_cast<typename Clock::duration, Clock>(time_point);
112 const std::time_t time = Clock::to_time_t(sys_time_point);
113
114#if __GNUC__ > 4 || \
115 ((__GNUC__ == 4) && __GNUC_MINOR__ > 8 && __GNUC_REVISION__ > 1)
116 // Maybe the put_time will be implemented later?
117 struct tm tm;
118 localtime_r(&time, &tm);
119 return stream << std::put_time(&tm, "%c"); // Print standard date&time
120#elif defined(_MSC_VER)
121 char buffer[26];
122 ctime_s(buffer, 26, &time);
123 buffer[24] = '\0'; // Removes the newline that is added
124 return stream << buffer;
125#else
126 char buffer[26];
127 ctime_r(&time, buffer);
128 buffer[24] = '\0'; // Removes the newline that is added
129 return stream << buffer;
130#endif
131}
132
133template <typename Rep, typename Period>
134std::ostream &operator<<(std::ostream &stream,
135 const std::chrono::duration<Rep, Period> &dur) {
136
137 using namespace std::chrono;
138
139 auto d = dur;
140
141 if (dur == dur.zero())
142 stream << "0";
143 else {
144 auto h = duration_cast<hours>(d);
145 d -= h;
146 auto m = duration_cast<minutes>(d);
147 d -= m;
148 auto s = duration_cast<seconds>(d);
149 d -= s;
150 auto ms = duration_cast<milliseconds>(d);
151 d -= ms;
152 auto us = duration_cast<microseconds>(d);
153 d -= us;
154 auto ns = duration_cast<nanoseconds>(d);
155
156 long long vals[] = {h.count(), m.count(), s.count(),
157 ms.count(), us.count(), ns.count()};
158 const char *units[] = {"hrs", "mins", "secs", "msecs", "usecs", "nsecs"};
159
160 for (int i = 0; i < 6; i++) {
161 if (i)
162 stream << " ";
163
164 if (vals[i] == 0)
165 continue;
166
167 stream << vals[i] << " " << units[i];
168 }
169 }
170
171 return stream;
172}
void start()
Start real-time timer.
Definition Timer.cpp:92
void stop()
Stop real-time timer.
Definition Timer.cpp:125
CPS::Logger::Log mSLog
Logger.
Definition Timer.h:49
void sleep()
Suspend thread execution until next tick.
Definition Timer.cpp:54
CPS::Logger::Level mLogLevel
Timer log level.
Definition Timer.h:47