diff --git a/src/common/clock/system_clock.cpp b/src/common/clock/system_clock.cpp new file mode 100644 index 0000000..81cb9c9 --- /dev/null +++ b/src/common/clock/system_clock.cpp @@ -0,0 +1,122 @@ +#include "system_clock.h" + +#include + +#include +#include + +#if defined(__POSIX__) +#include +#endif +#if defined(__APPLE__) +#include +#endif +#if defined(_WIN32) +#include +#endif + +int64_t SystemClock::CurrentTimeNs() { + int64_t ticks = -1; // Default to error case + +#if defined(__APPLE__) + static mach_timebase_info_data_t timebase; + if (timebase.denom == 0 && mach_timebase_info(&timebase) != KERN_SUCCESS) { + return -1; // Error case for macOS timebase info retrieval + } + ticks = static_cast(mach_absolute_time() * timebase.numer) / + timebase.denom; + +#elif defined(__POSIX__) + struct timespec ts; + if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) { + return -1; // Error case for POSIX clock retrieval + } + ticks = static_cast(ts.tv_sec) * kNumNanosecsPerSec + + static_cast(ts.tv_nsec); + +#elif defined(_WIN32) + static volatile LONG last_timegettime = 0; + static volatile int64_t num_wrap_timegettime = 0; + volatile LONG* last_timegettime_ptr = &last_timegettime; + + DWORD now = timeGetTime(); + DWORD old = InterlockedExchange(last_timegettime_ptr, now); + + if (now < old) { + // Handle wraparound (when timeGetTime() wraps around after ~49.7 days) + if (old > 0xf0000000 && now < 0x0fffffff) { + num_wrap_timegettime++; + } + } + + // Convert milliseconds to nanoseconds and add wraparound offset + ticks = static_cast(now) + (num_wrap_timegettime << 32); + ticks *= 1000000; +#endif + + return ticks; +} + +int64_t SystemClock::CurrentTimeUs() { return CurrentTimeNs() / 1000LL; } + +int64_t SystemClock::CurrentTimeMs() { return CurrentTimeNs() / 1000000LL; } + +int64_t SystemClock::CurrentTime() { return CurrentTimeNs() / 1000000000LL; } + +int64_t SystemClock::CurrentNtpTime() { + int64_t current_time_s = CurrentTime(); + return current_time_s + kNtpEpochOffset; +} + +int64_t SystemClock::CurrentNtpTimeMs() { + return CurrentTimeMs() + kNtpEpochOffset * 1000LL; +} + +int64_t SystemClock::CurrentNtpTimeUs() { + return CurrentTimeUs() + kNtpEpochOffset * 1000000LL; +} + +int64_t SystemClock::CurrentNtpTimeNs() { + return CurrentTimeNs() + kNtpEpochOffset * 1000000000LL; +} + +int64_t SystemClock::CurrentUtcTimeNs() { +#if defined(__POSIX__) + struct timeval time; + gettimeofday(&time, nullptr); + return (static_cast(time.tv_sec) * 1000000000 + time.tv_usec * 1000); +#elif defined(_WIN32) + FILETIME file_time; + GetSystemTimeAsFileTime(&file_time); + int64_t file_time_100ns = + ((int64_t)file_time.dwHighDateTime << 32) | file_time.dwLowDateTime; + constexpr int64_t kUnixEpochFileTimeOffsetIn100ns = 116444736000000000LL; + return (file_time_100ns - kUnixEpochFileTimeOffsetIn100ns) * 100; +#elif defined(__APPLE__) + struct timespec ts; + if (clock_gettime(CLOCK_REALTIME, &ts) != 0) { + return -1; // Error case for macOS clock retrieval + } + return static_cast(ts.tv_sec) * 1000000000LL + ts.tv_nsec; +#endif + return 0; +} + +int64_t SystemClock::CurrentUtcTimeUs() { return CurrentUtcTimeNs() / 1000LL; } + +int64_t SystemClock::CurrentUtcTimeMs() { + return CurrentUtcTimeNs() / 1000000LL; +} + +int64_t SystemClock::CurrentUtcTime() { + return CurrentUtcTimeNs() / 1000000000LL; +} + +static SystemClock* GetSystemClock() { + static SystemClock* const clock = new SystemClock(); + return clock; +} + +static std::shared_ptr GetSystemClockShared() { + return std::make_shared(); +} \ No newline at end of file diff --git a/src/common/clock/system_clock.h b/src/common/clock/system_clock.h new file mode 100644 index 0000000..818786c --- /dev/null +++ b/src/common/clock/system_clock.h @@ -0,0 +1,39 @@ +/* + * @Author: DI JUNKUN + * @Date: 2025-02-19 + * Copyright (c) 2025 by DI JUNKUN, All Rights Reserved. + */ + +#ifndef _SYSTEM_CLOCK_H_ +#define _SYSTEM_CLOCK_H_ + +#include +#include + +static const int64_t kNtpEpochOffset = 2208988800LL; + +class SystemClock { + public: + SystemClock() = default; + ~SystemClock() = default; + + int64_t CurrentTime(); + int64_t CurrentTimeMs(); + int64_t CurrentTimeUs(); + int64_t CurrentTimeNs(); + + int64_t CurrentNtpTime(); + int64_t CurrentNtpTimeMs(); + int64_t CurrentNtpTimeUs(); + int64_t CurrentNtpTimeNs(); + + int64_t CurrentUtcTime(); + int64_t CurrentUtcTimeMs(); + int64_t CurrentUtcTimeUs(); + int64_t CurrentUtcTimeNs(); +}; + +static SystemClock* GetSystemClock(); +static std::shared_ptr GetSystemClockShared(); + +#endif \ No newline at end of file diff --git a/xmake.lua b/xmake.lua index bd226bf..2ef96f2 100644 --- a/xmake.lua +++ b/xmake.lua @@ -43,6 +43,7 @@ target("common") set_kind("object") add_deps("log") add_files("src/common/common.cpp", + "src/common/clock/system_clock.cpp", "src/common/rtc_base/*.cc", "src/common/rtc_base/network/*.cc", "src/common/rtc_base/numerics/*.cc",