add mem pool test. fix mem pool leak bug

master
Francisco Paisana 4 years ago
parent 8912a8ce6c
commit e96b8c263a

@ -13,12 +13,23 @@
#ifndef SRSLTE_MEM_POOL_H #ifndef SRSLTE_MEM_POOL_H
#define SRSLTE_MEM_POOL_H #define SRSLTE_MEM_POOL_H
#include <cstdint>
#include <memory>
#include <mutex>
namespace srslte { namespace srslte {
/// Stores provided mem blocks in a stack in an non-owning manner. Not thread-safe /// Stores provided mem blocks in a stack in an non-owning manner. Not thread-safe
class memblock_stack class memblock_stack
{ {
struct node {
node* prev;
explicit node(node* prev_) : prev(prev_) {}
};
public: public:
const static size_t min_memblock_size = sizeof(node);
memblock_stack() = default; memblock_stack() = default;
memblock_stack(const memblock_stack&) = delete; memblock_stack(const memblock_stack&) = delete;
@ -60,12 +71,6 @@ public:
void clear() { head = nullptr; } void clear() { head = nullptr; }
private: private:
struct node {
node* prev;
explicit node(node* prev_) : prev(prev_) {}
};
node* head = nullptr; node* head = nullptr;
size_t count = 0; size_t count = 0;
}; };
@ -136,13 +141,20 @@ private:
* - ::reserve(N) - prereserve memory slots for faster object creation * - ::reserve(N) - prereserve memory slots for faster object creation
* @tparam T object type * @tparam T object type
*/ */
template <typename T, bool ThreadSafe = true> template <typename T, bool ThreadSafe = false>
class obj_pool class obj_pool
{ {
const static size_t memblock_size = sizeof(T) > memblock_stack::min_memblock_size ? sizeof(T)
: memblock_stack::min_memblock_size;
/// single-thread obj pool deleter /// single-thread obj pool deleter
struct obj_deleter { struct obj_deleter {
explicit obj_deleter(obj_pool<T, ThreadSafe>* pool_) : pool(pool_) {} explicit obj_deleter(obj_pool<T, ThreadSafe>* pool_) : pool(pool_) {}
void operator()(void* block) { pool->stack.push(static_cast<uint8_t*>(block)); } void operator()(void* block)
{
static_cast<T*>(block)->~T();
pool->stack.push(static_cast<uint8_t*>(block));
}
obj_pool<T, ThreadSafe>* pool; obj_pool<T, ThreadSafe>* pool;
}; };
@ -170,7 +182,7 @@ public:
{ {
uint8_t* block = stack.try_pop(); uint8_t* block = stack.try_pop();
if (block == nullptr) { if (block == nullptr) {
block = new uint8_t[sizeof(T)]; block = new uint8_t[memblock_size];
} }
new (block) T(std::forward<Args>(args)...); new (block) T(std::forward<Args>(args)...);
return obj_ptr(reinterpret_cast<T*>(block), obj_deleter(this)); return obj_ptr(reinterpret_cast<T*>(block), obj_deleter(this));
@ -180,12 +192,15 @@ public:
void reserve(size_t N) void reserve(size_t N)
{ {
for (size_t i = 0; i < N; ++i) { for (size_t i = 0; i < N; ++i) {
stack.push(new uint8_t[sizeof(T)]); stack.push(new uint8_t[memblock_size]);
} }
} }
size_t capacity() const { return stack.size(); } size_t capacity() const { return stack.size(); }
}; };
template <typename T>
using mutexed_pool_obj = obj_pool<T, true>;
template <typename T> template <typename T>
using unique_pool_obj = typename obj_pool<T, false>::obj_ptr; using unique_pool_obj = typename obj_pool<T, false>::obj_ptr;
template <typename T> template <typename T>

@ -37,3 +37,7 @@ add_test(observer_test observer_test)
add_executable(bounded_vector_test bounded_vector_test.cc) add_executable(bounded_vector_test bounded_vector_test.cc)
target_link_libraries(bounded_vector_test srslte_common) target_link_libraries(bounded_vector_test srslte_common)
add_test(bounded_vector_test bounded_vector_test) add_test(bounded_vector_test bounded_vector_test)
add_executable(mem_pool_test mem_pool_test.cc)
target_link_libraries(mem_pool_test srslte_common)
add_test(mem_pool_test mem_pool_test)

@ -0,0 +1,69 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2020 Software Radio Systems Limited
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the distribution.
*
*/
#include "srslte/adt/mem_pool.h"
#include "srslte/common/test_common.h"
class C
{
public:
C() { default_ctor_counter++; }
~C() { dtor_counter++; }
static int default_ctor_counter;
static int dtor_counter;
};
int C::default_ctor_counter = 0;
int C::dtor_counter = 0;
int test_nontrivial_obj_pool()
{
// No object creation on reservation
{
srslte::obj_pool<C> pool;
pool.reserve(10);
}
TESTASSERT(C::default_ctor_counter == 0);
TESTASSERT(C::dtor_counter == 0);
// default Ctor/Dtor are correctly called
{
srslte::obj_pool<C> pool;
pool.reserve(10);
srslte::unique_pool_obj<C> c = pool.make();
}
TESTASSERT(C::default_ctor_counter == 1);
TESTASSERT(C::dtor_counter == 1);
// move of unique_ptr is correctly called
C::default_ctor_counter = 0;
C::dtor_counter = 0;
{
srslte::obj_pool<C> pool;
pool.reserve(10);
srslte::unique_pool_obj<C> c = pool.make();
srslte::unique_pool_obj<C> c2 = std::move(c);
}
TESTASSERT(C::default_ctor_counter == 1);
TESTASSERT(C::dtor_counter == 1);
return SRSLTE_SUCCESS;
}
int main()
{
TESTASSERT(test_nontrivial_obj_pool() == SRSLTE_SUCCESS);
srslte::console("Success\n");
return 0;
}
Loading…
Cancel
Save