开始设计

This commit is contained in:
2026-08-10 01:21:15 +08:00
commit e45398991f
228 changed files with 20827 additions and 0 deletions
+179
View File
@@ -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*/