Skip to content

Commit

Permalink
removed mNow, using stack now timestamps instead
Browse files Browse the repository at this point in the history
  • Loading branch information
lpbeliveau-silabs committed Aug 11, 2023
1 parent c9f1284 commit 88dea90
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 52 deletions.
9 changes: 2 additions & 7 deletions src/app/reporting/ReportScheduler.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,9 +141,9 @@ class ReportScheduler : public ReadHandler::Observer, public ICDStateObserver
bool IsReportableNow(ReadHandler * aReadHandler)
{
// Update the now timestamp to ensure external calls to IsReportableNow are always comparing to the current time
mNow = mTimerDelegate->GetCurrentMonotonicTimestamp();
Timestamp now = mTimerDelegate->GetCurrentMonotonicTimestamp();
ReadHandlerNode * node = FindReadHandlerNode(aReadHandler);
return (nullptr != node) ? node->IsReportableNow(mNow) : false;
return (nullptr != node) ? node->IsReportableNow(now) : false;
}

/// @brief Check if a ReadHandler is reportable without considering the timing
Expand Down Expand Up @@ -190,11 +190,6 @@ class ReportScheduler : public ReadHandler::Observer, public ICDStateObserver

ObjectPool<ReadHandlerNode, CHIP_IM_MAX_NUM_READS + CHIP_IM_MAX_NUM_SUBSCRIPTIONS> mNodesPool;
TimerDelegate * mTimerDelegate;

