C++ Utilities
Loading...
Searching...
No Matches
stopwatch.h
Go to the documentation of this file.
1#pragma once
2// SPDX-FileCopyrightText: 2025 Nessan Fitzmaurice <nzznfitz+gh@icloud.com>
3// SPDX-License-Identifier: MIT
4
8
9#include <atomic>
10#include <cassert>
11#include <chrono>
12#include <iostream>
13#include <string>
14#include <format>
15
16namespace utilities {
18template<typename Clock = std::chrono::high_resolution_clock>
19class stopwatch {
20public:
22 using clock_type = Clock;
23
25 explicit stopwatch(const std::string& str = "") : m_name(str) { reset(); }
26
28 std::string name() const { return m_name; }
29
31 std::string& name() { return m_name; }
32
34 void reset()
35 {
36 m_zero = clock_type::now();
37 m_split = 0;
38 m_prior = 0;
39 }
40
42 double elapsed() const
43 {
44 std::atomic_thread_fence(std::memory_order_relaxed);
45 auto t = clock_type::now();
46 std::atomic_thread_fence(std::memory_order_relaxed);
47 return std::chrono::duration<double>(t - m_zero).count();
48 }
49
51 double click()
52 {
53 auto tau = elapsed();
54 m_prior = m_split;
55 m_split = tau;
56 return m_split;
57 }
58
60 double split() const { return m_split; }
61
63 double lap() const { return m_split - m_prior; }
64
79 constexpr static std::string format_seconds(double seconds)
80 {
81 if (seconds < 1.0) { return std::format("{:.2f}ms", seconds * 1000.0); }
82 return std::format("{:.2f}s", seconds);
83 }
84
86 std::string to_string() const
87 {
88 auto tau = format_seconds(elapsed());
89 if (m_name.empty()) return tau;
90 return std::format("{}: {}", m_name, tau);
91 }
92
93private:
94 using time_point = typename Clock::time_point;
95
96 std::string m_name; // Name of the stopwatch.
97 time_point m_zero; // The stopwatch measures time (in seconds) from this time point.
98 double m_split; // The total seconds to when the stopwatch was most recently clicked.
99 double m_prior; // The prior split.
100};
101
103template<class Rep, class Period>
104inline double
105to_seconds(const std::chrono::duration<Rep, Period>& d)
106{
107 return std::chrono::duration<double>(d).count();
108}
109
112
115
118
122template<typename Clock>
123inline std::ostream&
124operator<<(std::ostream& os, const stopwatch<Clock>& rhs)
125{
126 return os << rhs.to_string();
127}
128
129} // namespace utilities
130
131// --------------------------------------------------------------------------------------------------------------------
132// Specialises `std::formatter` to handle our stopwatch class ...
133// -------------------------------------------------------------------------------------------------------------------
134
136template<typename Clock>
137struct std::formatter<utilities::stopwatch<Clock>> {
138
139 constexpr auto parse(const std::format_parse_context& ctx)
140 {
141 // Throw an error for anything that is not default formatted for now ...
142 auto it = ctx.begin();
143 assert(it == ctx.end() || *it == '}');
144 return it;
145 }
146
147 template<class FormatContext>
148 auto format(const utilities::stopwatch<Clock>& rhs, FormatContext& ctx) const
149 {
150 // Punt the formatting to the stopwatch's `to_string()` method.
151 return std::format_to(ctx.out(), "{}", rhs.to_string());
152 }
153};
See the Stopwatch page for all the details.
Definition stopwatch.h:19
static constexpr std::string format_seconds(double seconds)
Class method that returns a "pretty" string for a time in seconds.
Definition stopwatch.h:79
double split() const
Returns the split as the time in seconds that elapsed from the zero point to the last click.
Definition stopwatch.h:60
void reset()
Set/reset the stopwatch's 'zero' point & clear any measured splits.
Definition stopwatch.h:34
stopwatch(const std::string &str="")
A stopwatch can have a name to distinguish it from others you may have running.
Definition stopwatch.h:25
double click()
Clicks the stopwatch to create a new 'split' and returns the elapsed time in seconds.
Definition stopwatch.h:51
std::string to_string() const
Returns a string representation of the stopwatch's elapsed time in seconds.
Definition stopwatch.h:86
Clock clock_type
The underlying clock type.
Definition stopwatch.h:22
std::string name() const
Provides read-only access to the stopwatch's name.
Definition stopwatch.h:28
double lap() const
Returns the last 'lap' time in seconds (i.e. the time between prior 2 splits).
Definition stopwatch.h:63
double elapsed() const
Get the time that has passed from the zero point to now. Units are seconds.
Definition stopwatch.h:42
std::string & name()
Provides read-write access to the stopwatch's name.
Definition stopwatch.h:31
The namespace for the utilities library.
Definition formatter.h:14
stopwatch< std::chrono::system_clock > system_stopwatch
A stopwatch that is uses the system clock.
Definition stopwatch.h:117
stopwatch< std::chrono::steady_clock > steady_stopwatch
A stopwatch that is guaranteed to be monotonic.
Definition stopwatch.h:114
double to_seconds(const std::chrono::duration< Rep, Period > &d)
A convenience function that converts a std::chrono::duration to a double number of seconds.
Definition stopwatch.h:105
stopwatch< std::chrono::high_resolution_clock > precise_stopwatch
Theoretically the most precise stopwatch – it might get put off by system reboots etc.
Definition stopwatch.h:111
std::ostream & operator<<(std::ostream &os, const stopwatch< Clock > &rhs)
The usual output stream operator.
Definition stopwatch.h:124