memgraph/poc/memory/block_allocator.hpp
florijan 5c921a21c4 utils::auto_scope refactor
Summary: Changed on-scope-exit-mechanism from macro (with two auto-generated variables and an all-capturing lambda) to an explicitly created variable that takes an std::function argument.

Reviewers: buda, mislav.bradac, teon.banek

Reviewed By: buda

Subscribers: pullbot

Differential Revision: https://phabricator.memgraph.io/D659
2017-08-11 09:43:10 +02:00

58 lines
1.4 KiB
C++

#pragma once
#include <memory>
#include <vector>
#include "utils/on_scope_exit.hpp"
/* @brief Allocates blocks of block_size and stores
* the pointers on allocated blocks inside a vector.
*/
template <size_t block_size>
class BlockAllocator {
struct Block {
Block() { data = malloc(block_size); }
Block(void *ptr) { data = ptr; }
void *data;
};
public:
static constexpr size_t size = block_size;
BlockAllocator(size_t capacity = 0) {
for (size_t i = 0; i < capacity; ++i) unused_.emplace_back();
}
~BlockAllocator() {
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(); }
// Returns nullptr on no memory.
void *acquire() {
if (unused_.size() == 0) unused_.emplace_back();
auto ptr = unused_.back().data;
// TODO is it necessary to use OnScopeExit here? ptr is copied by value, right?
utils::OnScopeExit on_exit([this]() { unused_.pop_back(); });
return ptr;
}
void release(void *ptr) { release_.emplace_back(ptr); }
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_;
};