[owning-list] add RemoveAndFreeAllMatching() to OwningList class (#10210)

This commit introduces a new method, `RemoveAndFreeAllMatching()`, to
the `OwningList<Type>` class. This method removes and frees all
entries in the list that match a given indicator. This is used to
simplify the native mDNS implementation. The unit test
`test_linked_list` is also updated to validate the newly added helper
method.
This commit is contained in:
Abtin Keshavarzian
2024-05-08 11:32:42 -07:00
committed by GitHub
parent 00f7c3131b
commit 226f239c5d
3 changed files with 79 additions and 36 deletions
+23
View File
@@ -149,6 +149,29 @@ public:
{ {
LinkedList<Type>::RemoveAllMatching(aIndicator, aRemovedList); LinkedList<Type>::RemoveAllMatching(aIndicator, aRemovedList);
} }
/**
* Removes and frees all entries in the list matching a given entry indicator.
*
* The template type `Indicator` specifies the type of @p aIndicator object which is used to match against entries
* in the list. To check that an entry matches the given indicator, the `Matches()` method is invoked on each
* `Type` entry in the list. The `Matches()` method should be provided by `Type` class accordingly:
*
* bool Type::Matches(const Indicator &aIndicator) const
*
* @param[in] aIndicator An entry indicator to match against entries in the list.
*
* @retval TRUE At least one matching entry was removed.
* @retval FALSE No matching entry was found.
*
*/
template <typename Indicator> bool RemoveAndFreeAllMatching(const Indicator &aIndicator)
{
OwningList removedList;
RemoveAllMatching(aIndicator, removedList);
return !removedList.IsEmpty();
}
}; };
} // namespace ot } // namespace ot
+19 -36
View File
@@ -313,11 +313,8 @@ void Core::HandleEntryTimer(void)
void Core::RemoveEmptyEntries(void) void Core::RemoveEmptyEntries(void)
{ {
OwningList<HostEntry> removedHosts; mHostEntries.RemoveAndFreeAllMatching(Entry::kRemoving);
OwningList<ServiceEntry> removedServices; mServiceEntries.RemoveAndFreeAllMatching(Entry::kRemoving);
mHostEntries.RemoveAllMatching(Entry::kRemoving, removedHosts);
mServiceEntries.RemoveAllMatching(Entry::kRemoving, removedServices);
} }
void Core::HandleEntryTask(void) void Core::HandleEntryTask(void)
@@ -1874,9 +1871,7 @@ void Core::ServiceEntry::ClearService(void)
void Core::ServiceEntry::ScheduleToRemoveIfEmpty(void) void Core::ServiceEntry::ScheduleToRemoveIfEmpty(void)
{ {
OwningList<SubType> removedSubTypes; mSubTypes.RemoveAndFreeAllMatching(EmptyChecker());
mSubTypes.RemoveAllMatching(EmptyChecker(), removedSubTypes);
if (IsEmpty()) if (IsEmpty())
{ {
@@ -2149,8 +2144,6 @@ void Core::ServiceEntry::PrepareResponseRecords(TxMessage &aResponse, TimeMilli
void Core::ServiceEntry::UpdateRecordsState(const TxMessage &aResponse) void Core::ServiceEntry::UpdateRecordsState(const TxMessage &aResponse)
{ {
OwningList<SubType> removedSubTypes;
Entry::UpdateRecordsState(aResponse); Entry::UpdateRecordsState(aResponse);
mPtrRecord.UpdateStateAfterAnswer(aResponse); mPtrRecord.UpdateStateAfterAnswer(aResponse);
@@ -2162,7 +2155,7 @@ void Core::ServiceEntry::UpdateRecordsState(const TxMessage &aResponse)
subType.mPtrRecord.UpdateStateAfterAnswer(aResponse); subType.mPtrRecord.UpdateStateAfterAnswer(aResponse);
} }
mSubTypes.RemoveAllMatching(EmptyChecker(), removedSubTypes); mSubTypes.RemoveAndFreeAllMatching(EmptyChecker());
if (IsEmpty()) if (IsEmpty())
{ {
@@ -4142,11 +4135,10 @@ void Core::TxMessageHistory::CalculateHash(const Message &aMessage, Hash &aHash)
void Core::TxMessageHistory::HandleTimer(void) void Core::TxMessageHistory::HandleTimer(void)
{ {
TimeMilli now = TimerMilli::GetNow(); TimeMilli now = TimerMilli::GetNow();
TimeMilli nextTime = now.GetDistantFuture(); TimeMilli nextTime = now.GetDistantFuture();
OwningList<HashEntry> expiredEntries;
mHashEntries.RemoveAllMatching(ExpireChecker(now), expiredEntries); mHashEntries.RemoveAndFreeAllMatching(ExpireChecker(now));
for (const HashEntry &entry : mHashEntries) for (const HashEntry &entry : mHashEntries)
{ {
@@ -4268,21 +4260,16 @@ void Core::AddPassiveIp6AddrCache(const char *aHostName)
void Core::HandleCacheTimer(void) void Core::HandleCacheTimer(void)
{ {
CacheTimerContext context(GetInstance()); CacheTimerContext context(GetInstance());
ExpireChecker expireChecker(context.GetNow()); ExpireChecker expireChecker(context.GetNow());
OwningList<BrowseCache> expiredBrowseList;
OwningList<SrvCache> expiredSrvList;
OwningList<TxtCache> expiredTxtList;
OwningList<Ip6AddrCache> expiredIp6AddrList;
OwningList<Ip4AddrCache> expiredIp4AddrList;
// First remove all expired entries. // First remove all expired entries.
mBrowseCacheList.RemoveAllMatching(expireChecker, expiredBrowseList); mBrowseCacheList.RemoveAndFreeAllMatching(expireChecker);
mSrvCacheList.RemoveAllMatching(expireChecker, expiredSrvList); mSrvCacheList.RemoveAndFreeAllMatching(expireChecker);
mTxtCacheList.RemoveAllMatching(expireChecker, expiredTxtList); mTxtCacheList.RemoveAndFreeAllMatching(expireChecker);
mIp6AddrCacheList.RemoveAllMatching(expireChecker, expiredIp6AddrList); mIp6AddrCacheList.RemoveAndFreeAllMatching(expireChecker);
mIp4AddrCacheList.RemoveAllMatching(expireChecker, expiredIp4AddrList); mIp4AddrCacheList.RemoveAndFreeAllMatching(expireChecker);
// Process cache types in a specific order to optimize name // Process cache types in a specific order to optimize name
// compression when constructing query messages. // compression when constructing query messages.
@@ -4720,9 +4707,7 @@ exit:
void Core::CacheEntry::ClearEmptyCallbacks(void) void Core::CacheEntry::ClearEmptyCallbacks(void)
{ {
CallbackList emptyCallbacks; mCallbacks.RemoveAndFreeAllMatching(EmptyChecker());
mCallbacks.RemoveAllMatching(EmptyChecker(), emptyCallbacks);
if (mCallbacks.IsEmpty()) if (mCallbacks.IsEmpty())
{ {
@@ -5765,13 +5750,13 @@ void Core::AddrCache::DetermineRecordFireTime(void)
void Core::AddrCache::ProcessExpiredRecords(TimeMilli aNow) void Core::AddrCache::ProcessExpiredRecords(TimeMilli aNow)
{ {
OwningList<AddrEntry> expiredEntries;
Heap::Array<AddressAndTtl> addrArray; Heap::Array<AddressAndTtl> addrArray;
AddressResult result; AddressResult result;
bool didRemoveAny;
mCommittedEntries.RemoveAllMatching(ExpireChecker(aNow), expiredEntries); didRemoveAny = mCommittedEntries.RemoveAndFreeAllMatching(ExpireChecker(aNow));
VerifyOrExit(!expiredEntries.IsEmpty()); VerifyOrExit(didRemoveAny);
ConstructResult(result, addrArray); ConstructResult(result, addrArray);
InvokeCallbacks(result); InvokeCallbacks(result);
@@ -5963,9 +5948,7 @@ void Core::AddrCache::CommitNewResponseEntries(void)
} }
else else
{ {
OwningList<AddrEntry> removedEntries; mCommittedEntries.RemoveAndFreeAllMatching(EmptyChecker());
mCommittedEntries.RemoveAllMatching(EmptyChecker(), removedEntries);
} }
while (!mNewEntries.IsEmpty()) while (!mNewEntries.IsEmpty())
+37
View File
@@ -313,6 +313,7 @@ void TestOwningList(void)
OwningList<Entry> list; OwningList<Entry> list;
OwningList<Entry> removedList; OwningList<Entry> removedList;
OwnedPtr<Entry> ptr; OwnedPtr<Entry> ptr;
bool didRemove;
printf("TestOwningList\n"); printf("TestOwningList\n");
@@ -433,6 +434,42 @@ void TestOwningList(void)
VerifyOrQuit(list.IsEmpty()); VerifyOrQuit(list.IsEmpty());
VerifyLinkedListContent(&removedList, &c, &d, &f, nullptr); VerifyLinkedListContent(&removedList, &c, &d, &f, nullptr);
VerifyOrQuit(!c.WasFreed()); VerifyOrQuit(!c.WasFreed());
// Test `RemoveAndFreeAllMatching()`
a.ResetTestFlags();
b.ResetTestFlags();
c.ResetTestFlags();
d.ResetTestFlags();
e.ResetTestFlags();
f.ResetTestFlags();
list.Push(a);
list.Push(b);
list.Push(c);
list.Push(d);
list.Push(e);
list.Push(f);
VerifyLinkedListContent(&list, &f, &e, &d, &c, &b, &a, nullptr);
didRemove = list.RemoveAndFreeAllMatching(kAlphaType);
VerifyLinkedListContent(&list, &f, &d, &c, nullptr);
VerifyOrQuit(didRemove);
VerifyOrQuit(a.WasFreed());
VerifyOrQuit(b.WasFreed());
VerifyOrQuit(e.WasFreed());
VerifyOrQuit(!c.WasFreed());
didRemove = list.RemoveAndFreeAllMatching(kAlphaType);
VerifyOrQuit(!didRemove);
VerifyLinkedListContent(&list, &f, &d, &c, nullptr);
VerifyOrQuit(!c.WasFreed());
didRemove = list.RemoveAndFreeAllMatching(kBetaType);
VerifyOrQuit(list.IsEmpty());
VerifyOrQuit(didRemove);
VerifyOrQuit(c.WasFreed());
VerifyOrQuit(d.WasFreed());
VerifyOrQuit(f.WasFreed());
} }
} // namespace ot } // namespace ot