diff --git a/Implementation/Common/common_chrono.cpp b/Implementation/Common/common_chrono.cpp index a3ac3a1f..994b4713 100644 --- a/Implementation/Common/common_chrono.cpp +++ b/Implementation/Common/common_chrono.cpp @@ -187,6 +187,11 @@ namespace AMCCommon { return convertToISO8601TimeUTC(getUTCTimeStampInMicrosecondsSince1970()); } + uint64_t CChrono::getElapsedMicroseconds() + { + return m_pChronoImpl->getElapsedMicroseconds(); + } + void CChrono::sleepSeconds(const uint64_t seconds) { sleepMicroseconds(seconds * 1000000ULL); diff --git a/Implementation/Common/common_chrono.hpp b/Implementation/Common/common_chrono.hpp index 7b0f9a9a..decf083f 100644 --- a/Implementation/Common/common_chrono.hpp +++ b/Implementation/Common/common_chrono.hpp @@ -68,6 +68,11 @@ namespace AMCCommon { // Returns Absolute UTC Time Stamp in ISO8601 formatting std::string getUTCTimeInISO8601(); + // Returns Monotonic Elapsed Time in microseconds since instance creation + // This time is NOT affected by system clock adjustments (NTP, manual changes) + // Use this for timing and delays, NOT for absolute timestamps + uint64_t getElapsedMicroseconds(); + // Sleeps for some seconds static void sleepSeconds(const uint64_t seconds); diff --git a/Implementation/Core/amc_statemachinestate.cpp b/Implementation/Core/amc_statemachinestate.cpp index 6ee10318..52eb2b6f 100644 --- a/Implementation/Core/amc_statemachinestate.cpp +++ b/Implementation/Core/amc_statemachinestate.cpp @@ -85,7 +85,8 @@ namespace AMC { void CStateMachineState::updateExecutionTime() { - m_LastExecutionTimeStampInMicroseconds = m_pGlobalChrono->getUTCTimeStampInMicrosecondsSince1970 (); + // Use monotonic elapsed time to avoid issues with NTP clock adjustments + m_LastExecutionTimeStampInMicroseconds = m_pGlobalChrono->getElapsedMicroseconds(); } @@ -161,8 +162,9 @@ namespace AMC { if (chunkInMilliseconds < AMC_MINREPEATDELAY_MS) throw ELibMCCustomException(LIBMC_ERROR_INVALIDREPEATDELAY, m_sInstanceName); - - uint64_t executionTimeInMicroSeconds = m_pGlobalChrono->getUTCTimeStampInMicrosecondsSince1970(); + + // Use monotonic elapsed time - not affected by NTP or system clock adjustments + uint64_t executionTimeInMicroSeconds = m_pGlobalChrono->getElapsedMicroseconds(); if (m_LastExecutionTimeStampInMicroseconds > executionTimeInMicroSeconds) throw ELibMCCustomException(LIBMC_ERROR_INVALIDEXECUTIONDELAY, std::to_string (m_LastExecutionTimeStampInMicroseconds)); @@ -171,7 +173,7 @@ namespace AMC { while (deltaExecutionTimeInMicroSeconds < (m_nRepeatDelay * 1000ULL)) { m_pGlobalChrono->sleepMilliseconds(chunkInMilliseconds); - uint64_t newExecutionTimeInMicroSeconds = m_pGlobalChrono->getUTCTimeStampInMicrosecondsSince1970(); + uint64_t newExecutionTimeInMicroSeconds = m_pGlobalChrono->getElapsedMicroseconds(); if (m_LastExecutionTimeStampInMicroseconds > newExecutionTimeInMicroSeconds) throw ELibMCCustomException(LIBMC_ERROR_INVALIDEXECUTIONDELAY, std::to_string(m_LastExecutionTimeStampInMicroseconds));