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
66 std::string to_string() const
67 {
68 auto tau = elapsed();
69 if (m_name.empty()) return std::format("{}s", tau);
70 return std::format("{}: {}s", m_name, tau);
71 }
72
73private:
74 using time_point = typename Clock::time_point;
75
76 std::string m_name; // Name of the stopwatch.
77 time_point m_zero; // The stopwatch measures time (in seconds) from this time point.
78 double m_split; // The total seconds to when the stopwatch was most recently clicked.
79 double m_prior; // The prior split.
80};
81
83template<class Rep, class Period>
84inline double
85to_seconds(const std::chrono::duration<Rep, Period>& d)
86{
87 return std::chrono::duration<double>(d).count();
88}
89
92
95
98
102template<typename Clock>
103inline std::ostream&
104operator<<(std::ostream& os, const stopwatch<Clock>& rhs)
105{
106 return os << rhs.to_string();
107}
108
109} // namespace utilities
110
111// --------------------------------------------------------------------------------------------------------------------
112// Specialises `std::formatter` to handle our stopwatch class ...
113// -------------------------------------------------------------------------------------------------------------------
114
116template<typename Clock>
117struct std::formatter<utilities::stopwatch<Clock>> {
118
119 constexpr auto parse(const std::format_parse_context& ctx)
120 {
121 // Throw an error for anything that is not default formatted for now ...
122 auto it = ctx.begin();
123 assert(it == ctx.end() || *it == '}');
124 return it;
125 }
126
127 template<class FormatContext>
128 auto format(const utilities::stopwatch<Clock>& rhs, FormatContext& ctx) const
129 {
130 // Punt the formatting to the stopwatch's `to_string()` method.
131 return std::format_to(ctx.out(), "{}", rhs.to_string());
132 }
133};
See the Stopwatch page for all the details.
Definition stopwatch.h:19
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:66
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:97
stopwatch< std::chrono::steady_clock > steady_stopwatch
A stopwatch that is guaranteed to be monotonic.
Definition stopwatch.h:94
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:85
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:91
std::ostream & operator<<(std::ostream &os, const stopwatch< Clock > &rhs)
The usual output stream operator.
Definition stopwatch.h:104