memgraph/src/utils/memory/block_allocator.hpp

71 lines
1.4 KiB
C++
Raw Normal View History

#pragma once
2015-10-09 07:24:12 +08:00
#include <memory>
#include <vector>
#include "utils/auto_scope.hpp"
/* @brief Allocates blocks of block_size and stores
* the pointers on allocated blocks inside a vector.
*/
2015-10-09 07:24:12 +08:00
template <size_t block_size>
class BlockAllocator
{
struct Block
{
2016-09-16 03:19:31 +08:00
Block() { data = malloc(block_size); }
2015-10-09 07:24:12 +08:00
2016-09-16 03:19:31 +08:00
Block(void *ptr) { data = ptr; }
2015-10-09 07:24:12 +08:00
2016-09-16 03:19:31 +08:00
void *data;
2015-10-09 07:24:12 +08:00
};
public:
static constexpr size_t size = block_size;
BlockAllocator(size_t capacity = 0)
{
2016-09-16 03:19:31 +08:00
for (size_t i = 0; i < capacity; ++i)
unused_.emplace_back();
2015-10-09 07:24:12 +08:00
}
2016-09-16 03:19:31 +08:00
~BlockAllocator()
2015-10-09 07:24:12 +08:00
{
for (auto block : unused_)
free(block.data);
unused_.clear();
for (auto block : release_)
free(block.data);
release_.clear();
}
size_t unused_size() const
{
return unused_.size();
}
size_t release_size() const
{
return release_.size();
2015-10-09 07:24:12 +08:00
}
2016-09-16 03:19:31 +08:00
// Returns nullptr on no memory.
void *acquire()
2015-10-09 07:24:12 +08:00
{
if (unused_.size() == 0) unused_.emplace_back();
2016-09-16 03:19:31 +08:00
auto ptr = unused_.back().data;
Auto(unused_.pop_back());
2016-09-16 03:19:31 +08:00
return ptr;
2015-10-09 07:24:12 +08:00
}
void release(void *ptr) { release_.emplace_back(ptr); }
2016-09-16 03:19:31 +08:00
2015-10-09 07:24:12 +08:00
private:
// TODO: try implement with just one vector
// but consecutive acquire release calls should work
// TODO: measure first!
std::vector<Block> unused_;
std::vector<Block> release_;
2015-10-09 07:24:12 +08:00
};