Helios Engine 0.1.0
A modular ECS based data-oriented C++23 game engine
 
Loading...
Searching...
No Matches
timer.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <chrono>
4#include <concepts>
5#include <cstdint>
6#include <ratio>
7#include <type_traits>
8
10#include <helios/core_pch.hpp>
11
12namespace helios {
13
14namespace details {
15
16/**
17 * @brief Concept for clock types compatible with std::chrono clocks.
18 * @details Requires nested types rep, period, duration and time_point, and a static now() function.
19 */
20template <typename T>
21concept ClockTrait = requires {
22 typename T::rep;
23 typename T::period;
24 typename T::duration;
25 typename T::time_point;
26 { T::now() } -> std::same_as<typename T::time_point>;
27};
28
29/**
30 * @brief Concept for duration types based on std::chrono::duration.
31 */
32template <typename T>
33concept DurationTrait = std::same_as<T, std::chrono::duration<typename T::rep, typename T::period>>;
34
35/**
36 * @brief Helper alias to normalize a duration to its canonical std::chrono::duration form.
37 */
38template <typename Rep, typename Period>
39using NormalizedDuration = std::chrono::duration<Rep, Period>;
40
41/**
42 * @brief Helper alias to normalize a clock's duration to a specific rep/period.
43 */
44template <typename Clock, typename Rep, typename Period>
45using NormalizedClockDuration = std::chrono::duration<Rep, Period>;
46
47} // namespace details
48
49/**
50 * @brief High–resolution timer with configurable clock and rich elapsed API.
51 * @details The timer measures elapsed time from the last reset point.
52 *
53 * - The clock type is configurable via the template parameter @p Clock.
54 * - Users can query elapsed time as:
55 * - A raw `Clock::duration`.
56 * - Any `std::chrono::duration` (via `ElapsedDuration`).
57 * - Arbitrary arithmetic type with specified time unit (via `Elapsed`).
58 * - Convenience helpers (seconds, milliseconds, microseconds, nanoseconds).
59 *
60 * @note The default clock is `std::chrono::steady_clock`.
61 * @tparam Clock Clock type used to measure time. Must satisfy `details::ClockTrait`.
62 */
63template <details::ClockTrait Clock = std::chrono::steady_clock>
64class Timer {
65public:
66 using ClockType = Clock;
67 using TimePoint = typename Clock::time_point;
68 using Duration = typename Clock::duration;
69
70 /**
71 * @brief Constructs timer and immediately resets start timestamp.
72 */
73 constexpr Timer() noexcept(noexcept(Clock::now())) = default;
74 constexpr Timer(const Timer&) noexcept(std::is_nothrow_copy_constructible_v<Clock>) = default;
75 constexpr Timer(Timer&&) noexcept(std::is_nothrow_move_constructible_v<Clock>) = default;
76 constexpr ~Timer() noexcept(std::is_nothrow_destructible_v<Clock>) = default;
77
78 constexpr Timer& operator=(const Timer&) noexcept(std::is_nothrow_copy_assignable_v<Clock>) = default;
79 constexpr Timer& operator=(Timer&&) noexcept(std::is_nothrow_move_assignable_v<Clock>) = default;
80
81 /**
82 * @brief Reset the timer start point to current time.
83 */
84 constexpr void Reset() noexcept(noexcept(Clock::now())) { start_time_ = Clock::now(); }
85
86 /**
87 * @brief Get elapsed time as a `std::chrono::duration`.
88 * @details This is the primary API for time measurement and should be preferred when working with `std::chrono`.
89 * @tparam Units Duration type to convert to. Must satisfy `details::DurationTrait`. Defaults to `Clock::duration`.
90 * @return Elapsed time since last reset as `Units`.
91 */
92 template <details::DurationTrait Units = Duration>
93 [[nodiscard]] constexpr Units ElapsedDuration() const;
94
95 /**
96 * @brief Get elapsed time converted to an arithmetic value with specified units.
97 * @details This method allows querying elapsed time in arbitrary precision and units, for example:
98 * - `Elapsed<double, std::chrono::seconds>()`
99 * - `Elapsed<std::uint64_t, std::chrono::microseconds>()`
100 * @tparam Type Arithmetic type used for the returned value.
101 * @tparam Units Duration type representing the desired time unit.
102 * @return Elapsed time as `Type`, where the underlying duration is `Units`.
103 */
104 template <utils::ArithmeticTrait Type = typename Duration::rep, details::DurationTrait Units = Duration>
105 [[nodiscard]] constexpr Type Elapsed() const;
106
107 /**
108 * @brief Elapsed time in seconds as double.
109 * @return Elapsed time since last reset in seconds.
110 */
111 [[nodiscard]] constexpr double ElapsedSec() const { return Elapsed<double, std::chrono::duration<double>>(); }
112
113 /**
114 * @brief Elapsed time in milliseconds as double.
115 * @return Elapsed time since last reset in milliseconds.
116 */
117 [[nodiscard]] constexpr double ElapsedMilliSec() const {
118 return Elapsed<double, std::chrono::duration<double, std::milli>>();
119 }
120
121 /**
122 * @brief Elapsed time in microseconds as 64-bit integer.
123 * @return Elapsed time since last reset in microseconds.
124 */
125 [[nodiscard]] constexpr int64_t ElapsedMicroSec() const { return Elapsed<int64_t, std::chrono::microseconds>(); }
126
127 /**
128 * @brief Elapsed time in nanoseconds as 64-bit integer.
129 * @return Elapsed time since last reset in nanoseconds.
130 */
131 [[nodiscard]] constexpr int64_t ElapsedNanoSec() const { return Elapsed<int64_t, std::chrono::nanoseconds>(); }
132
133 /**
134 * @brief Get the raw start timestamp of the timer.
135 * @return Starting time point.
136 */
137 [[nodiscard]] constexpr TimePoint Start() const noexcept { return start_time_; }
138
139private:
140 TimePoint start_time_{Clock::now()};
141};
142
143template <details::ClockTrait Clock>
144template <details::DurationTrait Units>
145constexpr Units Timer<Clock>::ElapsedDuration() const {
146 const auto now = Clock::now();
147 const auto diff = now - start_time_;
148 return std::chrono::duration_cast<Units>(diff);
149}
150
151template <details::ClockTrait Clock>
152template <utils::ArithmeticTrait Type, details::DurationTrait Units>
153constexpr Type Timer<Clock>::Elapsed() const {
154 const auto duration = ElapsedDuration<Units>();
155 return static_cast<Type>(duration.count());
156}
157
158} // namespace helios
High–resolution timer with configurable clock and rich elapsed API.
Definition timer.hpp:64
constexpr TimePoint Start() const noexcept
Get the raw start timestamp of the timer.
Definition timer.hpp:137
constexpr double ElapsedMilliSec() const
Elapsed time in milliseconds as double.
Definition timer.hpp:117
constexpr int64_t ElapsedMicroSec() const
Elapsed time in microseconds as 64-bit integer.
Definition timer.hpp:125
constexpr double ElapsedSec() const
Elapsed time in seconds as double.
Definition timer.hpp:111
constexpr Units ElapsedDuration() const
Get elapsed time as a std::chrono::duration.
Definition timer.hpp:145
Clock ClockType
Definition timer.hpp:66
constexpr int64_t ElapsedNanoSec() const
Elapsed time in nanoseconds as 64-bit integer.
Definition timer.hpp:131
constexpr Type Elapsed() const
Get elapsed time converted to an arithmetic value with specified units.
Definition timer.hpp:153
constexpr Timer() noexcept(noexcept(Clock::now()))=default
Constructs timer and immediately resets start timestamp.
typename Clock::duration Duration
Definition timer.hpp:68
constexpr void Reset() noexcept(noexcept(Clock::now()))
Reset the timer start point to current time.
Definition timer.hpp:84
typename Clock::time_point TimePoint
Definition timer.hpp:67
Concept for clock types compatible with std::chrono clocks.
Definition timer.hpp:21
Concept for duration types based on std::chrono::duration.
Definition timer.hpp:33
std::chrono::duration< Rep, Period > NormalizedDuration
Helper alias to normalize a duration to its canonical std::chrono::duration form.
Definition timer.hpp:39
std::chrono::duration< Rep, Period > NormalizedClockDuration
Helper alias to normalize a clock's duration to a specific rep/period.
Definition timer.hpp:45
STL namespace.