VLink 2.0.0
A high-performance communication middleware
载入中...
搜索中...
未找到
elapsed_timer.h
浏览该文件的文档.
1/*
2 * Copyright (C) 2026 by Thun Lu. All rights reserved.
3 * Author: Thun Lu <thun.lu@zohomail.cn>
4 * Repo: https://github.com/thun-res/vlink
5 * _ __ __ _ __
6 * | | / / / / (_) ____ / /__
7 * | | / / / / / / / __ \ / //_/
8 * | |/ / / /___ / / / / / / / ,<
9 * |___/ /_____/ /_/ /_/ /_/ /_/|_|
10 *
11 * Licensed under the Apache License, Version 2.0 (the "License");
12 * you may not use this file except in compliance with the License.
13 * You may obtain a copy of the License at
14 *
15 * http://www.apache.org/licenses/LICENSE-2.0
16 *
17 * Unless required by applicable law or agreed to in writing, software
18 * distributed under the License is distributed on an "AS IS" BASIS,
19 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 * See the License for the specific language governing permissions and
21 * limitations under the License.
22 */
23
24/**
25 * @file elapsed_timer.h
26 * @brief High-resolution elapsed-time measurement with configurable clock source and precision.
27 *
28 * @details
29 * @c ElapsedTimer measures how much time (wall-clock or CPU-active time) has elapsed
30 * since @c start() was called. It is the lowest-level timing primitive in VLink and
31 * is used internally by @c DeadlineTimer, @c CpuProfiler, and the message-loop task
32 * latency tracking.
33 *
34 * Two independent axes of configuration are available:
35 *
36 * @par Clock source (Method)
37 * | Value | Clock source | Notes |
38 * | ------------------ | ----------------------------------- | ---------------------------------- |
39 * | kCpuTimestamp | CLOCK_MONOTONIC_RAW / steady_clock | Monotonic wall time, never jumps |
40 * | kCpuActiveTime | getrusage / GetProcessTimes | CPU user+kernel time consumed |
41 *
42 * @par Precision (Accuracy)
43 * | Value | Unit | Range (64-bit) |
44 * | ------- | ------------ | ----------------------- |
45 * | kMilli | milliseconds | ~292 million years |
46 * | kMicro | microseconds | ~292 thousand years |
47 * | kNano | nanoseconds | ~292 years |
48 *
49 * @note
50 * - The timer is @b not started on construction; call @c start() explicitly.
51 * - @c get() returns @c -1 when the timer has not been started or has been stopped.
52 * - The internal @c start_time_ is stored as a @c std::atomic<int64_t>, making
53 * concurrent reads from multiple threads safe, though concurrent @c start()/stop()
54 * calls from different threads lead to a data race on the "is started" semantic.
55 * - On Linux, @c get_sys_timestamp() uses @c CLOCK_REALTIME via @c clock_gettime for
56 * nanosecond resolution; on Windows it falls back to @c std::chrono::system_clock.
57 * - @c get_cpu_timestamp() uses @c CLOCK_MONOTONIC_RAW on Linux (immune to NTP
58 * adjustments) and @c std::chrono::steady_clock on other platforms.
59 *
60 * @par Example
61 * @code
62 * vlink::ElapsedTimer t(vlink::ElapsedTimer::kCpuTimestamp,
63 * vlink::ElapsedTimer::kMicro);
64 * t.start();
65 * do_work();
66 * int64_t us = t.get(); // microseconds elapsed; -1 if not started
67 * t.stop();
68 *
69 * // One-liner: restart returns elapsed and resets the timer atomically
70 * int64_t delta = t.restart();
71 * @endcode
72 */
73
74#pragma once
75
76#include <atomic>
77#include <cstdint>
78
79#include "./macros.h"
80
81namespace vlink {
82
83/**
84 * @class ElapsedTimer
85 * @brief Atomic, high-resolution elapsed-time timer.
86 *
87 * @details
88 * Measures elapsed time since @c start() using either a monotonic wall-clock
89 * (@c kCpuTimestamp) or the process CPU-active time (@c kCpuActiveTime).
90 * The class is @c final and not copyable (copy/move constructors are provided
91 * but only copy the snapshot value, not ownership semantics).
92 */
94 public:
95 /**
96 * @brief Selects the underlying clock source for time measurement.
97 */
98 enum Method : uint8_t {
99 kCpuTimestamp = 0, ///< Monotonic wall-clock (CLOCK_MONOTONIC_RAW on Linux)
100 kCpuActiveTime = 1 ///< Process CPU time (user + kernel, via getrusage)
101 };
102
103 /**
104 * @brief Selects the precision (resolution) of the timer values returned.
105 */
106 enum Accuracy : uint8_t {
107 kMilli = 0, ///< Millisecond precision
108 kMicro = 1, ///< Microsecond precision
109 kNano = 2 ///< Nanosecond precision
110 };
111
112 /**
113 * @brief Constructs an @c ElapsedTimer with default method (@c kCpuTimestamp)
114 * and default accuracy (@c kMilli).
115 *
116 * @details The timer is @b not started after construction.
117 */
118 ElapsedTimer() noexcept;
119
120 /**
121 * @brief Constructs an @c ElapsedTimer with the specified clock source.
122 *
123 * @param method The clock source to use (@c kCpuTimestamp or @c kCpuActiveTime).
124 */
125 explicit ElapsedTimer(Method method) noexcept;
126
127 /**
128 * @brief Constructs an @c ElapsedTimer with the specified precision.
129 *
130 * @param accuracy The precision of time values (@c kMilli, @c kMicro, or @c kNano).
131 */
132 explicit ElapsedTimer(Accuracy accuracy) noexcept;
133
134 /**
135 * @brief Constructs an @c ElapsedTimer with the specified clock source and precision.
136 *
137 * @param method The clock source to use.
138 * @param accuracy The precision of time values.
139 */
140 explicit ElapsedTimer(Method method, Accuracy accuracy) noexcept;
141
142 /**
143 * @brief Copy constructor. Copies the current start-time snapshot, method, and accuracy.
144 *
145 * @param target The source timer.
146 */
147 ElapsedTimer(const ElapsedTimer& target) noexcept;
148
149 /**
150 * @brief Move constructor. Behaves identically to the copy constructor.
151 *
152 * @param target The source timer.
153 */
154 ElapsedTimer(ElapsedTimer&& target) noexcept;
155
156 /**
157 * @brief Destructor.
158 */
159 ~ElapsedTimer() noexcept;
160
161 /**
162 * @brief Copy-assignment operator.
163 *
164 * @param target The source timer.
165 * @return A reference to @c *this.
166 */
167 ElapsedTimer& operator=(const ElapsedTimer& target) noexcept;
168
169 /**
170 * @brief Move-assignment operator.
171 *
172 * @param target The source timer (moved from).
173 * @return A reference to @c *this.
174 */
175 ElapsedTimer& operator=(ElapsedTimer&&) noexcept;
176
177 /**
178 * @brief Returns the current wall-clock (system) timestamp.
179 *
180 * @details
181 * On Linux uses @c CLOCK_REALTIME via @c clock_gettime for maximum precision
182 * when @p high_resolution is @c true; otherwise uses @c std::chrono::system_clock.
183 * On Windows always uses @c std::chrono::system_clock.
184 *
185 * @param accuracy Desired precision (default: @c kMilli).
186 * @param high_resolution Whether to use @c clock_gettime (Linux only, default: @c true).
187 * @return Current system timestamp in the requested unit.
188 */
189 [[nodiscard]] static uint64_t get_sys_timestamp(Accuracy accuracy = kMilli, bool high_resolution = true) noexcept;
190
191 /**
192 * @brief Returns the current monotonic CPU timestamp.
193 *
194 * @details
195 * On Linux uses @c CLOCK_MONOTONIC_RAW (unaffected by NTP) when
196 * @p high_resolution is @c true; otherwise uses @c std::chrono::steady_clock.
197 * On Windows always uses @c std::chrono::steady_clock.
198 *
199 * @param accuracy Desired precision (default: @c kMilli).
200 * @param high_resolution Whether to use @c clock_gettime (Linux only, default: @c true).
201 * @return Current monotonic timestamp in the requested unit.
202 */
203 [[nodiscard]] static uint64_t get_cpu_timestamp(Accuracy accuracy = kMilli, bool high_resolution = true) noexcept;
204
205 /**
206 * @brief Returns the accumulated CPU time (user + kernel) consumed by the current process.
207 *
208 * @details
209 * Uses @c getrusage(RUSAGE_SELF) on POSIX or @c GetProcessTimes on Windows.
210 * The returned value is the total CPU time used so far in the process lifetime,
211 * not a delta. Use @c ElapsedTimer with @c kCpuActiveTime to measure deltas.
212 *
213 * @param accuracy Desired precision (default: @c kMilli).
214 * @return Cumulative process CPU time in the requested unit.
215 */
216 [[nodiscard]] static uint64_t get_cpu_active_time(Accuracy accuracy = kMilli) noexcept;
217
218 /**
219 * @brief Returns the clock source configured for this timer.
220 *
221 * @return The @c Method value set at construction.
222 */
223 [[nodiscard]] Method get_method() const noexcept;
224
225 /**
226 * @brief Returns the precision configured for this timer.
227 *
228 * @return The @c Accuracy value set at construction.
229 */
230 [[nodiscard]] Accuracy get_accuracy() const noexcept;
231
232 /**
233 * @brief Starts the timer if it is not already active.
234 *
235 * @details
236 * Records the current time as the start reference using a CAS on the
237 * internal atomic. If the timer is already active this call is a no-op.
238 * Call @c stop() first to reset and then @c start() again.
239 */
240 void start() noexcept;
241
242 /**
243 * @brief Stops the timer, setting the internal start time to @c -1.
244 *
245 * @details
246 * After @c stop(), @c is_active() returns @c false and @c get() returns @c -1.
247 */
248 void stop() noexcept;
249
250 /**
251 * @brief Atomically resets the start time to now and returns the elapsed time
252 * since the previous @c start() / @c restart() call.
253 *
254 * @details
255 * This is equivalent to @c get() followed by @c start(), but performed
256 * atomically using @c exchange. If the timer was not active, returns a
257 * negative value (the raw @c start_time_ value, which is -1 when stopped).
258 *
259 * @return
260 * - Elapsed time in the configured units since the last start/restart, or
261 * - A negative value if the timer was not started before this call.
262 */
263 int64_t restart() noexcept;
264
265 /**
266 * @brief Returns @c true when the timer has been started and not yet stopped.
267 *
268 * @return @c true if active (start_time_ >= 0), @c false otherwise.
269 */
270 [[nodiscard]] bool is_active() const noexcept;
271
272 /**
273 * @brief Returns the elapsed time since @c start() was called.
274 *
275 * @details
276 * The value is computed as @c (current_time - start_time_) in the configured
277 * precision units. Returns @c -1 if the timer has not been started (or has
278 * been stopped).
279 *
280 * @return
281 * - Elapsed time in the configured units (>= 0) when active.
282 * - @c -1 when the timer is not active.
283 */
284 [[nodiscard]] int64_t get() const noexcept;
285
286 private:
287 alignas(64) std::atomic<int64_t> start_time_{-1};
288 Method method_{kCpuTimestamp};
289 Accuracy accuracy_{kMilli};
290};
291
292} // namespace vlink
Platform-independent macro definitions for the VLink library.
#define VLINK_EXPORT
定义 macros.h:85
STL namespace