// ------------------------------------------------------------------------------------------------ #include "Library/Time.hpp" #include "Library/Numeric.hpp" #include "Base/Shared.hpp" // ------------------------------------------------------------------------------------------------ #ifdef SQMOD_OS_WINDOWS #include #else #include #endif // SQMOD_OS_WINDOWS // ------------------------------------------------------------------------------------------------ namespace SqMod { // ------------------------------------------------------------------------------------------------ #ifdef SQMOD_OS_WINDOWS /* ------------------------------------------------------------------------------------------------ * Used by GetCurrentSysTime to obtain the system frequency on initial call. */ LARGE_INTEGER GetFrequency() { LARGE_INTEGER frequency; QueryPerformanceFrequency(&frequency); return frequency; } // ------------------------------------------------------------------------------------------------ Int64 GetCurrentSysTime() { // Force the following code to run on first core // (see http://msdn.microsoft.com/en-us/library/windows/desktop/ms644904(v=vs.85).aspx) HANDLE current_thread = GetCurrentThread(); DWORD_PTR previous_mask = SetThreadAffinityMask(current_thread, 1); // Get the frequency of the performance counter // (it is constant across the program lifetime) static const LARGE_INTEGER frequency = GetFrequency(); // Get the current time LARGE_INTEGER time; QueryPerformanceCounter(&time); // Restore the thread affinity SetThreadAffinityMask(current_thread, previous_mask); // Return the current time as microseconds return Int64(1000000LL * time.QuadPart / frequency.QuadPart); } // ------------------------------------------------------------------------------------------------ Int64 GetEpochTimeMicro() { FILETIME ft; GetSystemTimeAsFileTime(&ft); // Extract the nanoseconds from the resulted timestamp Uint64 time = ft.dwHighDateTime; time <<= 32; time |= ft.dwLowDateTime; time /= 10; time -= 11644473600000000ULL; // Return the resulted timestamp return Int64(time); } #else // ------------------------------------------------------------------------------------------------ Int64 GetCurrentSysTime() { // POSIX implementation timespec time; clock_gettime(CLOCK_MONOTONIC, &time); return Int64(Uint64(time.tv_sec) * 1000000 + time.tv_nsec / 1000); } // ------------------------------------------------------------------------------------------------ Int64 GetEpochTimeMicro() { // POSIX implementation timespec time; clock_gettime(CLOCK_REALTIME, &time); return Int64(Uint64(time.tv_sec) * 1000000 + time.tv_nsec / 1000); } #endif // SQMOD_OS_WINDOWS // ------------------------------------------------------------------------------------------------ Int64 GetEpochTimeMilli() { return (GetEpochTimeMicro() / 1000L); } // ------------------------------------------------------------------------------------------------ Timestamp::Timestamp(const SLongInt & t) : m_Timestamp(t.GetNum()) { /* ... */ } // ------------------------------------------------------------------------------------------------ Int32 Timestamp::Cmp(const Timestamp & o) const { if (m_Timestamp == o.m_Timestamp) return 0; else if (m_Timestamp > o.m_Timestamp) return 1; else return -1; } // ------------------------------------------------------------------------------------------------ CSStr Timestamp::ToString() const { return ToStrF("%lld", m_Timestamp); } // ------------------------------------------------------------------------------------------------ void Timestamp::SetNow() { m_Timestamp = GetCurrentSysTime(); } // ------------------------------------------------------------------------------------------------ SLongInt Timestamp::GetMicroseconds() const { return SLongInt(m_Timestamp); } // ------------------------------------------------------------------------------------------------ void Timestamp::SetMicroseconds(const SLongInt & ammount) { m_Timestamp = ammount.GetNum(); } // ------------------------------------------------------------------------------------------------ SLongInt Timestamp::GetMilliseconds() const { return SLongInt(m_Timestamp / 1000L); } // ------------------------------------------------------------------------------------------------ void Timestamp::SetMilliseconds(const SLongInt & ammount) { m_Timestamp = (ammount.GetNum() * 1000L); } // ------------------------------------------------------------------------------------------------ Timer::Timer() : m_Timestamp(GetCurrentSysTime()) { /* ... */ } // ------------------------------------------------------------------------------------------------ Int32 Timer::Cmp(const Timer & o) const { if (m_Timestamp == o.m_Timestamp) return 0; else if (m_Timestamp > o.m_Timestamp) return 1; else return -1; } // ------------------------------------------------------------------------------------------------ CSStr Timer::ToString() const { return ToStrF("%lld", m_Timestamp); } // ------------------------------------------------------------------------------------------------ void Timer::Reset() { m_Timestamp = GetCurrentSysTime(); } // ------------------------------------------------------------------------------------------------ Timestamp Timer::Restart() { const Int64 now = GetCurrentSysTime(), elapsed = now - m_Timestamp; m_Timestamp = now; return Timestamp(elapsed); } // ------------------------------------------------------------------------------------------------ Int64 Timer::RestartRaw() { const Int64 now = GetCurrentSysTime(), elapsed = now - m_Timestamp; m_Timestamp = now; return elapsed; } // ------------------------------------------------------------------------------------------------ Timestamp Timer::GetElapsedTime() const { return Timestamp(GetCurrentSysTime() - m_Timestamp); } // ------------------------------------------------------------------------------------------------ Int64 Timer::GetElapsedTimeRaw() const { return (GetCurrentSysTime() - m_Timestamp); } // ------------------------------------------------------------------------------------------------ static SLongInt SqGetEpochTimeMicro() { return SLongInt(GetEpochTimeMicro()); } // ------------------------------------------------------------------------------------------------ static SLongInt SqGetEpochTimeMilli() { return SLongInt(GetEpochTimeMilli()); } // ------------------------------------------------------------------------------------------------ static SLongInt SqGetCurrentSysTime() { return SLongInt(GetCurrentSysTime()); } // ------------------------------------------------------------------------------------------------ static Timestamp SqGetEpochTimeNow() { return Timestamp(GetEpochTimeMicro()); } // ------------------------------------------------------------------------------------------------ static Timestamp SqGetMicrosecondsRaw(Int64 ammount) { return Timestamp(ammount); } // ------------------------------------------------------------------------------------------------ static Timestamp SqGetMicroseconds(const SLongInt & ammount) { return Timestamp(ammount); } // ------------------------------------------------------------------------------------------------ static Timestamp SqGetMilliseconds(SQInteger ammount) { return Timestamp(Int64(Int64(ammount) * 1000L)); } // ------------------------------------------------------------------------------------------------ static Timestamp SqGetSeconds(SQFloat ammount) { return Timestamp(Int64(Float64(ammount) * 1000000L)); } // ------------------------------------------------------------------------------------------------ static Timestamp SqGetMinutes(SQFloat ammount) { return Timestamp(Int64((Float64(ammount) * 60000000L))); } // ------------------------------------------------------------------------------------------------ static Timestamp SqGetHours(SQFloat ammount) { return Timestamp(Int64(Float64(ammount) * 3600000000LL)); } // ------------------------------------------------------------------------------------------------ static Timestamp SqGetDays(SQFloat ammount) { return Timestamp(Int64(Float64(ammount) * 86400000000LL)); } // ------------------------------------------------------------------------------------------------ static Timestamp SqGetYears(SQFloat ammount) { return Timestamp(Int64(Float64(ammount) * 31557600000000LL)); } // ================================================================================================ void Register_Time(HSQUIRRELVM vm) { Table timens(vm); timens.Bind(_SC("Stamp"), Class< Timestamp >(vm, _SC("SqTimestamp")) /* Constructors */ .Ctor() .Ctor< const Timestamp & >() /* Core Metamethods */ .Func(_SC("_tostring"), &Timestamp::ToString) .Func(_SC("_cmp"), &Timestamp::Cmp) /* Metamethods */ .Func< Timestamp (Timestamp::*)(const Timestamp &) const >(_SC("_add"), &Timestamp::operator +) .Func< Timestamp (Timestamp::*)(const Timestamp &) const >(_SC("_sub"), &Timestamp::operator -) .Func< Timestamp (Timestamp::*)(const Timestamp &) const >(_SC("_mul"), &Timestamp::operator *) .Func< Timestamp (Timestamp::*)(const Timestamp &) const >(_SC("_div"), &Timestamp::operator /) /* Properties */ .Prop(_SC("Microseconds"), &Timestamp::GetMicroseconds, &Timestamp::SetMicroseconds) .Prop(_SC("MicrosecondsRaw"), &Timestamp::GetMicrosecondsRaw, &Timestamp::SetMicrosecondsRaw) .Prop(_SC("Milliseconds"), &Timestamp::GetMilliseconds, &Timestamp::SetMilliseconds) .Prop(_SC("MillisecondsRaw"), &Timestamp::GetMillisecondsRaw, &Timestamp::SetMillisecondsRaw) .Prop(_SC("SecondsF"), &Timestamp::GetSecondsF, &Timestamp::SetSecondsF) .Prop(_SC("SecondsI"), &Timestamp::GetSecondsI, &Timestamp::SetSecondsI) .Prop(_SC("MinutesF"), &Timestamp::GetMinutesF, &Timestamp::SetMinutesF) .Prop(_SC("MinutesI"), &Timestamp::GetMinutesI, &Timestamp::SetMinutesI) .Prop(_SC("HoursF"), &Timestamp::GetHoursF, &Timestamp::SetHoursF) .Prop(_SC("HoursI"), &Timestamp::GetHoursI, &Timestamp::SetHoursI) .Prop(_SC("DaysF"), &Timestamp::GetDaysF, &Timestamp::SetDaysF) .Prop(_SC("DaysI"), &Timestamp::GetDaysI, &Timestamp::SetDaysI) .Prop(_SC("YearsF"), &Timestamp::GetYearsF, &Timestamp::SetYearsF) .Prop(_SC("YearsI"), &Timestamp::GetYearsI, &Timestamp::SetYearsI) /* Functions */ .Func(_SC("SetNow"), &Timestamp::SetNow) ); timens.Bind(_SC("Timer"), Class< Timer >(vm, _SC("SqTimer")) /* Constructors */ .Ctor() .Ctor< const Timer & >() /* Core Metamethods */ .Func(_SC("_tostring"), &Timer::ToString) .Func(_SC("_cmp"), &Timer::Cmp) /* Properties */ .Prop(_SC("Elapsed"), &Timer::GetElapsedTime) .Prop(_SC("ElapsedRaw"), &Timer::GetElapsedTimeRaw) /* Functions */ .Func(_SC("Reset"), &Timer::Reset) .Func(_SC("Restart"), &Timer::Restart) .Func(_SC("RestartRaw"), &Timer::RestartRaw) ); timens .Func(_SC("EpochMicro"), &SqGetEpochTimeMicro) .Func(_SC("EpochMilli"), &SqGetEpochTimeMilli) .Func(_SC("Current"), &SqGetCurrentSysTime) .Func(_SC("Now"), &SqGetEpochTimeNow) .Func(_SC("MicrosecondsRaw"), &SqGetMicrosecondsRaw) .Func(_SC("Microseconds"), &SqGetMicroseconds) .Func(_SC("Milliseconds"), &SqGetMilliseconds) .Func(_SC("Seconds"), &SqGetSeconds) .Func(_SC("Minutes"), &SqGetMinutes) .Func(_SC("Hours"), &SqGetHours) .Func(_SC("Days"), &SqGetDays) .Func(_SC("Years"), &SqGetYears); RootTable(vm).Bind(_SC("SqTime"), timens); } } // Namespace:: SqMod