blob: 3612b9c10461e2f360c4c4ea9e08fed4d2ec9975 [file] [log] [blame]
/*
*
* Copyright (c) 2020-2021 Project CHIP Authors
* Copyright (c) 2016-2017 Nest Labs, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file
* This file defines the member functions and private data for
* the chip::System::Timer class, which is used for
* representing an in-progress one-shot timer.
*/
// Include module header
#include <system/SystemTimer.h>
// Include local headers
#include <string.h>
#include <system/SystemError.h>
#include <system/SystemFaultInjection.h>
#include <system/SystemLayer.h>
#include <lib/support/CodeUtils.h>
namespace chip {
namespace System {
TimerList::Node * TimerList::Add(TimerList::Node * add)
{
VerifyOrDie(add != mEarliestTimer);
if (mEarliestTimer == nullptr || (add->AwakenTime() < mEarliestTimer->AwakenTime()))
{
add->mNextTimer = mEarliestTimer;
mEarliestTimer = add;
}
else
{
TimerList::Node * lTimer = mEarliestTimer;
while (lTimer->mNextTimer)
{
VerifyOrDie(lTimer->mNextTimer != add);
if (add->AwakenTime() < lTimer->mNextTimer->AwakenTime())
{
// found the insert location.
break;
}
lTimer = lTimer->mNextTimer;
}
add->mNextTimer = lTimer->mNextTimer;
lTimer->mNextTimer = add;
}
return mEarliestTimer;
}
TimerList::Node * TimerList::Remove(TimerList::Node * remove)
{
if (mEarliestTimer != nullptr && remove != nullptr)
{
if (remove == mEarliestTimer)
{
mEarliestTimer = remove->mNextTimer;
}
else
{
TimerList::Node * lTimer = mEarliestTimer;
while (lTimer->mNextTimer)
{
if (remove == lTimer->mNextTimer)
{
lTimer->mNextTimer = remove->mNextTimer;
break;
}
lTimer = lTimer->mNextTimer;
}
}
remove->mNextTimer = nullptr;
}
return mEarliestTimer;
}
TimerList::Node * TimerList::Remove(TimerCompleteCallback aOnComplete, void * aAppState)
{
TimerList::Node * previous = nullptr;
for (TimerList::Node * timer = mEarliestTimer; timer != nullptr; timer = timer->mNextTimer)
{
if (timer->GetCallback().GetOnComplete() == aOnComplete && timer->GetCallback().GetAppState() == aAppState)
{
if (previous == nullptr)
{
mEarliestTimer = timer->mNextTimer;
}
else
{
previous->mNextTimer = timer->mNextTimer;
}
timer->mNextTimer = nullptr;
return timer;
}
previous = timer;
}
return nullptr;
}
TimerList::Node * TimerList::PopEarliest()
{
if (mEarliestTimer == nullptr)
{
return nullptr;
}
TimerList::Node * earliest = mEarliestTimer;
mEarliestTimer = mEarliestTimer->mNextTimer;
earliest->mNextTimer = nullptr;
return earliest;
}
TimerList::Node * TimerList::PopIfEarlier(Clock::Timestamp t)
{
if ((mEarliestTimer == nullptr) || !(mEarliestTimer->AwakenTime() < t))
{
return nullptr;
}
TimerList::Node * earliest = mEarliestTimer;
mEarliestTimer = mEarliestTimer->mNextTimer;
earliest->mNextTimer = nullptr;
return earliest;
}
TimerList TimerList::ExtractEarlier(Clock::Timestamp t)
{
TimerList out;
if ((mEarliestTimer != nullptr) && (mEarliestTimer->AwakenTime() < t))
{
out.mEarliestTimer = mEarliestTimer;
TimerList::Node * end = mEarliestTimer;
while ((end->mNextTimer != nullptr) && (end->mNextTimer->AwakenTime() < t))
{
end = end->mNextTimer;
}
mEarliestTimer = end->mNextTimer;
end->mNextTimer = nullptr;
}
return out;
}
Clock::Timeout TimerList::GetRemainingTime(TimerCompleteCallback aOnComplete, void * aAppState)
{
for (TimerList::Node * timer = mEarliestTimer; timer != nullptr; timer = timer->mNextTimer)
{
if (timer->GetCallback().GetOnComplete() == aOnComplete && timer->GetCallback().GetAppState() == aAppState)
{
Clock::Timestamp currentTime = SystemClock().GetMonotonicTimestamp();
if (currentTime < timer->AwakenTime())
{
return Clock::Timeout(timer->AwakenTime() - currentTime);
}
return Clock::kZero;
}
}
return Clock::kZero;
}
} // namespace System
} // namespace chip