From dae646bd09675e0491b7dc907a74ef1f4fa4d8b6 Mon Sep 17 00:00:00 2001 From: Kevin Schoedel <67607049+kpschoedel@users.noreply.github.com> Date: Tue, 21 Dec 2021 09:12:12 -0500 Subject: [PATCH] ObjectPool: add const version for ForEachActiveObject (#13167) #### Problem Iterating a `const` pool can be useful. #### Change overview Add `const` overloads for `ForEachActiveObject` and associated internals. #### Testing Make the `TestPool` utility function `GetNumObjectsInUse()` take a `const` pool. --- src/lib/support/Pool.cpp | 2 -- src/lib/support/Pool.h | 34 ++++++++++++++++++++++++++++-- src/lib/support/PoolWrapper.h | 24 ++++++++++++++++++--- src/lib/support/tests/TestPool.cpp | 4 ++-- 4 files changed, 55 insertions(+), 9 deletions(-) diff --git a/src/lib/support/Pool.cpp b/src/lib/support/Pool.cpp index 4f44edaf97d1c7..77454ef052bff7 100644 --- a/src/lib/support/Pool.cpp +++ b/src/lib/support/Pool.cpp @@ -84,7 +84,6 @@ size_t StaticAllocatorBitmap::IndexOf(void * element) return index; } -using Lambda = Loop (*)(void *, void *); Loop StaticAllocatorBitmap::ForEachActiveObjectInner(void * context, Lambda lambda) { for (size_t word = 0; word * kBitChunkSize < Capacity(); ++word) @@ -117,7 +116,6 @@ HeapObjectListNode * HeapObjectList::FindNode(void * object) const return nullptr; } -using Lambda = Loop (*)(void *, void *); Loop HeapObjectList::ForEachNode(void * context, Lambda lambda) { ++mIterationDepth; diff --git a/src/lib/support/Pool.h b/src/lib/support/Pool.h index 9bd7d6a5d872b7..cc1cca426007b0 100644 --- a/src/lib/support/Pool.h +++ b/src/lib/support/Pool.h @@ -91,7 +91,12 @@ class StaticAllocatorBitmap : public internal::StaticAllocatorBase void * At(size_t index) { return static_cast(mElements) + mElementSize * index; } size_t IndexOf(void * element); - Loop ForEachActiveObjectInner(void * context, Loop lambda(void * context, void * object)); + using Lambda = Loop (*)(void * context, void * object); + Loop ForEachActiveObjectInner(void * context, Lambda lambda); + Loop ForEachActiveObjectInner(void * context, Loop lambda(void * context, const void * object)) const + { + return const_cast(this)->ForEachActiveObjectInner(context, reinterpret_cast(lambda)); + } private: void * mElements; @@ -120,6 +125,10 @@ class LambdaProxy { return static_cast(context)->mFunction(static_cast(target)); } + static Loop ConstCall(void * context, const void * target) + { + return static_cast(context)->mFunction(static_cast(target)); + } private: Function mFunction; @@ -154,7 +163,12 @@ struct HeapObjectList : HeapObjectListNode HeapObjectListNode * FindNode(void * object) const; - Loop ForEachNode(void * context, Loop lambda(void * context, void * object)); + using Lambda = Loop (*)(void *, void *); + Loop ForEachNode(void * context, Lambda lambda); + Loop ForEachNode(void * context, Loop lambda(void * context, const void * object)) const + { + return const_cast(this)->ForEachNode(context, reinterpret_cast(lambda)); + } size_t mIterationDepth; }; @@ -242,6 +256,14 @@ class BitMapObjectPool : public internal::StaticAllocatorBitmap, public internal internal::LambdaProxy proxy(std::forward(function)); return ForEachActiveObjectInner(&proxy, &internal::LambdaProxy::Call); } + template + Loop ForEachActiveObject(Function && function) const + { + static_assert(std::is_same()))>::value, + "The function must take const T* and return Loop"); + internal::LambdaProxy proxy(std::forward(function)); + return ForEachActiveObjectInner(&proxy, &internal::LambdaProxy::ConstCall); + } private: static Loop ReleaseObject(void * context, void * object) @@ -324,6 +346,14 @@ class HeapObjectPool : public internal::Statistics, public internal::PoolCommon< internal::LambdaProxy proxy(std::forward(function)); return mObjects.ForEachNode(&proxy, &internal::LambdaProxy::Call); } + template + Loop ForEachActiveObject(Function && function) const + { + static_assert(std::is_same()))>::value, + "The function must take const T* and return Loop"); + internal::LambdaProxy proxy(std::forward(function)); + return mObjects.ForEachNode(&proxy, &internal::LambdaProxy::ConstCall); + } private: static Loop ReleaseObject(void * context, void * object) diff --git a/src/lib/support/PoolWrapper.h b/src/lib/support/PoolWrapper.h index ca338b4d7c6e89..e5025640179cf6 100644 --- a/src/lib/support/PoolWrapper.h +++ b/src/lib/support/PoolWrapper.h @@ -47,10 +47,21 @@ class PoolInterface return ForEachActiveObjectInner( &proxy, [](void * context, U * target) -> Loop { return (*static_cast(context))(target); }); } + template + Loop ForEachActiveObject(Function && function) const + { + static_assert(std::is_same()))>::value, + "The function must take const T* and return Loop"); + auto proxy = [&](const U * target) -> Loop { return function(target); }; + return ForEachActiveObjectInner( + &proxy, [](void * context, const U * target) -> Loop { return (*static_cast(context))(target); }); + } protected: - using Lambda = Loop (*)(void *, U *); - virtual Loop ForEachActiveObjectInner(void * context, Lambda lambda) = 0; + using Lambda = Loop (*)(void *, U *); + using LambdaConst = Loop (*)(void *, const U *); + virtual Loop ForEachActiveObjectInner(void * context, Lambda lambda) = 0; + virtual Loop ForEachActiveObjectInner(void * context, LambdaConst lambda) const = 0; }; template @@ -82,8 +93,14 @@ class PoolProxy> : public PoolIn { return Impl().ForEachActiveObject([&](T * target) { return lambda(context, static_cast(target)); }); } + virtual Loop ForEachActiveObjectInner(void * context, + typename PoolInterface::LambdaConst lambda) const override + { + return Impl().ForEachActiveObject([&](const T * target) { return lambda(context, static_cast(target)); }); + } - virtual ObjectPool & Impl() = 0; + virtual ObjectPool & Impl() = 0; + virtual const ObjectPool & Impl() const = 0; }; /* @@ -107,6 +124,7 @@ class PoolImpl : public PoolProxy... protected: virtual ObjectPool & Impl() override { return mImpl; } + virtual const ObjectPool & Impl() const override { return mImpl; } private: ObjectPool mImpl; diff --git a/src/lib/support/tests/TestPool.cpp b/src/lib/support/tests/TestPool.cpp index 4870e8f1ede3bd..0a23aa71363691 100644 --- a/src/lib/support/tests/TestPool.cpp +++ b/src/lib/support/tests/TestPool.cpp @@ -35,10 +35,10 @@ namespace chip { template -size_t GetNumObjectsInUse(POOL & pool) +size_t GetNumObjectsInUse(const POOL & pool) { size_t count = 0; - pool.ForEachActiveObject([&count](void *) { + pool.ForEachActiveObject([&count](const void *) { ++count; return Loop::Continue; });