// This represents the current time to be used for scheduling the next report, or to compare against Timestamps to determine
// reportability based on time. This timestamp needs to be updated upon each callback that will do scheduling or check the
// reportability state.
Timestamp mNow = System::Clock::Milliseconds64(0);
};
}; // namespace reporting
}; // namespace app
Expand Down
36 changes: 18 additions & 18 deletions src/app/reporting/ReportSchedulerImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@ ReportSchedulerImpl::ReportSchedulerImpl(TimerDelegate * aTimerDelegate) : Repor
void ReportSchedulerImpl::OnEnterActiveMode()
{
#if ICD_REPORT_ON_ENTER_ACTIVE_MODE
mNow = mTimerDelegate->GetCurrentMonotonicTimestamp();
mNodesPool.ForEachActiveObject([this](ReadHandlerNode * node) {
if (this->mNow >= node->GetMinTimestamp())
Timestamp now = mTimerDelegate->GetCurrentMonotonicTimestamp();
mNodesPool.ForEachActiveObject([now](ReadHandlerNode * node) {
if (now >= node->GetMinTimestamp())
{
this->HandlerForceDirtyState(node->GetReadHandler());
}
Expand All @@ -64,11 +64,11 @@ void ReportSchedulerImpl::OnSubscriptionEstablished(ReadHandler * aReadHandler)
VerifyOrDie(nullptr == newNode);

// Update the now timestamp to the current time to determine the min and max timestamps
mNow = mTimerDelegate->GetCurrentMonotonicTimestamp();
Timestamp now = mTimerDelegate->GetCurrentMonotonicTimestamp();

// The NodePool is the same size as the ReadHandler pool from the IM Engine, so we don't need a check for size here since if a
// ReadHandler was created, space should be available.
newNode = mNodesPool.CreateObject(aReadHandler, this, mNow);
newNode = mNodesPool.CreateObject(aReadHandler, this, now);

ChipLogProgress(DataManagement,
"Registered a ReadHandler that will schedule a report between system Timestamp: %" PRIu64
Expand All @@ -83,11 +83,11 @@ void ReportSchedulerImpl::OnBecameReportable(ReadHandler * aReadHandler)
VerifyOrReturn(nullptr != node);

// Update the now timestamp to the current time to calculate the next report timeout
mNow = mTimerDelegate->GetCurrentMonotonicTimestamp();
Timestamp now = mTimerDelegate->GetCurrentMonotonicTimestamp();

Milliseconds32 newTimeout;
CalculateNextReportTimeout(newTimeout, node);
ScheduleReport(newTimeout, node);
CalculateNextReportTimeout(newTimeout, node, now);
ScheduleReport(newTimeout, node, now);
}

void ReportSchedulerImpl::OnSubscriptionReportSent(ReadHandler * aReadHandler)
Expand All @@ -96,12 +96,12 @@ void ReportSchedulerImpl::OnSubscriptionReportSent(ReadHandler * aReadHandler)
VerifyOrReturn(nullptr != node);

// Update the now timestamp to the current time to update the node's interval timestamps and calculate the next report timeout
mNow = mTimerDelegate->GetCurrentMonotonicTimestamp();
Timestamp now = mTimerDelegate->GetCurrentMonotonicTimestamp();

node->SetIntervalTimeStamps(aReadHandler, mNow);
node->SetIntervalTimeStamps(aReadHandler, now);
Milliseconds32 newTimeout;
CalculateNextReportTimeout(newTimeout, node);
ScheduleReport(newTimeout, node);
CalculateNextReportTimeout(newTimeout, node, now);
ScheduleReport(newTimeout, node, now);
node->SetEngineRunScheduled(false);
}

Expand All @@ -117,7 +117,7 @@ void ReportSchedulerImpl::OnReadHandlerDestroyed(ReadHandler * aReadHandler)
mNodesPool.ReleaseObject(removeNode);
}

CHIP_ERROR ReportSchedulerImpl::ScheduleReport(Timeout timeout, ReadHandlerNode * node)
CHIP_ERROR ReportSchedulerImpl::ScheduleReport(Timeout timeout, ReadHandlerNode * node, const Timestamp & now)
{
// Cancel Report if it is currently scheduled
mTimerDelegate->CancelTimer(node);
Expand Down Expand Up @@ -153,26 +153,26 @@ bool ReportSchedulerImpl::IsReportScheduled(ReadHandler * aReadHandler)
return mTimerDelegate->IsTimerActive(node);
}

CHIP_ERROR ReportSchedulerImpl::CalculateNextReportTimeout(Timeout & timeout, ReadHandlerNode * aNode)
CHIP_ERROR ReportSchedulerImpl::CalculateNextReportTimeout(Timeout & timeout, ReadHandlerNode * aNode, const Timestamp & now)
{
VerifyOrReturnError(nullptr != FindReadHandlerNode(aNode->GetReadHandler()), CHIP_ERROR_INVALID_ARGUMENT);

// If the handler is reportable now, just schedule a report immediately
if (aNode->IsReportableNow(mNow))
if (aNode->IsReportableNow(now))
{
// If the handler is reportable now, just schedule a report immediately
timeout = Milliseconds32(0);
}
else if (IsReadHandlerReportable(aNode->GetReadHandler()) && (aNode->GetMinTimestamp() > mNow))
else if (IsReadHandlerReportable(aNode->GetReadHandler()) && (aNode->GetMinTimestamp() > now))
{
// If the handler is reportable now, but the min interval is not elapsed, schedule a report for the moment the min interval
// has elapsed
timeout = aNode->GetMinTimestamp() - mNow;
timeout = aNode->GetMinTimestamp() - now;
}
else
{
// If the handler is not reportable now, schedule a report for the max interval
timeout = aNode->GetMaxTimestamp() - mNow;
timeout = aNode->GetMaxTimestamp() - now;
}
return CHIP_NO_ERROR;
}
Expand Down
4 changes: 2 additions & 2 deletions src/app/reporting/ReportSchedulerImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,14 @@ class ReportSchedulerImpl : public ReportScheduler
void ReportTimerCallback() override;

protected:
virtual CHIP_ERROR ScheduleReport(Timeout timeout, ReadHandlerNode * node);
virtual CHIP_ERROR ScheduleReport(Timeout timeout, ReadHandlerNode * node, const Timestamp & now);
void CancelReport(ReadHandler * aReadHandler);
virtual void UnregisterAllHandlers();

private:
friend class chip::app::reporting::TestReportScheduler;

virtual CHIP_ERROR CalculateNextReportTimeout(Timeout & timeout, ReadHandlerNode * aNode);
virtual CHIP_ERROR CalculateNextReportTimeout(Timeout & timeout, ReadHandlerNode * aNode, const Timestamp & now);
};

} // namespace reporting
Expand Down
43 changes: 22 additions & 21 deletions src/app/reporting/SynchronizedReportSchedulerImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ void SynchronizedReportSchedulerImpl::OnReadHandlerDestroyed(ReadHandler * aRead
}
}

