| /* |
| * |
| * 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 |