srsLTE/lib/test/adt/mem_pool_test.cc

152 lines
3.8 KiB
C++
Raw Normal View History

/**
*
* \section COPYRIGHT
*
2021-03-19 03:45:56 -07:00
* Copyright 2013-2021 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 "srsran/adt/pool/fixed_size_pool.h"
#include "srsran/adt/pool/mem_pool.h"
2021-03-19 03:45:56 -07:00
#include "srsran/common/test_common.h"
class C
{
public:
C() { default_ctor_counter++; }
~C() { dtor_counter++; }
void* operator new(size_t sz);
void operator delete(void* ptr)noexcept;
static int default_ctor_counter;
static int dtor_counter;
};
int C::default_ctor_counter = 0;
int C::dtor_counter = 0;
2021-03-19 03:45:56 -07:00
srsran::big_obj_pool<C> pool;
void* C::operator new(size_t sz)
{
return pool.allocate_node(sz);
}
void C::operator delete(void* ptr)noexcept
{
pool.deallocate_node(ptr);
}
int test_nontrivial_obj_pool()
{
// No object creation on reservation
{
pool.reserve(10);
}
TESTASSERT(C::default_ctor_counter == 0);
TESTASSERT(C::dtor_counter == 0);
// default Ctor/Dtor are correctly called
{
pool.clear();
pool.reserve(10);
std::unique_ptr<C> c(new C{});
}
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;
{
pool.clear();
pool.reserve(10);
std::unique_ptr<C> c(new C{});
auto c2 = std::move(c);
}
TESTASSERT(C::default_ctor_counter == 1);
TESTASSERT(C::dtor_counter == 1);
2021-03-19 03:45:56 -07:00
return SRSRAN_SUCCESS;
}
struct BigObj {
C c;
std::array<uint8_t, 500> space;
using pool_t = srsran::concurrent_fixed_memory_pool<512, true>;
void* operator new(size_t sz)
{
srsran_assert(sz == sizeof(BigObj), "Allocated node size and object size do not match");
return pool_t::get_instance()->allocate_node(sizeof(BigObj));
}
void* operator new(size_t sz, const std::nothrow_t& nothrow_value) noexcept
{
srsran_assert(sz == sizeof(BigObj), "Allocated node size and object size do not match");
return pool_t::get_instance()->allocate_node(sizeof(BigObj));
}
void operator delete(void* ptr) { pool_t::get_instance()->deallocate_node(ptr); }
};
void test_fixedsize_pool()
{
size_t pool_size = 1024;
auto* fixed_pool = BigObj::pool_t::get_instance(pool_size);
fixed_pool->print_all_buffers();
{
std::vector<std::unique_ptr<BigObj> > vec(pool_size);
for (size_t i = 0; i < pool_size; ++i) {
vec[i].reset(new BigObj());
TESTASSERT(vec[i].get() != nullptr);
}
std::unique_ptr<BigObj> obj(new (std::nothrow) BigObj());
TESTASSERT(obj == nullptr);
vec.clear();
obj = std::unique_ptr<BigObj>(new (std::nothrow) BigObj());
TESTASSERT(obj != nullptr);
obj.reset();
fixed_pool->print_all_buffers();
}
fixed_pool->print_all_buffers();
// TEST: one thread allocates, and the other deallocates
{
std::unique_ptr<BigObj> obj;
std::atomic<bool> stop(false);
srsran::dyn_blocking_queue<std::unique_ptr<BigObj> > queue(pool_size / 2);
std::thread t([&queue, &stop]() {
while (not stop.load(std::memory_order_relaxed)) {
std::unique_ptr<BigObj> obj(new (std::nothrow) BigObj());
TESTASSERT(obj != nullptr);
queue.try_push(std::move(obj));
}
});
for (size_t i = 0; i < pool_size * 8; ++i) {
obj = queue.pop_blocking();
TESTASSERT(obj != nullptr);
}
stop.store(true);
fixed_pool->print_all_buffers();
t.join();
}
fixed_pool->print_all_buffers();
}
int main(int argc, char** argv)
{
srsran::test_init(argc, argv);
2021-03-19 03:45:56 -07:00
TESTASSERT(test_nontrivial_obj_pool() == SRSRAN_SUCCESS);
test_fixedsize_pool();
2021-03-19 03:45:56 -07:00
srsran::console("Success\n");
return 0;
}