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) {