开始设计
This commit is contained in:
@@ -0,0 +1,179 @@
|
||||
#ifndef INCLUDED_C_STOPWATCH_H
|
||||
#define INCLUDED_C_STOPWATCH_H
|
||||
|
||||
#ifndef INCLUDED_C_BASE_H
|
||||
#include <c_Base.h>
|
||||
#endif /*INCLUDED_C_BASE_H*/
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------------------------ */
|
||||
/* */
|
||||
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
#include <windows.h>
|
||||
typedef LARGE_INTEGER c_TimePoint_t;
|
||||
#else
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
typedef struct timespec c_TimePoint_t;
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
c_TimePoint_t start_time;
|
||||
double elapsed_milliseconds;
|
||||
c_bool_t is_running;
|
||||
} c_Stopwatch_t;
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------------------------ */
|
||||
/* */
|
||||
|
||||
/**
|
||||
* Internal private helper: Captures the system's hardware clock monotonic timestamp.
|
||||
*/
|
||||
C_STATIC_FORCE_INLINE
|
||||
void c_Stopwatch_GetTimePoint(c_TimePoint_t* tp) {
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
QueryPerformanceCounter(tp);
|
||||
#else
|
||||
// Using CLOCK_MONOTONIC to guarantee safety against system time changes/NTP adjustments
|
||||
clock_gettime(CLOCK_MONOTONIC, tp);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal private helper: Computes the difference in seconds between two points.
|
||||
*/
|
||||
C_STATIC_FORCE_INLINE
|
||||
double c_Stopwatch_ComputeDiffInS(const c_TimePoint_t* start, const c_TimePoint_t* end) {
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
LARGE_INTEGER freq;
|
||||
QueryPerformanceFrequency(&freq);
|
||||
return (double)(end->QuadPart - start->HighPart) / (double)freq.QuadPart;
|
||||
#else
|
||||
double start_sec = (double)start->tv_sec + (double)start->tv_nsec / 1e9;
|
||||
double end_sec = (double)end->tv_sec + (double)end->tv_nsec / 1e9;
|
||||
return end_sec - start_sec;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the delta time in milliseconds between two distinct time points.
|
||||
* Time Complexity: O(1) | Auxiliary Space: O(1)
|
||||
* @param start Pointer to the starting time point timestamp.
|
||||
* @param end Pointer to the ending time point timestamp.
|
||||
* @return The double precision scalar difference value in milliseconds,
|
||||
* or -1.0 if any parameter pointer is NULL.
|
||||
*/
|
||||
C_STATIC_FORCE_INLINE
|
||||
double c_Stopwatch_ComputeDiffInMS(const c_TimePoint_t* start, const c_TimePoint_t* end) {
|
||||
if (start == NULL || end == NULL) return -1.0;
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
LARGE_INTEGER freq;
|
||||
QueryPerformanceFrequency(&freq);
|
||||
// Convert to seconds first, then scale up to milliseconds
|
||||
double seconds = (double)(end->QuadPart - start->QuadPart) / (double)freq.QuadPart;
|
||||
return seconds * 1000.0;
|
||||
#else
|
||||
double start_ms = ((double)start->tv_sec * 1000.0) + ((double)start->tv_nsec / 1e6);
|
||||
double end_ms = ((double)end->tv_sec * 1000.0) + ((double)end->tv_nsec / 1e6);
|
||||
return end_ms - start_ms;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the Stopwatch. Registers parameters to default states cleanly.
|
||||
*/
|
||||
C_STATIC_FORCE_INLINE
|
||||
c_err_t c_Stopwatch_Init(c_Stopwatch_t* sw) {
|
||||
if (sw == NULL) return C_ERR_PARAM;
|
||||
|
||||
sw->elapsed_milliseconds = 0.0;
|
||||
sw->is_running = C_FALSE;
|
||||
memset(&sw->start_time, 0, sizeof(c_TimePoint_t));
|
||||
|
||||
return C_ERR_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start or resume tracking time.
|
||||
*/
|
||||
C_STATIC_FORCE_INLINE
|
||||
c_err_t c_Stopwatch_Start(c_Stopwatch_t* sw) {
|
||||
if (sw == NULL) return C_ERR_PARAM;
|
||||
if (sw->is_running) return C_ERR_OK; // Safe skip if already processing
|
||||
|
||||
c_Stopwatch_GetTimePoint(&sw->start_time);
|
||||
sw->is_running = C_TRUE;
|
||||
|
||||
return C_ERR_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop tracking time and cache the elapsed segment into the accumulator.
|
||||
*/
|
||||
C_STATIC_FORCE_INLINE
|
||||
c_err_t c_Stopwatch_Stop(c_Stopwatch_t* sw) {
|
||||
if (sw == NULL) return C_ERR_PARAM;
|
||||
if (!sw->is_running) return C_ERR_OK;
|
||||
|
||||
c_TimePoint_t end_time;
|
||||
c_Stopwatch_GetTimePoint(&end_time);
|
||||
|
||||
// Add the delta directly to the millisecond buffer field
|
||||
sw->elapsed_milliseconds += c_Stopwatch_ComputeDiffInMS(&sw->start_time, &end_time);
|
||||
sw->is_running = C_FALSE;
|
||||
|
||||
return C_ERR_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Soft Reset: Blasts elapsed counts down to zero while preserving the active running state.
|
||||
*/
|
||||
C_STATIC_FORCE_INLINE
|
||||
c_err_t c_Stopwatch_Clear(c_Stopwatch_t* sw) {
|
||||
if (sw == NULL) return C_ERR_PARAM;
|
||||
|
||||
sw->elapsed_milliseconds = 0.0;
|
||||
if (sw->is_running) {
|
||||
c_Stopwatch_GetTimePoint(&sw->start_time); // Re-anchor start time mark to prevent jumps
|
||||
}
|
||||
|
||||
return C_ERR_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Utility helper: Extract elapsed timing down to millisecond intervals.
|
||||
*/
|
||||
C_STATIC_FORCE_INLINE
|
||||
double c_Stopwatch_GetElapsedMilliseconds(const c_Stopwatch_t* sw) {
|
||||
if (sw == NULL) return 0.0;
|
||||
if (!sw->is_running) return sw->elapsed_milliseconds; // Pure O(1) cache read
|
||||
|
||||
c_TimePoint_t active_tick;
|
||||
c_Stopwatch_GetTimePoint(&active_tick);
|
||||
|
||||
// Dynamically add current active delta segment to the base accumulator
|
||||
return sw->elapsed_milliseconds + c_Stopwatch_ComputeDiffInMS(&sw->start_time, &active_tick);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Extract total measured elapsed time in seconds up to this exact moment.
|
||||
* Works perfectly whether the stopwatch is running or stopped (Lap peeking feature).
|
||||
* Time Complexity: O(1) | Auxiliary Space: O(1) in-place
|
||||
* @param sw Pointer to the constant stopwatch instance context.
|
||||
* @return The double precision scalar elapsed time value in seconds,
|
||||
* or 0.0 if the stopwatch instance handle is NULL.
|
||||
*/
|
||||
C_STATIC_FORCE_INLINE
|
||||
double c_Stopwatch_GetElapsedSeconds(const c_Stopwatch_t* sw) {
|
||||
if (sw == NULL) return 0.0;
|
||||
|
||||
// Leverage the existing GetElapsedMilliseconds API and scale it down to second precision.
|
||||
// This maintains perfect abstraction layer unity without duplicating clock read conditions.
|
||||
return c_Stopwatch_GetElapsedMilliseconds(sw) / 1000.0;
|
||||
}
|
||||
|
||||
#endif /*INCLUDED_C_STOPWATCH_H*/
|
||||
Reference in New Issue
Block a user