/* * * 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 // Include local headers #include #include #include #include #include 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