From f6727d26bde0bafd4802b01074b6c0057dcce56d Mon Sep 17 00:00:00 2001 From: Balazs Racz Date: Sun, 29 Jan 2023 14:07:17 +0100 Subject: [PATCH] Adds time jump information to the broadcast time update callbacks. The jump information gives direct access in the callback to both the old state and the new state. This allows the user of the time object to determine whether the fast time has jumped, by how much and which direction. Use-cases that work with time intervals need this jump information. --- src/openlcb/BroadcastTime.hxx | 26 +++++++++++++++++++------- src/openlcb/BroadcastTimeClient.hxx | 16 ++++++++-------- src/openlcb/BroadcastTimeServer.cxx | 5 ++++- 3 files changed, 31 insertions(+), 16 deletions(-) diff --git a/src/openlcb/BroadcastTime.hxx b/src/openlcb/BroadcastTime.hxx index 5b6f54a82..7a8841d2f 100644 --- a/src/openlcb/BroadcastTime.hxx +++ b/src/openlcb/BroadcastTime.hxx @@ -50,7 +50,16 @@ class BroadcastTime : public SimpleEventHandler , public TimeBase { public: - typedef std::vector>::size_type UpdateSubscribeHandle; + /// An opaque data element that is returned from update subscriber + /// registration, and allows unregistering a subscriber. + typedef size_t UpdateSubscribeHandle; + + /// Callback type used for time update subscribers. + /// + /// @param old Fast clock's current time according to the pre-update state. + /// @param current Fast clock's current time according to the post-update + /// state. + typedef std::function TimeUpdateCallback; /// Destructor. virtual ~BroadcastTime() @@ -127,7 +136,7 @@ public: /// executor. /// @param callback function callback to be called. /// @return handle to entry that can be used in update_unsubscribe - UpdateSubscribeHandle update_subscribe_add(std::function callback) + UpdateSubscribeHandle update_subscribe_add(TimeUpdateCallback callback) { AtomicHolder h(this); for (size_t i = 0; i < callbacks_.size(); ++i) @@ -135,11 +144,11 @@ public: // atempt to garbage collect unused entries if (callbacks_[i] == nullptr) { - callbacks_[i] = callback; + callbacks_[i] = std::move(callback); return i; } } - callbacks_.emplace_back(callback); + callbacks_.emplace_back(std::move(callback)); return callbacks_.size() - 1; } @@ -225,14 +234,17 @@ protected: /// Service all of the attached update subscribers. These are called when /// there are jumps in time or if the clock is stopped or started. - void service_callbacks() + /// @param old Fast clock's current time according to the pre-update state. + /// @param current Fast clock's current time according to the post-update + /// state. + void service_callbacks(time_t old, time_t current) { AtomicHolder h(this); for (auto n : callbacks_) { if (n) { - n(); + n(old, current); } } } @@ -245,7 +257,7 @@ protected: StateFlowTimer timer_; ///< timer helper /// update subscribers - std::vector> callbacks_; + std::vector callbacks_; int16_t rateRequested_; ///< pending clock rate diff --git a/src/openlcb/BroadcastTimeClient.hxx b/src/openlcb/BroadcastTimeClient.hxx index 4b834e77a..94037bcce 100644 --- a/src/openlcb/BroadcastTimeClient.hxx +++ b/src/openlcb/BroadcastTimeClient.hxx @@ -239,6 +239,7 @@ private: void start_stop_logic(bool started) { bool notify = false; + time_t val = 0; { AtomicHolder h(this); if (started_ != started) @@ -254,12 +255,13 @@ private: } started_ = started; notify = true; + val = seconds_; } // release AtomicHolder } if (notify) { - service_callbacks(); + service_callbacks(val, val); } } @@ -333,20 +335,17 @@ private: { bool notify = false; + time_t old_seconds = 0; + time_t new_seconds = 0; { AtomicHolder h(this); - time_t old_seconds; + old_seconds = time(); if (rate_ != rateRequested_ || (immediateUpdate_ && immediatePending_)) { // rate changed or an immediate update was pending. notify = true; } - else - { - // we will need to check for jitter later - old_seconds = time(); - } // we are about to commit an updated time, reset the flags immediateUpdate_ = false; @@ -355,6 +354,7 @@ private: rate_ = rateRequested_; seconds_ = ::mktime(&tm_); timestamp_ = OSTime::get_monotonic(); + new_seconds = seconds_; if (rolloverPending_) { // roll forward/back the 3 second delay for the year/date @@ -377,7 +377,7 @@ private: } if (notify) { - service_callbacks(); + service_callbacks(old_seconds, new_seconds); } } diff --git a/src/openlcb/BroadcastTimeServer.cxx b/src/openlcb/BroadcastTimeServer.cxx index 7cb223710..02fcb7bae 100644 --- a/src/openlcb/BroadcastTimeServer.cxx +++ b/src/openlcb/BroadcastTimeServer.cxx @@ -543,6 +543,8 @@ class BroadcastTimeServerSet bool start_or_stop = false; struct tm tm; server_->gmtime_r(&tm); + time_t old_seconds = server_->time(); + time_t new_seconds = 0; uint16_t suffix = message()->data()->suffix_; @@ -590,9 +592,10 @@ class BroadcastTimeServerSet AtomicHolder h(server_); server_->seconds_ = mktime(&tm); server_->timestamp_ = OSTime::get_monotonic(); + new_seconds = server_->seconds_; } - server_->service_callbacks(); + server_->service_callbacks(old_seconds, new_seconds); if (start_or_stop) {