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

Extend PoolInterface to heap pools #12997

Merged
merged 1 commit into from
Dec 15, 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
3 changes: 2 additions & 1 deletion src/lib/dnssd/minimal_mdns/Server.h
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,8 @@ class ServerBase

// The PoolImpl impl is used as a base class because its destructor must be called after ServerBase's destructor.
template <size_t kCount>
class Server : private chip::PoolImpl<ServerBase::EndpointInfo, kCount, ServerBase::EndpointInfoPoolType::Interface>,
class Server : private chip::PoolImpl<ServerBase::EndpointInfo, kCount, chip::ObjectPoolMem::kStatic,
ServerBase::EndpointInfoPoolType::Interface>,
public ServerBase
{
public:
Expand Down
3 changes: 2 additions & 1 deletion src/lib/dnssd/minimal_mdns/tests/CheckOnlyServer.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,8 @@ void MakePrintableName(char (&location)[N], FullQName name)

} // namespace

class CheckOnlyServer : private chip::PoolImpl<ServerBase::EndpointInfo, 0, ServerBase::EndpointInfoPoolType::Interface>,
class CheckOnlyServer : private chip::PoolImpl<ServerBase::EndpointInfo, 0, chip::ObjectPoolMem::kStatic,
ServerBase::EndpointInfoPoolType::Interface>,
public ServerBase,
public ParserDelegate,
public TxtRecordDelegate
Expand Down
21 changes: 8 additions & 13 deletions src/lib/support/Pool.h
Original file line number Diff line number Diff line change
Expand Up @@ -336,33 +336,28 @@ class HeapObjectPool : public internal::Statistics, public internal::PoolCommon<

#endif // CHIP_SYSTEM_CONFIG_POOL_USE_HEAP

#if CHIP_SYSTEM_CONFIG_POOL_USE_HEAP
template <typename T, unsigned int N>
using ObjectPool = HeapObjectPool<T>;
#else // CHIP_SYSTEM_CONFIG_POOL_USE_HEAP
template <typename T, unsigned int N>
using ObjectPool = BitMapObjectPool<T, N>;
#endif // CHIP_SYSTEM_CONFIG_POOL_USE_HEAP

enum class ObjectPoolMem
{
kStatic,
#if CHIP_SYSTEM_CONFIG_POOL_USE_HEAP
kDynamic
kDynamic,
kDefault = kDynamic
#else // CHIP_SYSTEM_CONFIG_POOL_USE_HEAP
kDefault = kStatic
#endif // CHIP_SYSTEM_CONFIG_POOL_USE_HEAP
};

template <typename T, size_t N, ObjectPoolMem P>
class MemTypeObjectPool;
template <typename T, size_t N, ObjectPoolMem P = ObjectPoolMem::kDefault>
class ObjectPool;

template <typename T, size_t N>
class MemTypeObjectPool<T, N, ObjectPoolMem::kStatic> : public BitMapObjectPool<T, N>
class ObjectPool<T, N, ObjectPoolMem::kStatic> : public BitMapObjectPool<T, N>
{
};

#if CHIP_SYSTEM_CONFIG_POOL_USE_HEAP
template <typename T, size_t N>
class MemTypeObjectPool<T, N, ObjectPoolMem::kDynamic> : public HeapObjectPool<T>
class ObjectPool<T, N, ObjectPoolMem::kDynamic> : public HeapObjectPool<T>
{
};
#endif // CHIP_SYSTEM_CONFIG_POOL_USE_HEAP
Expand Down
17 changes: 9 additions & 8 deletions src/lib/support/PoolWrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,11 @@ class PoolInterface
virtual Loop ForEachActiveObjectInner(void * context, Lambda lambda) = 0;
};

template <class T, size_t N, typename Interface>
template <class T, size_t N, ObjectPoolMem M, typename Interface>
class PoolProxy;

template <class T, size_t N, typename U, typename... ConstructorArguments>
class PoolProxy<T, N, std::tuple<U, ConstructorArguments...>> : public PoolInterface<U, ConstructorArguments...>
template <class T, size_t N, ObjectPoolMem M, typename U, typename... ConstructorArguments>
class PoolProxy<T, N, M, std::tuple<U, ConstructorArguments...>> : public PoolInterface<U, ConstructorArguments...>
{
public:
static_assert(std::is_base_of<U, T>::value, "Interface type is not derived from Pool type");
Expand All @@ -83,7 +83,7 @@ class PoolProxy<T, N, std::tuple<U, ConstructorArguments...>> : public PoolInter
return Impl().ForEachActiveObject([&](T * target) { return lambda(context, static_cast<U *>(target)); });
}

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

