Skip to content

Commit

Permalink
Adds time jump information to the broadcast time update callbacks. (#694
Browse files Browse the repository at this point in the history
)

* 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.
  • Loading branch information
balazsracz authored Jul 8, 2023
1 parent 343b60b commit 441f046
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 16 deletions.
26 changes: 19 additions & 7 deletions src/openlcb/BroadcastTime.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,16 @@ class BroadcastTime : public SimpleEventHandler
, public TimeBase
{
public:
typedef std::vector<std::function<void()>>::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<void(time_t old, time_t current)> TimeUpdateCallback;

/// Destructor.
virtual ~BroadcastTime()
Expand Down Expand Up @@ -127,19 +136,19 @@ 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<void()> callback)
UpdateSubscribeHandle update_subscribe_add(TimeUpdateCallback callback)
{
AtomicHolder h(this);
for (size_t i = 0; i < callbacks_.size(); ++i)
{
// 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;
}

Expand Down Expand Up @@ -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);
}
}
}
Expand All @@ -245,7 +257,7 @@ protected:
StateFlowTimer timer_; ///< timer helper

/// update subscribers
std::vector<std::function<void()>> callbacks_;
std::vector<TimeUpdateCallback> callbacks_;

int16_t rateRequested_; ///< pending clock rate

Expand Down
16 changes: 8 additions & 8 deletions src/openlcb/BroadcastTimeClient.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@ private:
void start_stop_logic(bool started)
{
bool notify = false;
time_t val = 0;
{
AtomicHolder h(this);
if (started_ != started)
Expand All @@ -254,12 +255,13 @@ private:
}
started_ = started;
notify = true;
val = seconds_;
}
// release AtomicHolder
}
if (notify)
{
service_callbacks();
service_callbacks(val, val);
}
}

Expand Down Expand Up @@ -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;
Expand All @@ -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
Expand All @@ -377,7 +377,7 @@ private:
}
if (notify)
{
service_callbacks();
service_callbacks(old_seconds, new_seconds);
}
}

Expand Down
5 changes: 4 additions & 1 deletion src/openlcb/BroadcastTimeServer.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -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_;

Expand Down Expand Up @@ -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)
{
Expand Down

0 comments on commit 441f046

Please sign in to comment.