CHIP_ERROR SynchronizedReportSchedulerImpl::ScheduleReport(Timeout timeout, ReadHandlerNode * node)
CHIP_ERROR SynchronizedReportSchedulerImpl::ScheduleReport(Timeout timeout, ReadHandlerNode * node, const Timestamp & now)
{
// Cancel Report if it is currently scheduled
mTimerDelegate->CancelTimer(this);
Expand All @@ -54,7 +54,7 @@ CHIP_ERROR SynchronizedReportSchedulerImpl::ScheduleReport(Timeout timeout, Read
return CHIP_NO_ERROR;
}
ReturnErrorOnFailure(mTimerDelegate->StartTimer(this, timeout));
mTestNextReportTimestamp = mNow + timeout;
mTestNextReportTimestamp = now + timeout;

return CHIP_NO_ERROR;
}
Expand All @@ -73,13 +73,13 @@ bool SynchronizedReportSchedulerImpl::IsReportScheduled()

/// @brief Find the smallest maximum interval possible and set it as the common maximum
/// @return NO_ERROR if the smallest maximum interval was found, error otherwise, INVALID LIST LENGTH if the list is empty
CHIP_ERROR SynchronizedReportSchedulerImpl::FindNextMaxInterval()
CHIP_ERROR SynchronizedReportSchedulerImpl::FindNextMaxInterval(const Timestamp & now)
{
VerifyOrReturnError(mNodesPool.Allocated(), CHIP_ERROR_INVALID_LIST_LENGTH);
System::Clock::Timestamp earliest = mNow + Seconds16::max();
System::Clock::Timestamp earliest = now + Seconds16::max();

mNodesPool.ForEachActiveObject([&earliest, this](ReadHandlerNode * node) {
if (node->GetMaxTimestamp() < earliest && node->GetMaxTimestamp() > this->mNow)
mNodesPool.ForEachActiveObject([&earliest, now](ReadHandlerNode * node) {
if (node->GetMaxTimestamp() < earliest && node->GetMaxTimestamp() > now)
{
earliest = node->GetMaxTimestamp();
}
Expand All @@ -96,10 +96,10 @@ CHIP_ERROR SynchronizedReportSchedulerImpl::FindNextMaxInterval()
/// minimum. If the max timestamp has not been updated and is in the past, or if no min timestamp is lower than the current max
/// timestamp, this will set now as the common minimum timestamp, thus allowing the report to be sent immediately.
/// @return NO_ERROR if the highest minimum timestamp was found, error otherwise, INVALID LIST LENGTH if the list is empty
CHIP_ERROR SynchronizedReportSchedulerImpl::FindNextMinInterval()
CHIP_ERROR SynchronizedReportSchedulerImpl::FindNextMinInterval(const Timestamp & now)
{
VerifyOrReturnError(mNodesPool.Allocated(), CHIP_ERROR_INVALID_LIST_LENGTH);
System::Clock::Timestamp latest = mNow;
System::Clock::Timestamp latest = now;

mNodesPool.ForEachActiveObject([&latest, this](ReadHandlerNode * node) {
if (node->GetMinTimestamp() > latest && this->IsReadHandlerReportable(node->GetReadHandler()) &&
Expand All @@ -117,18 +117,19 @@ CHIP_ERROR SynchronizedReportSchedulerImpl::FindNextMinInterval()
return CHIP_NO_ERROR;
}

CHIP_ERROR SynchronizedReportSchedulerImpl::CalculateNextReportTimeout(Timeout & timeout, ReadHandlerNode * aNode)
CHIP_ERROR SynchronizedReportSchedulerImpl::CalculateNextReportTimeout(Timeout & timeout, ReadHandlerNode * aNode,
const Timestamp & now)
{
VerifyOrReturnError(nullptr != FindReadHandlerNode(aNode->GetReadHandler()), CHIP_ERROR_INVALID_ARGUMENT);
ReturnErrorOnFailure(FindNextMaxInterval());
ReturnErrorOnFailure(FindNextMinInterval());
ReturnErrorOnFailure(FindNextMaxInterval(now));
ReturnErrorOnFailure(FindNextMinInterval(now));
bool reportableNow = false;
bool reportableAtMin = false;

mNodesPool.ForEachActiveObject([&reportableNow, &reportableAtMin, this](ReadHandlerNode * node) {
mNodesPool.ForEachActiveObject([&reportableNow, &reportableAtMin, this, now](ReadHandlerNode * node) {
if (!node->IsEngineRunScheduled())
{
if (node->IsReportableNow(mNow))
if (node->IsReportableNow(now))
{
reportableNow = true;
return Loop::Break;
Expand All @@ -151,21 +152,21 @@ CHIP_ERROR SynchronizedReportSchedulerImpl::CalculateNextReportTimeout(Timeout &
}
else if (reportableAtMin)
{
timeout = mNextMinTimestamp - mNow;
timeout = mNextMinTimestamp - now;
}
else
{
// Schedule report at next max otherwise
timeout = mNextMaxTimestamp - mNow;
timeout = mNextMaxTimestamp - now;
}

// Updates the synching time of each handler
mNodesPool.ForEachActiveObject([this, timeout](ReadHandlerNode * node) {
mNodesPool.ForEachActiveObject([now, timeout](ReadHandlerNode * node) {
// Prevent modifying the sync if the handler is currently reportable, sync's purpose is to allow handler to become
// reportable earlier than their max interval
if (!node->IsReportableNow(this->mNow))
if (!node->IsReportableNow(now))
{
node->SetSyncTimestamp(Milliseconds64(this->mNow + timeout));
node->SetSyncTimestamp(Milliseconds64(now + timeout));
}

return Loop::Continue;
Expand All @@ -179,12 +180,12 @@ CHIP_ERROR SynchronizedReportSchedulerImpl::CalculateNextReportTimeout(Timeout &
void SynchronizedReportSchedulerImpl::TimerFired()
{
// Update the current time to validate reportability upon current time
mNow = mTimerDelegate->GetCurrentMonotonicTimestamp();
Timestamp now = mTimerDelegate->GetCurrentMonotonicTimestamp();

InteractionModelEngine::GetInstance()->GetReportingEngine().ScheduleRun();

mNodesPool.ForEachActiveObject([this](ReadHandlerNode * node) {
if (node->IsReportableNow(this->mNow))
mNodesPool.ForEachActiveObject([now](ReadHandlerNode * node) {
if (node->IsReportableNow(now))
{
node->SetEngineRunScheduled(true);
ChipLogProgress(DataManagement, "Handler: %p with min: %" PRIu64 " and max: %" PRIu64 " and sync: %" PRIu64, (node),
Expand Down
8 changes: 4 additions & 4 deletions src/app/reporting/SynchronizedReportSchedulerImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,15 @@ class SynchronizedReportSchedulerImpl : public ReportSchedulerImpl, public Timer
void TimerFired() override;

protected:
CHIP_ERROR ScheduleReport(System::Clock::Timeout timeout, ReadHandlerNode * node) override;
CHIP_ERROR ScheduleReport(System::Clock::Timeout timeout, ReadHandlerNode * node, const Timestamp & now) override;
void CancelReport();

private:
friend class chip::app::reporting::TestReportScheduler;

CHIP_ERROR FindNextMinInterval();
CHIP_ERROR FindNextMaxInterval();
CHIP_ERROR CalculateNextReportTimeout(Timeout & timeout, ReadHandlerNode * aReadHandlerNode) override;
CHIP_ERROR FindNextMinInterval(const Timestamp & now);
CHIP_ERROR FindNextMaxInterval(const Timestamp & now);
CHIP_ERROR CalculateNextReportTimeout(Timeout & timeout, ReadHandlerNode * aReadHandlerNode, const Timestamp & now) override;

Timestamp mNextMaxTimestamp = Milliseconds64(0);
Timestamp mNextMinTimestamp = Milliseconds64(0);
Expand Down

0 comments on commit 88dea90

Please sign in to comment.