Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ObjectPool: add const version for ForEachActiveObject #13167

Merged
merged 1 commit into from
Dec 21, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions src/lib/support/Pool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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;
Expand Down
34 changes: 32 additions & 2 deletions src/lib/support/Pool.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,12 @@ class StaticAllocatorBitmap : public internal::StaticAllocatorBase
void * At(size_t index) { return static_cast<uint8_t *>(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<StaticAllocatorBitmap *>(this)->ForEachActiveObjectInner(context, reinterpret_cast<Lambda>(lambda));
}

private:
void * mElements;
Expand Down Expand Up @@ -120,6 +125,10 @@ class LambdaProxy
{
return static_cast<LambdaProxy *>(context)->mFunction(static_cast<T *>(target));
}
static Loop ConstCall(void * context, const void * target)
{
return static_cast<LambdaProxy *>(context)->mFunction(static_cast<const T *>(target));
}

private:
Function mFunction;
Expand Down Expand Up @@ -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<HeapObjectList *>(this)->ForEachNode(context, reinterpret_cast<Lambda>(lambda));
}

size_t mIterationDepth;
};
Expand Down Expand Up @@ -242,6 +256,14 @@ class BitMapObjectPool : public internal::StaticAllocatorBitmap, public internal
internal::LambdaProxy<T, Function> proxy(std::forward<Function>(function));
return ForEachActiveObjectInner(&proxy, &internal::LambdaProxy<T, Function>::Call);
}
template <typename Function>
Loop ForEachActiveObject(Function && function) const
{
static_assert(std::is_same<Loop, decltype(function(std::declval<const T *>()))>::value,
"The function must take const T* and return Loop");
internal::LambdaProxy<T, Function> proxy(std::forward<Function>(function));
return ForEachActiveObjectInner(&proxy, &internal::LambdaProxy<T, Function>::ConstCall);
}

private:
static Loop ReleaseObject(void * context, void * object)
Expand Down Expand Up @@ -324,6 +346,14 @@ class HeapObjectPool : public internal::Statistics, public internal::PoolCommon<
internal::LambdaProxy<T, Function> proxy(std::forward<Function>(function));
return mObjects.ForEachNode(&proxy, &internal::LambdaProxy<T, Function>::Call);
}
template <typename Function>
Loop ForEachActiveObject(Function && function) const
{
static_assert(std::is_same<Loop, decltype(function(std::declval<const T *>()))>::value,
"The function must take const T* and return Loop");
internal::LambdaProxy<const T, Function> proxy(std::forward<Function>(function));
return mObjects.ForEachNode(&proxy, &internal::LambdaProxy<const T, Function>::ConstCall);
}

private:
static Loop ReleaseObject(void * context, void * object)
Expand Down
24 changes: 21 additions & 3 deletions src/lib/support/PoolWrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,21 @@ class PoolInterface
return ForEachActiveObjectInner(
&proxy, [](void * context, U * target) -> Loop { return (*static_cast<decltype(proxy) *>(context))(target); });
}
template <typename Function>
Loop ForEachActiveObject(Function && function) const
{
static_assert(std::is_same<Loop, decltype(function(std::declval<U *>()))>::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<decltype(proxy) *>(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 <class T, size_t N, ObjectPoolMem M, typename Interface>
Expand Down Expand Up @@ -82,8 +93,14 @@ class PoolProxy<T, N, M, std::tuple<U, ConstructorArguments...>> : public PoolIn
{
return Impl().ForEachActiveObject([&](T * target) { return lambda(context, static_cast<U *>(target)); });
}
virtual Loop ForEachActiveObjectInner(void * context,
typename PoolInterface<U, ConstructorArguments...>::LambdaConst lambda) const override
{
return Impl().ForEachActiveObject([&](const T * target) { return lambda(context, static_cast<const U *>(target)); });
}

virtual ObjectPool<T, N, M> & Impl() = 0;
virtual ObjectPool<T, N, M> & Impl() = 0;
virtual const ObjectPool<T, N, M> & Impl() const = 0;
};

/*
Expand All @@ -107,6 +124,7 @@ class PoolImpl : public PoolProxy<T, N, M, Interfaces>...

protected:
virtual ObjectPool<T, N, M> & Impl() override { return mImpl; }
virtual const ObjectPool<T, N, M> & Impl() const override { return mImpl; }

private:
ObjectPool<T, N, M> mImpl;
Expand Down
4 changes: 2 additions & 2 deletions src/lib/support/tests/TestPool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,10 @@
namespace chip {

template <class POOL>
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;
});
Expand Down