/*
Expand All @@ -92,23 +92,24 @@ class PoolProxy<T, N, std::tuple<U, ConstructorArguments...>> : public PoolInter
*
* @tparam T a subclass of element to be allocated.
* @tparam N a positive integer max number of elements the pool provides.
* @tparam M an ObjectPoolMem constant selecting static vs heap allocation.
* @tparam Interfaces a list of parameters which defines PoolInterface's. each interface is defined by a
* std::tuple<U, ConstructorArguments...>. The PoolImpl is derived from every
* PoolInterface<U, ConstructorArguments...>, the PoolImpl can be converted to the interface type
* and passed around
*/
template <class T, size_t N, typename... Interfaces>
class PoolImpl : public PoolProxy<T, N, Interfaces>...
template <class T, size_t N, ObjectPoolMem M, typename... Interfaces>
class PoolImpl : public PoolProxy<T, N, M, Interfaces>...
{
public:
PoolImpl() {}
virtual ~PoolImpl() override {}

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

private:
BitMapObjectPool<T, N> mImpl;
ObjectPool<T, N, M> mImpl;
};

} // namespace chip
76 changes: 71 additions & 5 deletions src/lib/support/tests/TestPool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include <set>

#include <lib/support/Pool.h>
#include <lib/support/PoolWrapper.h>
#include <lib/support/UnitTestRegistration.h>
#include <system/SystemConfig.h>

