EasyNav Plugins
Loading...
Searching...
No Matches
grid_allocator.hpp
Go to the documentation of this file.
1/*
2 * Copyright Contributors to the Bonxai Project
3 * Copyright Contributors to the OpenVDB Project
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
8 */
9
10#pragma once
11
12#include <cassert>
13#include <memory>
14#include <mutex>
15#include <stdexcept>
16#include <functional>
17
18#include "mask.hpp"
19
20namespace Bonxai
21{
22
29template<typename DataT>
31public:
32 // use log2dim of the block to be allocated
33 GridBlockAllocator(size_t log2dim);
34
37
40
41 using Deleter = std::function<void()>;
42
43 std::pair<DataT *, Deleter> allocateBlock();
44
45 void clear()
46 {
47 chunks_.clear();
48 size_ = 0;
49 capacity_ = 0;
50 }
51
53
54 size_t capacity() const
55 {
56 return capacity_;
57 }
58
59 size_t size() const
60 {
61 return size_;
62 }
63
64 size_t memUsage() const;
65
66 // specific size to use for Mask(3)
67 static constexpr size_t blocks_per_chunk = 512;
68
69protected:
70 size_t log2dim_ = 0;
71 size_t block_bytes_ = 0;
72 size_t capacity_ = 0;
73 size_t size_ = 0;
74 struct Chunk
75 {
77 : mask(3, true) {}
79 std::vector<char> data;
80 };
81 std::vector<std::shared_ptr<Chunk>> chunks_;
82 std::unique_ptr<std::mutex> mutex_;
83
85
86 Deleter createDeleter(std::shared_ptr<Chunk> chunk, uint32_t index);
87};
88
89//----------------------------------------------------
90//----------------- Implementations ------------------
91//----------------------------------------------------
92
93template<typename DataT>
95: log2dim_(log2dim),
96 block_bytes_(std::pow((1 << log2dim), 3) * sizeof(DataT)),
97 mutex_(new std::mutex) {}
98
99template<typename DataT>
100inline std::pair<DataT *, typename GridBlockAllocator<DataT>::Deleter>
102{
103 std::unique_lock lock(*mutex_);
104 if (size_ >= capacity_) {
105 // Need more memory. Create a new chunk
106 addNewChunk();
107 // first index of new chunk is available
108 std::shared_ptr<Chunk> chunk = chunks_.back();
109 DataT * ptr = reinterpret_cast<DataT *>(chunk->data.data());
110 chunk->mask.setOff(0);
111 size_++;
112 return {ptr, createDeleter(chunk, 0)};
113 }
114
115 // There must be available memory, somewhere. Search in reverse order
116 for (auto it = chunks_.rbegin(); it != chunks_.rend(); it++) {
117 std::shared_ptr<Chunk> & chunk = (*it);
118 auto mask_index = chunk->mask.findFirstOn();
119 if (mask_index < chunk->mask.size()) {
120 // found in this chunk
121 uint32_t data_index = block_bytes_ * mask_index;
122 DataT * ptr = reinterpret_cast<DataT *>(&chunk->data[data_index]);
123 chunk->mask.setOff(mask_index);
124 size_++;
125 return {ptr, createDeleter(chunk, mask_index)};
126 }
127 }
128 throw std::logic_error("Unexpected end of GridBlockAllocator::allocateBlock");
129}
130
131template<typename DataT>
133{
134 std::unique_lock lock(*mutex_);
135 int to_be_erased_count = 0;
136 auto remove_if = std::remove_if(chunks_.begin(), chunks_.end(), [&](const auto & chunk) -> bool {
137 bool notUsed = chunk->mask.isOn();
138 to_be_erased_count += (notUsed) ? 1 : 0;
139 return notUsed;
140 });
141 chunks_.erase(remove_if, chunks_.end());
142 capacity_ -= to_be_erased_count * blocks_per_chunk;
143}
144
145template<typename DataT>
147{
148 return chunks_.size() * (sizeof(Chunk) + block_bytes_ * blocks_per_chunk);
149}
150
151template<typename DataT>
153{
154 auto chunk = std::make_shared<Chunk>();
155 chunk->data.resize(blocks_per_chunk * block_bytes_);
156 chunks_.push_back(chunk);
158}
159
160template<typename DataT>
162 std::shared_ptr<Chunk> chunk, uint32_t index)
163{
164 return [this, index, chunk] {
165 assert(index < blocks_per_chunk);
166 std::unique_lock lock(*mutex_);
167 chunk->mask.setOn(index);
168 size_--;
169 };
170}
171
172} // namespace Bonxai
size_t memUsage() const
Definition grid_allocator.hpp:146
std::function< void()> Deleter
Definition grid_allocator.hpp:41
size_t size() const
Definition grid_allocator.hpp:59
void addNewChunk()
Definition grid_allocator.hpp:152
GridBlockAllocator(GridBlockAllocator &&)=default
std::pair< DataT *, Deleter > allocateBlock()
Definition grid_allocator.hpp:101
size_t log2dim_
Definition grid_allocator.hpp:70
size_t size_
Definition grid_allocator.hpp:73
size_t capacity() const
Definition grid_allocator.hpp:54
std::unique_ptr< std::mutex > mutex_
Definition grid_allocator.hpp:82
size_t capacity_
Definition grid_allocator.hpp:72
size_t block_bytes_
Definition grid_allocator.hpp:71
void clear()
Definition grid_allocator.hpp:45
Deleter createDeleter(std::shared_ptr< Chunk > chunk, uint32_t index)
Definition grid_allocator.hpp:161
GridBlockAllocator & operator=(const GridBlockAllocator &other)=delete
GridBlockAllocator(size_t log2dim)
Definition grid_allocator.hpp:94
void releaseUnusedMemory()
Definition grid_allocator.hpp:132
std::vector< std::shared_ptr< Chunk > > chunks_
Definition grid_allocator.hpp:81
GridBlockAllocator & operator=(GridBlockAllocator &&other)=default
GridBlockAllocator(const GridBlockAllocator &)=delete
static constexpr size_t blocks_per_chunk
Definition grid_allocator.hpp:67
Definition mask.hpp:20
Definition bonxai.hpp:28
Definition grid_coord.hpp:226
Definition grid_allocator.hpp:75
Mask mask
Definition grid_allocator.hpp:78
std::vector< char > data
Definition grid_allocator.hpp:79
Chunk()
Definition grid_allocator.hpp:76