[time] introduce common ExpirationChecker class (#11883)

This commit introduces a new common helper class `ExpirationChecker`.

This class is designed to be used as a "matcher" for finding expired
entries in collections like `LinkedList` or `Array`. It encapsulates
a "now" time and provides an `IsExpired()` method to check if a given
time has passed.

This change consolidates duplicated private similar structs that
previously existed in `RoutingManager`, `Mdns`, and
`SrpAdvertisingProxy`, updating all users to the new common
implementation. This simplifies the code by removing redundancy.
This commit is contained in:
Abtin Keshavarzian
2025-08-29 18:20:13 -07:00
committed by GitHub
parent 83272e7eae
commit 269268fbf6
6 changed files with 81 additions and 71 deletions
+2 -8
View File
@@ -812,12 +812,6 @@ private:
//------------------------------------------------------------------------------------------------------------------
// Nested types
struct ExpirationChecker
{
explicit ExpirationChecker(TimeMilli aNow) { mNow = aNow; }
TimeMilli mNow;
};
class LifetimedPrefix
{
// Represents an IPv6 prefix with its valid lifetime. Used as
@@ -831,7 +825,7 @@ private:
TimeMilli GetExpireTime(void) const { return CalculateExpirationTime(mValidLifetime); }
bool Matches(const Ip6::Prefix &aPrefix) const { return (mPrefix == aPrefix); }
bool Matches(const ExpirationChecker &aChecker) const { return (GetExpireTime() <= aChecker.mNow); }
bool Matches(const ExpirationChecker &aChecker) const { return aChecker.IsExpired(GetExpireTime()); }
void SetStaleTimeCalculated(bool aFlag) { mStaleTimeCalculated = aFlag; }
bool IsStaleTimeCalculated(void) const { return mStaleTimeCalculated; }
@@ -903,7 +897,7 @@ private:
void CopyInfoTo(RdnssAddrEntry &aEntry, TimeMilli aNow) const;
bool Matches(const Ip6::Address &aAddress) const { return (mAddress == aAddress); }
bool Matches(const ExpirationChecker &aChecker) const { return (GetExpireTime() <= aChecker.mNow); }
bool Matches(const ExpirationChecker &aChecker) const { return aChecker.IsExpired(GetExpireTime()); }
private:
Ip6::Address mAddress;
+43 -1
View File
@@ -60,6 +60,48 @@ namespace ot {
* @{
*/
/**
* Represents an Expiration Checker to determine if a given time has expired relative to a fixed "current time".
*
* This type is typically used as a "matcher", e.g., as an input to the `Matches(const ExpirationChecker &aChecker)`
* method on various `Entry` object types (which can be stored in collections like `LinkedList`, `Array`, etc.).
* The `Matches()` method checks whether a given entry has expired. This is then used with methods like
* `FindMatching()`, `RemoveMatching()`, `RemoveAndFreeAllMatching()` to efficiently find and remove expired entries
* from a collection.
*/
class ExpirationChecker
{
public:
/**
* Initializes the `ExpirationChecker` with a given current time.
*
* @param[in] aNow The current time.
*/
explicit ExpirationChecker(Time aNow) { mNow = aNow; }
/**
* Gets the current time (now) tracked by the `ExpirationChecker`.
*
* @returns The current time.
*/
Time GetNow(void) const { return mNow; }
/**
* Indicates whether or not a given time is considered expired.
*
* A time is considered expired if it is before (or same) as the current time tracked by `ExpirationChecker`.
*
* @param[in] aTime The time to check against the checker's reference current time.
*
* @retval TRUE If @p aTime is expired (is in the past or now).
* @retval FALSE If @p aTime is not expired (is in the future).
*/
bool IsExpired(Time aTime) const { return aTime <= mNow; }
private:
Time mNow;
};
/**
* Represents an object tracking the next fire time along with the current time (now).
*/
@@ -69,7 +111,7 @@ public:
/**
* Initializes the `NextFireTime` with a given current time.
*
* @pram[in] aNow The current time.
* @param[in] aNow The current time.
*/
explicit NextFireTime(Time aNow);
+24 -29
View File
@@ -4882,7 +4882,7 @@ void Core::MultiPacketRxMessages::HandleTimer(void)
NextFireTime nextTime;
OwningList<RxMsgEntry> expiredEntries;
mRxMsgEntries.RemoveAllMatching(expiredEntries, ExpireChecker(nextTime.GetNow()));
mRxMsgEntries.RemoveAllMatching(expiredEntries, ExpirationChecker(nextTime.GetNow()));
for (RxMsgEntry &expiredEntry : expiredEntries)
{
@@ -4923,11 +4923,6 @@ exit:
return matches;
}
bool Core::MultiPacketRxMessages::RxMsgEntry::Matches(const ExpireChecker &aExpireChecker) const
{
return (mProcessTime <= aExpireChecker.mNow);
}
void Core::MultiPacketRxMessages::RxMsgEntry::Add(OwnedPtr<RxMessage> &aRxMessagePtr)
{
uint16_t numMsgs = 0;
@@ -5024,7 +5019,7 @@ void Core::TxMessageHistory::HandleTimer(void)
{
NextFireTime nextTime;
mMsgEntries.RemoveAndFreeAllMatching(ExpireChecker(nextTime.GetNow()));
mMsgEntries.RemoveAndFreeAllMatching(ExpirationChecker(nextTime.GetNow()));
for (const MsgEntry &entry : mMsgEntries)
{
@@ -5170,17 +5165,17 @@ void Core::AddPassiveIp6AddrCache(const char *aHostName)
void Core::HandleCacheTimer(void)
{
CacheContext context(GetInstance());
ExpireChecker expireChecker(context.GetNow());
CacheContext context(GetInstance());
ExpirationChecker expirationChecker(context.GetNow());
// First remove all expired entries.
mBrowseCacheList.RemoveAndFreeAllMatching(expireChecker);
mSrvCacheList.RemoveAndFreeAllMatching(expireChecker);
mTxtCacheList.RemoveAndFreeAllMatching(expireChecker);
mIp6AddrCacheList.RemoveAndFreeAllMatching(expireChecker);
mIp4AddrCacheList.RemoveAndFreeAllMatching(expireChecker);
mRecordCacheList.RemoveAndFreeAllMatching(expireChecker);
mBrowseCacheList.RemoveAndFreeAllMatching(expirationChecker);
mSrvCacheList.RemoveAndFreeAllMatching(expirationChecker);
mTxtCacheList.RemoveAndFreeAllMatching(expirationChecker);
mIp6AddrCacheList.RemoveAndFreeAllMatching(expirationChecker);
mIp4AddrCacheList.RemoveAndFreeAllMatching(expirationChecker);
mRecordCacheList.RemoveAndFreeAllMatching(expirationChecker);
// Process cache types in a specific order to optimize name
// compression when constructing query messages.
@@ -5941,7 +5936,7 @@ bool Core::BrowseCache::Matches(const Browser &aBrowser) const
return Matches(aBrowser.mServiceType, aBrowser.mSubTypeLabel);
}
bool Core::BrowseCache::Matches(const ExpireChecker &aExpireChecker) const { return ShouldDelete(aExpireChecker.mNow); }
bool Core::BrowseCache::Matches(const ExpirationChecker &aChecker) const { return ShouldDelete(aChecker.GetNow()); }
Error Core::BrowseCache::Add(const Browser &aBrowser) { return CacheEntry::Add(ResultCallback(aBrowser.mCallback)); }
@@ -6134,7 +6129,7 @@ void Core::BrowseCache::ProcessExpiredRecords(TimeMilli aNow)
{
OwningList<PtrEntry> expiredEntries;
mPtrEntries.RemoveAllMatching(expiredEntries, ExpireChecker(aNow));
mPtrEntries.RemoveAllMatching(expiredEntries, ExpirationChecker(aNow));
for (PtrEntry &exiredEntry : expiredEntries)
{
@@ -6185,9 +6180,9 @@ Error Core::BrowseCache::PtrEntry::Init(const char *aServiceInstance)
return mServiceInstance.Set(aServiceInstance);
}
bool Core::BrowseCache::PtrEntry::Matches(const ExpireChecker &aExpireChecker) const
bool Core::BrowseCache::PtrEntry::Matches(const ExpirationChecker &aChecker) const
{
return mRecord.ShouldExpire(aExpireChecker.mNow);
return mRecord.ShouldExpire(aChecker.GetNow());
}
void Core::BrowseCache::PtrEntry::ConvertTo(BrowseResult &aResult, const BrowseCache &aBrowseCache) const
@@ -6311,7 +6306,7 @@ bool Core::SrvCache::Matches(const SrvResolver &aResolver) const
return ServiceCache::Matches(aResolver.mServiceInstance, aResolver.mServiceType);
}
bool Core::SrvCache::Matches(const ExpireChecker &aExpireChecker) const { return ShouldDelete(aExpireChecker.mNow); }
bool Core::SrvCache::Matches(const ExpirationChecker &aChecker) const { return ShouldDelete(aChecker.GetNow()); }
Error Core::SrvCache::Add(const SrvResolver &aResolver) { return CacheEntry::Add(ResultCallback(aResolver.mCallback)); }
@@ -6509,7 +6504,7 @@ bool Core::TxtCache::Matches(const TxtResolver &aResolver) const
return ServiceCache::Matches(aResolver.mServiceInstance, aResolver.mServiceType);
}
bool Core::TxtCache::Matches(const ExpireChecker &aExpireChecker) const { return ShouldDelete(aExpireChecker.mNow); }
bool Core::TxtCache::Matches(const ExpirationChecker &aChecker) const { return ShouldDelete(aChecker.GetNow()); }
Error Core::TxtCache::Add(const TxtResolver &aResolver) { return CacheEntry::Add(ResultCallback(aResolver.mCallback)); }
@@ -6689,7 +6684,7 @@ bool Core::AddrCache::Matches(const char *aName) const { return NameMatch(mName,
bool Core::AddrCache::Matches(const AddressResolver &aResolver) const { return Matches(aResolver.mHostName); }
bool Core::AddrCache::Matches(const ExpireChecker &aExpireChecker) const { return ShouldDelete(aExpireChecker.mNow); }
bool Core::AddrCache::Matches(const ExpirationChecker &aChecker) const { return ShouldDelete(aChecker.GetNow()); }
Error Core::AddrCache::Add(const AddressResolver &aResolver)
{
@@ -6751,7 +6746,7 @@ void Core::AddrCache::ProcessExpiredRecords(TimeMilli aNow)
AddressResult result;
bool didRemoveAny;
didRemoveAny = mCommittedEntries.RemoveAndFreeAllMatching(ExpireChecker(aNow));
didRemoveAny = mCommittedEntries.RemoveAndFreeAllMatching(ExpirationChecker(aNow));
VerifyOrExit(didRemoveAny);
@@ -7010,9 +7005,9 @@ Core::AddrCache::AddrEntry::AddrEntry(const Ip6::Address &aAddress)
{
}
bool Core::AddrCache::AddrEntry::Matches(const ExpireChecker &aExpireChecker) const
bool Core::AddrCache::AddrEntry::Matches(const ExpirationChecker &aChecker) const
{
return mRecord.ShouldExpire(aExpireChecker.mNow);
return mRecord.ShouldExpire(aChecker.GetNow());
}
bool Core::AddrCache::AddrEntry::Matches(EmptyChecker aChecker) const
@@ -7135,7 +7130,7 @@ exit:
return matches;
}
bool Core::RecordCache::Matches(const ExpireChecker &aExpireChecker) const { return ShouldDelete(aExpireChecker.mNow); }
bool Core::RecordCache::Matches(const ExpirationChecker &aChecker) const { return ShouldDelete(aChecker.GetNow()); }
Error Core::RecordCache::Add(const RecordQuerier &aQuerier)
{
@@ -7379,7 +7374,7 @@ void Core::RecordCache::ProcessExpiredRecords(TimeMilli aNow)
{
OwningList<RecordEntry> expiredEntries;
mCommittedEntries.RemoveAllMatching(expiredEntries, ExpireChecker(aNow));
mCommittedEntries.RemoveAllMatching(expiredEntries, ExpirationChecker(aNow));
for (RecordEntry &entry : expiredEntries)
{
@@ -7484,9 +7479,9 @@ bool Core::RecordCache::RecordEntry::Matches(uint16_t aType, const Heap::Data &a
return (mType == aType) && (mData == aData);
}
bool Core::RecordCache::RecordEntry::Matches(const ExpireChecker &aExpireChecker) const
bool Core::RecordCache::RecordEntry::Matches(const ExpirationChecker &aChecker) const
{
return mRecord.ShouldExpire(aExpireChecker.mNow);
return mRecord.ShouldExpire(aChecker.GetNow());
}
bool Core::RecordCache::RecordEntry::Matches(EmptyChecker aChecker) const
+10 -21
View File
@@ -963,17 +963,6 @@ private:
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
struct ExpireChecker
{
// Used in `Matches()` to find expired entries in a list.
explicit ExpireChecker(TimeMilli aNow) { mNow = aNow; }
TimeMilli mNow;
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
class Callback : public Clearable<Callback>
{
public:
@@ -1658,7 +1647,7 @@ private:
explicit RxMsgEntry(Instance &aInstance);
bool Matches(const AddressInfo &aAddress) const;
bool Matches(const ExpireChecker &aExpireChecker) const;
bool Matches(const ExpirationChecker &aChecker) const { return aChecker.IsExpired(mProcessTime); }
void Add(OwnedPtr<RxMessage> &aRxMessagePtr);
OwningList<RxMessage> mRxMessages;
@@ -1703,7 +1692,7 @@ private:
struct MsgEntry : public LinkedListEntry<MsgEntry>, public Heap::Allocatable<MsgEntry>
{
bool Matches(const MsgInfo &aInfo) const { return mInfo == aInfo; }
bool Matches(const ExpireChecker &aExpireChecker) const { return mExpireTime <= aExpireChecker.mNow; }
bool Matches(const ExpirationChecker &aChecker) const { return aChecker.IsExpired(mExpireTime); }
MsgEntry *mNext;
MsgInfo mInfo;
@@ -1897,7 +1886,7 @@ private:
bool Matches(const Name &aFullName) const;
bool Matches(const char *aServiceType, const char *aSubTypeLabel) const;
bool Matches(const Browser &aBrowser) const;
bool Matches(const ExpireChecker &aExpireChecker) const;
bool Matches(const ExpirationChecker &aChecker) const;
Error Add(const Browser &aBrowser);
void Remove(const Browser &aBrowser);
void ProcessResponseRecord(const Message &aMessage, uint16_t aRecordOffset);
@@ -1910,7 +1899,7 @@ private:
{
Error Init(const char *aServiceInstance);
bool Matches(const char *aServiceInstance) const { return NameMatch(mServiceInstance, aServiceInstance); }
bool Matches(const ExpireChecker &aExpireChecker) const;
bool Matches(const ExpirationChecker &aChecker) const;
void ConvertTo(BrowseResult &aResult, const BrowseCache &aBrowseCache) const;
PtrEntry *mNext;
@@ -2000,7 +1989,7 @@ private:
bool Matches(const Name &aFullName) const;
bool Matches(const SrvResolver &aResolver) const;
bool Matches(const ServiceName &aServiceName) const;
bool Matches(const ExpireChecker &aExpireChecker) const;
bool Matches(const ExpirationChecker &aChecker) const;
Error Add(const SrvResolver &aResolver);
void Remove(const SrvResolver &aResolver);
void ProcessResponseRecord(const Message &aMessage, uint16_t aRecordOffset);
@@ -2038,7 +2027,7 @@ private:
bool Matches(const Name &aFullName) const;
bool Matches(const TxtResolver &aResolver) const;
bool Matches(const ServiceName &aServiceName) const;
bool Matches(const ExpireChecker &aExpireChecker) const;
bool Matches(const ExpirationChecker &aChecker) const;
Error Add(const TxtResolver &aResolver);
void Remove(const TxtResolver &aResolver);
void ProcessResponseRecord(const Message &aMessage, uint16_t aRecordOffset);
@@ -2073,7 +2062,7 @@ private:
bool Matches(const Name &aFullName) const;
bool Matches(const char *aName) const;
bool Matches(const AddressResolver &aResolver) const;
bool Matches(const ExpireChecker &aExpireChecker) const;
bool Matches(const ExpirationChecker &aChecker) const;
Error Add(const AddressResolver &aResolver);
void Remove(const AddressResolver &aResolver);
void CommitNewResponseEntries(void);
@@ -2086,7 +2075,7 @@ private:
{
explicit AddrEntry(const Ip6::Address &aAddress);
bool Matches(const Ip6::Address &aAddress) const { return (mAddress == aAddress); }
bool Matches(const ExpireChecker &aExpireChecker) const;
bool Matches(const ExpirationChecker &aChecker) const;
bool Matches(EmptyChecker aChecker) const;
uint32_t GetTtl(void) const { return mRecord.GetTtl(); }
@@ -2161,7 +2150,7 @@ private:
public:
bool Matches(const Name &aFullName, uint16_t aRecordType) const;
bool Matches(const RecordQuerier &aQuerier) const;
bool Matches(const ExpireChecker &aExpireChecker) const;
bool Matches(const ExpirationChecker &aChecker) const;
Error Add(const RecordQuerier &aQuerier);
void Remove(const RecordQuerier &aQuerier);
void ProcessResponseRecord(const Message &aMessage, const ResourceRecord &aRecord, uint16_t aRecordOffset);
@@ -2191,7 +2180,7 @@ private:
bool Matches(uint16_t aType) const;
bool Matches(uint16_t aType, const Heap::Data &aData) const;
bool Matches(const ExpireChecker &aExpireChecker) const;
bool Matches(const ExpirationChecker &aChecker) const;
bool Matches(EmptyChecker aChecker) const;
uint32_t GetTtl(void) const { return mRecord.GetTtl(); }
+1 -1
View File
@@ -1252,7 +1252,7 @@ void AdvertisingProxy::HandleTimer(void)
VerifyOrExit(mState == kStateRunning);
mAdvInfoList.RemoveAllMatching(expiredList, AdvInfo::ExpirationChecker(nextTime.GetNow()));
mAdvInfoList.RemoveAllMatching(expiredList, ExpirationChecker(nextTime.GetNow()));
for (AdvInfo &adv : mAdvInfoList)
{
+1 -11
View File
@@ -223,21 +223,11 @@ private:
// completed (successfully or failed).
};
struct ExpirationChecker
{
explicit ExpirationChecker(TimeMilli aNow)
: mNow(aNow)
{
}
TimeMilli mNow;
};
AdvInfo(Host &aHost, const Server::MessageMetadata &aMetadata, uint32_t aTimeout);
void SignalServerToCommit(void);
bool IsCompleted(void) const;
bool Matches(const CompletionChecker &) const { return IsCompleted(); }
bool Matches(const ExpirationChecker &aChecker) const { return (mExpireTime <= aChecker.mNow); }
bool Matches(const ExpirationChecker &aChecker) const { return aChecker.IsExpired(mExpireTime); }
Instance &GetInstance(void) const { return mHost.GetInstance(); }
AdvInfo *mNext;