mirror of
https://github.com/espressif/openthread.git
synced 2026-10-12 02:37:37 +00:00
[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:
@@ -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
@@ -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())
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user