diff --git a/src/Actor.cpp b/src/Actor.cpp index 18f1af1c3d..db47a101d9 100644 --- a/src/Actor.cpp +++ b/src/Actor.cpp @@ -919,7 +919,7 @@ void Actor::UpdateInternal(float delta_time) } break; case CLOCK_TIMER_GLOBAL: - generic_global_timer_update(RageTimer::GetUsecsSinceStart(), m_fEffectDelta, m_fSecsIntoEffect); + generic_global_timer_update(RageTimer::GetTimeSinceStartMicroseconds(), m_fEffectDelta, m_fSecsIntoEffect); break; case CLOCK_BGM_BEAT: generic_global_timer_update(g_fCurrentBGMBeat, m_fEffectDelta, m_fSecsIntoEffect); diff --git a/src/ArrowEffects.cpp b/src/ArrowEffects.cpp index 68dbb2da3f..1fe97c4a8f 100644 --- a/src/ArrowEffects.cpp +++ b/src/ArrowEffects.cpp @@ -101,13 +101,13 @@ float ArrowEffects::GetTime() { case ModTimerType_Default: case ModTimerType_Game: - return (RageTimer::GetTimeSinceStartFast()+offset)*mult; + return (RageTimer::GetTimeSinceStart()+offset)*mult; case ModTimerType_Beat: return (GAMESTATE->m_Position.m_fSongBeatVisible+offset)*mult; case ModTimerType_Song: return (GAMESTATE->m_Position.m_fMusicSeconds+offset)*mult; default: - return RageTimer::GetTimeSinceStartFast()+offset; + return RageTimer::GetTimeSinceStart()+offset; } } @@ -316,7 +316,7 @@ void ArrowEffects::Init(PlayerNumber pn) void ArrowEffects::Update() { static float fLastTime = 0; - float fTime = RageTimer::GetTimeSinceStartFast(); + float fTime = RageTimer::GetTimeSinceStart(); FOREACH_EnabledPlayer( pn ) { diff --git a/src/BGAnimationLayer.cpp b/src/BGAnimationLayer.cpp index f8a9e56fbf..d6851feddd 100644 --- a/src/BGAnimationLayer.cpp +++ b/src/BGAnimationLayer.cpp @@ -611,7 +611,7 @@ void BGAnimationLayer::UpdateInternal( float fDeltaTime ) break; case TYPE_TILES: { - float fSecs = RageTimer::GetTimeSinceStartFast(); + float fSecs = RageTimer::GetTimeSinceStart(); float fTotalWidth = m_iNumTilesWide * m_fTilesSpacingX; float fTotalHeight = m_iNumTilesHigh * m_fTilesSpacingY; diff --git a/src/Inventory.cpp b/src/Inventory.cpp index e8aee6498f..84c93c0ad5 100644 --- a/src/Inventory.cpp +++ b/src/Inventory.cpp @@ -132,8 +132,9 @@ void Inventory::Update( float fDelta ) GAMESTATE->m_Position.m_fSongBeat < song.GetLastBeat() ) { // every 1 seconds, try to use an item - int iLastSecond = (int)(RageTimer::GetTimeSinceStartFast() - fDelta); - int iThisSecond = (int)RageTimer::GetTimeSinceStartFast(); + int iDelta = static_cast(fDelta); + int iLastSecond = RageTimer::GetTimeSinceStartSeconds() - iDelta; + int iThisSecond = RageTimer::GetTimeSinceStartSeconds(); if( iLastSecond != iThisSecond ) { for( int s=0; s 0.015f ) - LOG->Trace( "Lock at %s:%i took %f", file, line, dur ); + const uint_fast64_t current_usecs = RageTimer::GetTimeSinceStartMicroseconds(); + const uint_fast64_t dur_usecs = current_usecs - locked_at; + + if (dur_usecs > THRESHOLD_USEC) + LOG->Trace("Lock at %s:%i took %llu microseconds", file, line, dur_usecs); } } diff --git a/src/RageThreads.h b/src/RageThreads.h index 7b702d39aa..f9e1bef683 100644 --- a/src/RageThreads.h +++ b/src/RageThreads.h @@ -2,6 +2,9 @@ #define RAGE_THREADS_H #include +#include + +static constexpr uint_fast64_t FAST_ULL_MAX = std::numeric_limits::max(); struct ThreadSlot; class RageTimer; @@ -128,12 +131,12 @@ class LockMutex const char *file; int line; - float locked_at; + uint_fast64_t locked_at; bool locked; public: LockMutex(RageMutex &mut, const char *file, int line); - LockMutex(RageMutex &mut): mutex(mut), file(nullptr), line(-1), locked_at(-1), locked(true) { mutex.Lock(); } + LockMutex(RageMutex &mut): mutex(mut), file(nullptr), line(-1), locked_at(FAST_ULL_MAX), locked(true) { mutex.Lock(); } ~LockMutex(); LockMutex(LockMutex &cpy): mutex(cpy.mutex), file(nullptr), line(-1), locked_at(cpy.locked_at), locked(true) { mutex.Lock(); } diff --git a/src/RageTimer.cpp b/src/RageTimer.cpp index 643aa6dfe7..f7fb9b88e4 100644 --- a/src/RageTimer.cpp +++ b/src/RageTimer.cpp @@ -32,14 +32,16 @@ const std::uint64_t ONE_SECOND_IN_MICROSECONDS_ULL = 1000000ULL; const std::int64_t ONE_SECOND_IN_MICROSECONDS_LL = 1000000LL; +const uint_fast64_t ONE_SECOND_IN_MICROSECONDS_FAST_ULL = 1000000ULL; const double ONE_SECOND_IN_MICROSECONDS_DBL = 1000000.0; const RageTimer RageZeroTimer(0,0); -static std::uint64_t g_iStartTime = ArchHooks::GetMicrosecondsSinceStart(); +static const std::uint64_t g_iStartTime = ArchHooks::GetSystemTimeInMicroseconds(); +static uint_fast64_t g_iStartTimeFast64 = g_iStartTime; static std::uint64_t GetTime() { - return ArchHooks::GetMicrosecondsSinceStart(); + return ArchHooks::GetSystemTimeInMicroseconds(); } /* The accuracy of RageTimer::GetTimeSinceStart() is directly tied to the @@ -52,14 +54,19 @@ static std::uint64_t GetTime() * and do thorough testing if you change anything here. -sukibaby */ double RageTimer::GetTimeSinceStart() { - std::uint64_t usecs = GetTime(); - usecs -= g_iStartTime; - return usecs / ONE_SECOND_IN_MICROSECONDS_DBL; + constexpr double USEC_TO_SEC = 1.0 / 1000000.0; + return static_cast(RageTimer::GetTimeSinceStartMicroseconds()) * USEC_TO_SEC; } -std::uint64_t RageTimer::GetUsecsSinceStart() +int RageTimer::GetTimeSinceStartSeconds() { - return GetTime() - g_iStartTime; + uint_fast64_t usec = RageTimer::GetTimeSinceStartMicroseconds(); + return static_cast(usec / ONE_SECOND_IN_MICROSECONDS_FAST_ULL); +} + +uint_fast64_t RageTimer::GetTimeSinceStartMicroseconds() +{ + return GetTime() - g_iStartTimeFast64; } void RageTimer::Touch() diff --git a/src/RageTimer.h b/src/RageTimer.h index 9c9ea0942b..567df80c39 100644 --- a/src/RageTimer.h +++ b/src/RageTimer.h @@ -25,7 +25,8 @@ public: static double GetTimeSinceStart(); // seconds since the program was started static float GetTimeSinceStartFast() { return GetTimeSinceStart(); } - static std::uint64_t GetUsecsSinceStart(); + static int GetTimeSinceStartSeconds(); + static uint_fast64_t GetTimeSinceStartMicroseconds(); /* Get a timer representing half of the time ago as this one. */ RageTimer Half() const; diff --git a/src/RageUtil.cpp b/src/RageUtil.cpp index bd93bd5243..68ab34d8be 100644 --- a/src/RageUtil.cpp +++ b/src/RageUtil.cpp @@ -252,6 +252,16 @@ RString SecondsToMSSMsMs( float fSecs ) return sReturn; } +RString MicrosecondsToMMSSMsMs(uint64_t usecs) +{ + const uint64_t totalSeconds = usecs / 1000000; + const uint64_t iMinsDisplay = totalSeconds / 60; + const uint64_t iSecsDisplay = totalSeconds % 60; + const uint64_t iLeftoverDisplay = (usecs % 1000000) / 10000; // Adjusted for two decimal places + RString sReturn = ssprintf("%02llu:%02llu.%02llu", iMinsDisplay, iSecsDisplay, std::min(99, iLeftoverDisplay)); + return sReturn; +} + RString SecondsToMMSSMsMsMs( float fSecs ) { const int iMinsDisplay = static_cast(fSecs/60); @@ -261,6 +271,16 @@ RString SecondsToMMSSMsMsMs( float fSecs ) return sReturn; } +RString MicrosecondsToMMSSMsMsMs(uint64_t usecs) +{ + const uint64_t totalSeconds = usecs / 1000000; + const uint64_t iMinsDisplay = totalSeconds / 60; + const uint64_t iSecsDisplay = totalSeconds % 60; + const uint64_t iLeftoverDisplay = (usecs % 1000000) / 1000; + RString sReturn = ssprintf("%02llu:%02llu.%03llu", iMinsDisplay, iSecsDisplay, std::min(999, iLeftoverDisplay)); + return sReturn; +} + RString SecondsToMSS( float fSecs ) { const int iMinsDisplay = static_cast(fSecs/60); diff --git a/src/RageUtil.h b/src/RageUtil.h index 5c86c4e71f..899106867a 100644 --- a/src/RageUtil.h +++ b/src/RageUtil.h @@ -326,6 +326,8 @@ RString SecondsToHHMMSS( float fSecs ); RString SecondsToMSSMsMs( float fSecs ); RString SecondsToMMSSMsMs( float fSecs ); RString SecondsToMMSSMsMsMs( float fSecs ); +RString MicrosecondsToMMSSMsMs(uint64_t usecs); +RString MicrosecondsToMMSSMsMsMs(uint64_t usecs); RString SecondsToMSS( float fSecs ); RString SecondsToMMSS( float fSecs ); RString PrettyPercent( float fNumerator, float fDenominator ); diff --git a/src/ScreenDebugOverlay.cpp b/src/ScreenDebugOverlay.cpp index 87a36ce640..d7f737c621 100644 --- a/src/ScreenDebugOverlay.cpp +++ b/src/ScreenDebugOverlay.cpp @@ -1319,7 +1319,7 @@ class DebugLineForceCrash : public IDebugLine class DebugLineUptime : public IDebugLine { virtual RString GetDisplayTitle() { return UPTIME.GetValue(); } - virtual RString GetDisplayValue() { return SecondsToMMSSMsMsMs(RageTimer::GetTimeSinceStart()); } + virtual RString GetDisplayValue() { return MicrosecondsToMMSSMsMsMs(RageTimer::GetTimeSinceStartMicroseconds()); } virtual bool IsEnabled() { return false; } virtual void DoAndLog( RString &sMessageOut ) {} }; diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index e8e6ee23dd..ee94f33bf0 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -48,9 +48,9 @@ static Preference g_iDefaultRecordLength( "DefaultRecordLength", 4 ); static Preference g_bEditorShowBGChangesPlay( "EditorShowBGChangesPlay", true ); /** @brief How long must the button be held to generate a hold in record mode? */ -const float record_hold_default= 0.3f; -float record_hold_seconds = record_hold_default; -const float time_between_autosave= 300.0f; // 5 minutes. -Kyz +constexpr uint_fast64_t record_hold_default = 300000; // 0.3 seconds in microseconds +uint_fast64_t record_hold_seconds = record_hold_default; +constexpr uint_fast64_t time_between_autosave = 300000000; // 300 seconds in microseconds #define PLAYER_X (SCREEN_CENTER_X) #define PLAYER_Y (SCREEN_CENTER_Y) @@ -1666,8 +1666,8 @@ void ScreenEdit::Update( float fDeltaTime ) if(m_EditState == STATE_EDITING) { - if(IsDirty() && m_next_autosave_time > -1.0f && - RageTimer::GetTimeSinceStartFast() > m_next_autosave_time) + if(IsDirty() && m_next_autosave_time > -1000000 && + RageTimer::GetTimeSinceStartMicroseconds() > m_next_autosave_time) { PerformSave(true); } @@ -4362,7 +4362,7 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM ) else if( SM == SM_AutoSaveSuccessful ) { LOG->Trace("AutoSave successful."); - m_next_autosave_time= RageTimer::GetTimeSinceStartFast() + time_between_autosave; + m_next_autosave_time= RageTimer::GetTimeSinceStartMicroseconds() + time_between_autosave; SCREENMAN->SystemMessage(AUTOSAVE_SUCCESSFUL); } else if( SM == SM_SaveFailed ) // save failed; stay in the editor @@ -4438,19 +4438,19 @@ void ScreenEdit::SetDirty(bool dirty) if(EDIT_MODE.GetValue() != EditMode_Full) { m_dirty= false; - m_next_autosave_time= -1.0f; + m_next_autosave_time= -1000000; return; } if(dirty) { if(!m_dirty) { - m_next_autosave_time= RageTimer::GetTimeSinceStartFast() + time_between_autosave; + m_next_autosave_time= RageTimer::GetTimeSinceStartMicroseconds() + time_between_autosave; } } else { - m_next_autosave_time= -1.0f; + m_next_autosave_time= -1000000; } m_dirty= dirty; } diff --git a/src/ScreenStatsOverlay.cpp b/src/ScreenStatsOverlay.cpp index 14f5cd163a..4d70a8e19f 100644 --- a/src/ScreenStatsOverlay.cpp +++ b/src/ScreenStatsOverlay.cpp @@ -125,7 +125,7 @@ void ScreenStatsOverlay::UpdateSkips() if( skip ) { - RString sTime( SecondsToMMSSMsMs(RageTimer::GetTimeSinceStartFast()) ); + RString sTime( MicrosecondsToMMSSMsMs(RageTimer::GetTimeSinceStartMicroseconds()) ); static const RageColor colors[] = { diff --git a/src/WheelNotifyIcon.cpp b/src/WheelNotifyIcon.cpp index c29538be5b..75444e7c5a 100644 --- a/src/WheelNotifyIcon.cpp +++ b/src/WheelNotifyIcon.cpp @@ -86,9 +86,10 @@ void WheelNotifyIcon::Update( float fDeltaTime ) /* We should probably end up parsing the vector and then dynamically * insert flag icons based on "priority". Easy to do, hopefully - Midiman */ - const float fSecondFraction = std::fmod( RageTimer::GetTimeSinceStartFast(), 1 ); - const int index = (int)(fSecondFraction*m_vIconsToShow.size()); - Sprite::SetState( m_vIconsToShow[index] ); + static std::uint_fast32_t updateCounter = 0; + updateCounter++; + const int index = updateCounter % m_vIconsToShow.size(); + Sprite::SetState(m_vIconsToShow[index]); } Sprite::Update( fDeltaTime ); diff --git a/src/arch/ArchHooks/ArchHooks.h b/src/arch/ArchHooks/ArchHooks.h index 341552a477..8adb419f83 100644 --- a/src/arch/ArchHooks/ArchHooks.h +++ b/src/arch/ArchHooks/ArchHooks.h @@ -87,7 +87,7 @@ public: * underlying timers may be 32-bit, but implementations should try to avoid * wrapping if possible. */ - static std::int64_t GetMicrosecondsSinceStart(); + static std::int64_t GetSystemTimeInMicroseconds(); /* * Add file search paths, higher priority first. @@ -129,7 +129,7 @@ public: void RegisterWithLua(); private: - /* This are helpers for GetMicrosecondsSinceStart on systems with a timer + /* This are helpers for GetSystemTimeInMicroseconds on systems with a timer * that may loop or move backwards. */ static std::int64_t FixupTimeIfLooped( std::int64_t usecs ); static std::int64_t FixupTimeIfBackwards( std::int64_t usecs ); diff --git a/src/arch/ArchHooks/ArchHooksUtil.cpp b/src/arch/ArchHooks/ArchHooksUtil.cpp index fe1ac43483..02e0f6cb85 100644 --- a/src/arch/ArchHooks/ArchHooksUtil.cpp +++ b/src/arch/ArchHooks/ArchHooksUtil.cpp @@ -4,7 +4,7 @@ #include /* - * This is a helper for GetMicrosecondsSinceStart on systems with a system + * This is a helper for GetSystemTimeInMicroseconds on systems with a system * timer that may loop or move backwards. * * The time may decrease last for at least two reasons: @@ -23,7 +23,7 @@ * * This helper only needs to be used if one or both of the above conditions can occur. * If the underlying timer is reliable, this doesn't need to be used (for a small - * efficiency bonus). Also, you may omit this for GetMicrosecondsSinceStart() when + * efficiency bonus). Also, you may omit this for GetSystemTimeInMicroseconds() when * bAccurate == false. */ diff --git a/src/arch/ArchHooks/ArchHooks_MacOSX.mm b/src/arch/ArchHooks/ArchHooks_MacOSX.mm index 34e5093584..e9a8b0fda2 100644 --- a/src/arch/ArchHooks/ArchHooks_MacOSX.mm +++ b/src/arch/ArchHooks/ArchHooks_MacOSX.mm @@ -258,7 +258,7 @@ bool ArchHooks_MacOSX::GoToURL( RString sUrl ) return result == 0; } -std::int64_t ArchHooks::GetMicrosecondsSinceStart() +std::int64_t ArchHooks::GetSystemTimeInMicroseconds() { // http://developer.apple.com/qa/qa2004/qa1398.html static double factor = 0.0; diff --git a/src/arch/ArchHooks/ArchHooks_Unix.cpp b/src/arch/ArchHooks/ArchHooks_Unix.cpp index ae2e4424eb..3926cfcc50 100644 --- a/src/arch/ArchHooks/ArchHooks_Unix.cpp +++ b/src/arch/ArchHooks/ArchHooks_Unix.cpp @@ -120,7 +120,7 @@ static void TestTLS() #endif #if 1 -/* If librt is available, use CLOCK_MONOTONIC to implement GetMicrosecondsSinceStart, +/* If librt is available, use CLOCK_MONOTONIC to implement GetSystemTimeInMicroseconds, * if supported, so changes to the system clock don't cause problems. */ namespace { @@ -149,7 +149,7 @@ clockid_t ArchHooks_Unix::GetClock() return g_Clock; } -std::int64_t ArchHooks::GetMicrosecondsSinceStart() +std::int64_t ArchHooks::GetSystemTimeInMicroseconds() { OpenGetTime(); @@ -162,7 +162,7 @@ std::int64_t ArchHooks::GetMicrosecondsSinceStart() return iRet; } #else -std::int64_t ArchHooks::GetMicrosecondsSinceStart() +std::int64_t ArchHooks::GetSystemTimeInMicroseconds() { struct timeval tv; gettimeofday( &tv, nullptr ); diff --git a/src/arch/ArchHooks/ArchHooks_Unix.h b/src/arch/ArchHooks/ArchHooks_Unix.h index 6c0e61fa2b..472bfc005c 100644 --- a/src/arch/ArchHooks/ArchHooks_Unix.h +++ b/src/arch/ArchHooks/ArchHooks_Unix.h @@ -13,7 +13,7 @@ public: void DumpDebugInfo(); void SetTime( tm newtime ); - std::int64_t GetMicrosecondsSinceStart(); + std::int64_t GetSystemTimeInMicroseconds(); void MountInitialFilesystems( const RString &sDirOfExecutable ); float GetDisplayAspectRatio() { return 4.0f/3; } diff --git a/src/arch/ArchHooks/ArchHooks_Win32Static.cpp b/src/arch/ArchHooks/ArchHooks_Win32Static.cpp index c21e63fed4..4c25f01680 100644 --- a/src/arch/ArchHooks/ArchHooks_Win32Static.cpp +++ b/src/arch/ArchHooks/ArchHooks_Win32Static.cpp @@ -39,7 +39,7 @@ static void InitTimer() QueryPerformanceFrequency(&g_liFrequency); } -std::int64_t ArchHooks::GetMicrosecondsSinceStart() +std::int64_t ArchHooks::GetSystemTimeInMicroseconds() { // Make sure the timer is initialized. if (!g_bTimerInitialized) { diff --git a/src/arch/Sound/RageSoundDriver_Generic_Software.cpp b/src/arch/Sound/RageSoundDriver_Generic_Software.cpp index 3d97fc2d0e..032950a641 100644 --- a/src/arch/Sound/RageSoundDriver_Generic_Software.cpp +++ b/src/arch/Sound/RageSoundDriver_Generic_Software.cpp @@ -301,8 +301,9 @@ void RageSoundDriver::Update() // LOG->Trace("set (#%i) %p from STOPPING to HALTING", i, m_Sounds[i].m_pSound); } - static float fNext = 0; - if( RageTimer::GetTimeSinceStart() >= fNext ) + constexpr uint_fast64_t iUsecs = 1000000; + static uint_fast64_t fNextUsecs = 0; + if (RageTimer::GetTimeSinceStartMicroseconds() >= fNextUsecs) { /* Lockless: only Mix() can write to underruns. */ int current_underruns = underruns; @@ -314,7 +315,7 @@ void RageSoundDriver::Update() /* Don't log again for at least a second, or we'll burst output * and possibly cause more underruns. */ - fNext = RageTimer::GetTimeSinceStart() + 1; + fNextUsecs = RageTimer::GetTimeSinceStartMicroseconds() + iUsecs; } } @@ -493,7 +494,7 @@ std::int64_t RageSoundDriver::ClampHardwareFrame( std::int64_t iHardwareFrame ) /* Clamp the output to one per second, so one underruns don't cascade due to * output spam. */ static std::int64_t lastTime = 0; - std::int64_t currentTime = RageTimer::GetUsecsSinceStart(); + std::int64_t currentTime = RageTimer::GetTimeSinceStartMicroseconds(); if( lastTime == 0 || (currentTime - lastTime) > 1000000 ) { LOG->Trace("RageSoundDriver: driver returned a lesser position (%" PRId64 " < %" PRId64 ")", iHardwareFrame, m_iMaxHardwareFrame); @@ -529,9 +530,9 @@ std::int64_t RageSoundDriver::GetHardwareFrame( RageTimer *pTimestamp=nullptr ) do { - iStartTime = RageTimer::GetUsecsSinceStart(); + iStartTime = RageTimer::GetTimeSinceStartMicroseconds(); iPositionFrames = GetPosition(); - std::uint64_t elapsedTime = RageTimer::GetUsecsSinceStart() - iStartTime; + std::uint64_t elapsedTime = RageTimer::GetTimeSinceStartMicroseconds() - iStartTime; if (elapsedTime <= iThreshold) break; } while (--iTries); diff --git a/src/arch/Sound/RageSoundDriver_Null.cpp b/src/arch/Sound/RageSoundDriver_Null.cpp index c73ac3adba..2045441ce8 100644 --- a/src/arch/Sound/RageSoundDriver_Null.cpp +++ b/src/arch/Sound/RageSoundDriver_Null.cpp @@ -25,7 +25,7 @@ void RageSoundDriver_Null::Update() std::int64_t RageSoundDriver_Null::GetPosition() const { - return std::int64_t( RageTimer::GetTimeSinceStart() * m_iSampleRate ); + return (RageTimer::GetTimeSinceStartMicroseconds() * m_iSampleRate) / 1000000; } RageSoundDriver_Null::RageSoundDriver_Null()