Expand Down Expand Up @@ -53,7 +54,7 @@ using namespace chip;
template <typename T, size_t N, ObjectPoolMem P>
void TestReleaseNull(nlTestSuite * inSuite, void * inContext)
{
MemTypeObjectPool<T, N, P> pool;
ObjectPool<T, N, P> pool;
pool.ReleaseObject(nullptr);
NL_TEST_ASSERT(inSuite, GetNumObjectsInUse(pool) == 0);
NL_TEST_ASSERT(inSuite, pool.Allocated() == 0);
Expand All @@ -74,7 +75,7 @@ void TestReleaseNullDynamic(nlTestSuite * inSuite, void * inContext)
template <typename T, size_t N, ObjectPoolMem P>
void TestCreateReleaseObject(nlTestSuite * inSuite, void * inContext)
{
MemTypeObjectPool<uint32_t, N, ObjectPoolMem::kStatic> pool;
ObjectPool<uint32_t, N, ObjectPoolMem::kStatic> pool;
uint32_t * obj[N];

NL_TEST_ASSERT(inSuite, pool.Allocated() == 0);
Expand Down Expand Up @@ -105,7 +106,7 @@ void TestCreateReleaseObjectStatic(nlTestSuite * inSuite, void * inContext)
constexpr const size_t kSize = 100;
TestCreateReleaseObject<uint32_t, kSize, ObjectPoolMem::kStatic>(inSuite, inContext);

MemTypeObjectPool<uint32_t, kSize, ObjectPoolMem::kStatic> pool;
ObjectPool<uint32_t, kSize, ObjectPoolMem::kStatic> pool;
uint32_t * obj[kSize];

for (size_t i = 0; i < kSize; ++i)
Expand Down Expand Up @@ -159,7 +160,7 @@ void TestCreateReleaseStruct(nlTestSuite * inSuite, void * inContext)
std::set<S *> objs1;

constexpr const size_t kSize = 100;
MemTypeObjectPool<S, kSize, P> pool;
ObjectPool<S, kSize, P> pool;

S * objs2[kSize];
for (size_t i = 0; i < kSize; ++i)
Expand Down Expand Up @@ -223,7 +224,7 @@ void TestForEachActiveObject(nlTestSuite * inSuite, void * inContext)
S * objArray[kSize];
std::set<size_t> objIds;

MemTypeObjectPool<S, kSize, P> pool;
ObjectPool<S, kSize, P> pool;

for (size_t i = 0; i < kSize; ++i)
{
Expand Down Expand Up @@ -343,6 +344,69 @@ void TestForEachActiveObjectDynamic(nlTestSuite * inSuite, void * inContext)
}
#endif // CHIP_SYSTEM_CONFIG_POOL_USE_HEAP

template <ObjectPoolMem P>
void TestPoolInterface(nlTestSuite * inSuite, void * inContext)
{
struct TestObject
{
TestObject(uint32_t * set, size_t id) : mSet(set), mId(id) { *mSet |= (1 << mId); }
~TestObject() { *mSet &= ~(1 << mId); }
uint32_t * mSet;
size_t mId;
};
using TestObjectPoolType = PoolInterface<TestObject, uint32_t *, size_t>;

struct PoolHolder
{
PoolHolder(TestObjectPoolType & testObjectPool) : mTestObjectPoolInterface(testObjectPool) {}
TestObjectPoolType & mTestObjectPoolInterface;
};

constexpr size_t kSize = 10;
PoolImpl<TestObject, kSize, P, typename TestObjectPoolType::Interface> testObjectPool;
PoolHolder poolHolder(testObjectPool);
uint32_t bits = 0;

TestObject * objs2[kSize];
for (size_t i = 0; i < kSize; ++i)
{
objs2[i] = poolHolder.mTestObjectPoolInterface.CreateObject(&bits, i);
NL_TEST_ASSERT(inSuite, objs2[i] != nullptr);
NL_TEST_ASSERT(inSuite, GetNumObjectsInUse(poolHolder.mTestObjectPoolInterface) == i + 1);
NL_TEST_ASSERT(inSuite, bits == (1ul << (i + 1)) - 1);
}
for (size_t i = 0; i < kSize; ++i)
{
poolHolder.mTestObjectPoolInterface.ReleaseObject(objs2[i]);
NL_TEST_ASSERT(inSuite, GetNumObjectsInUse(poolHolder.mTestObjectPoolInterface) == kSize - i - 1);
}
NL_TEST_ASSERT(inSuite, bits == 0);

// Verify that ReleaseAll() calls the destructors.
for (size_t i = 0; i < kSize; ++i)
{
objs2[i] = poolHolder.mTestObjectPoolInterface.CreateObject(&bits, i);
}
NL_TEST_ASSERT(inSuite, bits == (1ul << kSize) - 1);
NL_TEST_ASSERT(inSuite, GetNumObjectsInUse(poolHolder.mTestObjectPoolInterface) == kSize);

poolHolder.mTestObjectPoolInterface.ReleaseAll();
NL_TEST_ASSERT(inSuite, bits == 0);
NL_TEST_ASSERT(inSuite, GetNumObjectsInUse(poolHolder.mTestObjectPoolInterface) == 0);
}

void TestPoolInterfaceStatic(nlTestSuite * inSuite, void * inContext)
{
TestPoolInterface<ObjectPoolMem::kStatic>(inSuite, inContext);
}

#if CHIP_SYSTEM_CONFIG_POOL_USE_HEAP
void TestPoolInterfaceDynamic(nlTestSuite * inSuite, void * inContext)
{
TestPoolInterface<ObjectPoolMem::kDynamic>(inSuite, inContext);
}
#endif // CHIP_SYSTEM_CONFIG_POOL_USE_HEAP

int Setup(void * inContext)
{
return SUCCESS;
Expand All @@ -365,11 +429,13 @@ static const nlTest sTests[] = {
NL_TEST_DEF_FN(TestCreateReleaseObjectStatic),
NL_TEST_DEF_FN(TestCreateReleaseStructStatic),
NL_TEST_DEF_FN(TestForEachActiveObjectStatic),
NL_TEST_DEF_FN(TestPoolInterfaceStatic),
#if CHIP_SYSTEM_CONFIG_POOL_USE_HEAP
NL_TEST_DEF_FN(TestReleaseNullDynamic),
NL_TEST_DEF_FN(TestCreateReleaseObjectDynamic),
NL_TEST_DEF_FN(TestCreateReleaseStructDynamic),
NL_TEST_DEF_FN(TestForEachActiveObjectDynamic),
NL_TEST_DEF_FN(TestPoolInterfaceDynamic),
#endif // CHIP_SYSTEM_CONFIG_POOL_USE_HEAP
NL_TEST_SENTINEL()
// clang-format on
Expand Down
2 changes: 1 addition & 1 deletion src/transport/raw/TCP.h
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ class TCP : public TCPBase
private:
friend class TCPTest;
TCPBase::ActiveConnectionState mConnectionsBuffer[kActiveConnectionsSize];
PoolImpl<PendingPacket, kPendingPacketSize, PendingPacketPoolType::Interface> mPendingPackets;
PoolImpl<PendingPacket, kPendingPacketSize, ObjectPoolMem::kStatic, PendingPacketPoolType::Interface> mPendingPackets;
};

} // namespace Transport
Expand Down