diff --git a/src/lib/support/Pool.cpp b/src/lib/support/Pool.cpp index b794bb4080f577..9a08a928f43025 100644 --- a/src/lib/support/Pool.cpp +++ b/src/lib/support/Pool.cpp @@ -73,4 +73,32 @@ void StaticAllocatorBitmap::Deallocate(void * element) mAllocated--; } +size_t StaticAllocatorBitmap::IndexOf(void * element) +{ + std::ptrdiff_t diff = static_cast(element) - static_cast(mElements); + assert(diff >= 0); + assert(static_cast(diff) % mElementSize == 0); + auto index = static_cast(diff) / mElementSize; + assert(index < Capacity()); + return index; +} + +bool StaticAllocatorBitmap::ForEachActiveObjectInner(void * context, Lambda lambda) +{ + for (size_t word = 0; word * kBitChunkSize < Capacity(); ++word) + { + auto & usage = mUsage[word]; + auto value = usage.load(std::memory_order_relaxed); + for (size_t offset = 0; offset < kBitChunkSize && offset + word * kBitChunkSize < Capacity(); ++offset) + { + if ((value & (kBit1 << offset)) != 0) + { + if (!lambda(context, At(word * kBitChunkSize + offset))) + return false; + } + } + } + return true; +} + } // namespace chip diff --git a/src/lib/support/Pool.h b/src/lib/support/Pool.h index 29466b0206e88e..2158929ca216ee 100644 --- a/src/lib/support/Pool.h +++ b/src/lib/support/Pool.h @@ -65,15 +65,10 @@ class StaticAllocatorBitmap : public StaticAllocatorBase protected: void * At(size_t index) { return static_cast(mElements) + mElementSize * index; } - size_t IndexOf(void * element) - { - std::ptrdiff_t diff = static_cast(element) - static_cast(mElements); - assert(diff >= 0); - assert(static_cast(diff) % mElementSize == 0); - auto index = static_cast(diff) / mElementSize; - assert(index < Capacity()); - return index; - } + size_t IndexOf(void * element); + + using Lambda = bool (*)(void *, void *); + bool ForEachActiveObjectInner(void * context, Lambda lambda); private: void * mElements; @@ -119,33 +114,35 @@ class BitMapObjectPool : public StaticAllocatorBitmap * @brief * Run a functor for each active object in the pool * - * @param f The functor of type `bool (*)(T*)`, return false to break the iteration - * @return bool Returns false if broke during iteration + * @param function The functor of type `bool (*)(T*)`, return false to break the iteration + * @return bool Returns false if broke during iteration * * caution * this function is not thread-safe, make sure all usage of the * pool is protected by a lock, or else avoid using this function */ - template - bool ForEachActiveObject(F f) + template + bool ForEachActiveObject(Function && function) { - for (size_t word = 0; word * kBitChunkSize < Capacity(); ++word) - { - auto & usage = mUsage[word]; - auto value = usage.load(std::memory_order_relaxed); - for (size_t offset = 0; offset < kBitChunkSize && offset + word * kBitChunkSize < Capacity(); ++offset) - { - if ((value & (kBit1 << offset)) != 0) - { - if (!f(static_cast(At(word * kBitChunkSize + offset)))) - return false; - } - } - } - return true; + LambdaProxy proxy(std::forward(function)); + return ForEachActiveObjectInner(&proxy, &LambdaProxy::Call); } private: + template + class LambdaProxy + { + public: + LambdaProxy(Function && function) : mFunction(std::move(function)) {} + static bool Call(void * context, void * target) + { + return static_cast(context)->mFunction(static_cast(target)); + } + + private: + Function mFunction; + }; + std::atomic mUsage[(N + kBitChunkSize - 1) / kBitChunkSize]; alignas(alignof(T)) uint8_t mMemory[N * sizeof(T)]; };