Loading services/vibratorservice/VibratorCallbackScheduler.cpp +8 −3 Original line number Original line Diff line number Diff line Loading @@ -29,8 +29,11 @@ bool DelayedCallback::isExpired() const { return mExpiration <= std::chrono::steady_clock::now(); return mExpiration <= std::chrono::steady_clock::now(); } } DelayedCallback::Timestamp DelayedCallback::getExpiration() const { std::chrono::milliseconds DelayedCallback::getWaitForExpirationDuration() const { return mExpiration; std::chrono::milliseconds delta = std::chrono::duration_cast<std::chrono::milliseconds>( mExpiration - std::chrono::steady_clock::now()); // Return zero if this is already expired. return delta > delta.zero() ? delta : delta.zero(); } } void DelayedCallback::run() const { void DelayedCallback::run() const { Loading Loading @@ -88,7 +91,9 @@ void CallbackScheduler::loop() { mCondition.wait(mMutex); mCondition.wait(mMutex); } else { } else { // Wait until next callback expires, or a new one is scheduled. // Wait until next callback expires, or a new one is scheduled. mCondition.wait_until(mMutex, mQueue.top().getExpiration()); // Use the monotonic steady clock to wait for the measured delay interval via wait_for // instead of using a wall clock via wait_until. mCondition.wait_for(mMutex, mQueue.top().getWaitForExpirationDuration()); } } } } } } Loading services/vibratorservice/include/vibratorservice/VibratorCallbackScheduler.h +4 −4 Original line number Original line Diff line number Diff line Loading @@ -30,15 +30,13 @@ namespace vibrator { // Wrapper for a callback to be executed after a delay. // Wrapper for a callback to be executed after a delay. class DelayedCallback { class DelayedCallback { public: public: using Timestamp = std::chrono::time_point<std::chrono::steady_clock>; DelayedCallback(std::function<void()> callback, std::chrono::milliseconds delay) DelayedCallback(std::function<void()> callback, std::chrono::milliseconds delay) : mCallback(callback), mExpiration(std::chrono::steady_clock::now() + delay) {} : mCallback(callback), mExpiration(std::chrono::steady_clock::now() + delay) {} ~DelayedCallback() = default; ~DelayedCallback() = default; void run() const; void run() const; bool isExpired() const; bool isExpired() const; Timestamp getExpiration() const; std::chrono::milliseconds getWaitForExpirationDuration() const; // Compare by expiration time, where A < B when A expires first. // Compare by expiration time, where A < B when A expires first. bool operator<(const DelayedCallback& other) const; bool operator<(const DelayedCallback& other) const; Loading @@ -46,7 +44,9 @@ public: private: private: std::function<void()> mCallback; std::function<void()> mCallback; Timestamp mExpiration; // Use a steady monotonic clock to calculate the duration until expiration. // This clock is not related to wall clock time and is most suitable for measuring intervals. std::chrono::time_point<std::chrono::steady_clock> mExpiration; }; }; // Schedules callbacks to be executed after a delay. // Schedules callbacks to be executed after a delay. Loading services/vibratorservice/test/VibratorCallbackSchedulerTest.cpp +9 −3 Original line number Original line Diff line number Diff line Loading @@ -71,15 +71,21 @@ protected: } } int32_t waitForCallbacks(int32_t callbackCount, milliseconds timeout) { int32_t waitForCallbacks(int32_t callbackCount, milliseconds timeout) { time_point<steady_clock> expiration = steady_clock::now() + timeout + TEST_TIMEOUT; time_point<steady_clock> expirationTime = steady_clock::now() + timeout + TEST_TIMEOUT; int32_t expiredCallbackCount = 0; int32_t expiredCallbackCount = 0; while (steady_clock::now() < expiration) { while (steady_clock::now() < expirationTime) { std::lock_guard<std::mutex> lock(mMutex); std::lock_guard<std::mutex> lock(mMutex); expiredCallbackCount = mExpiredCallbacks.size(); expiredCallbackCount = mExpiredCallbacks.size(); if (callbackCount <= expiredCallbackCount) { if (callbackCount <= expiredCallbackCount) { return expiredCallbackCount; return expiredCallbackCount; } } mCondition.wait_until(mMutex, expiration); auto currentTimeout = std::chrono::duration_cast<std::chrono::milliseconds>( expirationTime - steady_clock::now()); if (currentTimeout > currentTimeout.zero()) { // Use the monotonic steady clock to wait for the requested timeout via wait_for // instead of using a wall clock via wait_until. mCondition.wait_for(mMutex, currentTimeout); } } } return expiredCallbackCount; return expiredCallbackCount; } } Loading Loading
services/vibratorservice/VibratorCallbackScheduler.cpp +8 −3 Original line number Original line Diff line number Diff line Loading @@ -29,8 +29,11 @@ bool DelayedCallback::isExpired() const { return mExpiration <= std::chrono::steady_clock::now(); return mExpiration <= std::chrono::steady_clock::now(); } } DelayedCallback::Timestamp DelayedCallback::getExpiration() const { std::chrono::milliseconds DelayedCallback::getWaitForExpirationDuration() const { return mExpiration; std::chrono::milliseconds delta = std::chrono::duration_cast<std::chrono::milliseconds>( mExpiration - std::chrono::steady_clock::now()); // Return zero if this is already expired. return delta > delta.zero() ? delta : delta.zero(); } } void DelayedCallback::run() const { void DelayedCallback::run() const { Loading Loading @@ -88,7 +91,9 @@ void CallbackScheduler::loop() { mCondition.wait(mMutex); mCondition.wait(mMutex); } else { } else { // Wait until next callback expires, or a new one is scheduled. // Wait until next callback expires, or a new one is scheduled. mCondition.wait_until(mMutex, mQueue.top().getExpiration()); // Use the monotonic steady clock to wait for the measured delay interval via wait_for // instead of using a wall clock via wait_until. mCondition.wait_for(mMutex, mQueue.top().getWaitForExpirationDuration()); } } } } } } Loading
services/vibratorservice/include/vibratorservice/VibratorCallbackScheduler.h +4 −4 Original line number Original line Diff line number Diff line Loading @@ -30,15 +30,13 @@ namespace vibrator { // Wrapper for a callback to be executed after a delay. // Wrapper for a callback to be executed after a delay. class DelayedCallback { class DelayedCallback { public: public: using Timestamp = std::chrono::time_point<std::chrono::steady_clock>; DelayedCallback(std::function<void()> callback, std::chrono::milliseconds delay) DelayedCallback(std::function<void()> callback, std::chrono::milliseconds delay) : mCallback(callback), mExpiration(std::chrono::steady_clock::now() + delay) {} : mCallback(callback), mExpiration(std::chrono::steady_clock::now() + delay) {} ~DelayedCallback() = default; ~DelayedCallback() = default; void run() const; void run() const; bool isExpired() const; bool isExpired() const; Timestamp getExpiration() const; std::chrono::milliseconds getWaitForExpirationDuration() const; // Compare by expiration time, where A < B when A expires first. // Compare by expiration time, where A < B when A expires first. bool operator<(const DelayedCallback& other) const; bool operator<(const DelayedCallback& other) const; Loading @@ -46,7 +44,9 @@ public: private: private: std::function<void()> mCallback; std::function<void()> mCallback; Timestamp mExpiration; // Use a steady monotonic clock to calculate the duration until expiration. // This clock is not related to wall clock time and is most suitable for measuring intervals. std::chrono::time_point<std::chrono::steady_clock> mExpiration; }; }; // Schedules callbacks to be executed after a delay. // Schedules callbacks to be executed after a delay. Loading
services/vibratorservice/test/VibratorCallbackSchedulerTest.cpp +9 −3 Original line number Original line Diff line number Diff line Loading @@ -71,15 +71,21 @@ protected: } } int32_t waitForCallbacks(int32_t callbackCount, milliseconds timeout) { int32_t waitForCallbacks(int32_t callbackCount, milliseconds timeout) { time_point<steady_clock> expiration = steady_clock::now() + timeout + TEST_TIMEOUT; time_point<steady_clock> expirationTime = steady_clock::now() + timeout + TEST_TIMEOUT; int32_t expiredCallbackCount = 0; int32_t expiredCallbackCount = 0; while (steady_clock::now() < expiration) { while (steady_clock::now() < expirationTime) { std::lock_guard<std::mutex> lock(mMutex); std::lock_guard<std::mutex> lock(mMutex); expiredCallbackCount = mExpiredCallbacks.size(); expiredCallbackCount = mExpiredCallbacks.size(); if (callbackCount <= expiredCallbackCount) { if (callbackCount <= expiredCallbackCount) { return expiredCallbackCount; return expiredCallbackCount; } } mCondition.wait_until(mMutex, expiration); auto currentTimeout = std::chrono::duration_cast<std::chrono::milliseconds>( expirationTime - steady_clock::now()); if (currentTimeout > currentTimeout.zero()) { // Use the monotonic steady clock to wait for the requested timeout via wait_for // instead of using a wall clock via wait_until. mCondition.wait_for(mMutex, currentTimeout); } } } return expiredCallbackCount; return expiredCallbackCount; } } Loading