OpenVDB 12.1.0
Loading...
Searching...
No Matches
HostBuffer.h
Go to the documentation of this file.
1// Copyright Contributors to the OpenVDB Project
2// SPDX-License-Identifier: Apache-2.0
3
4/*!
5 @file nanovdb/HostBuffer.h
6
7 @date April 20, 2021
8
9 @brief HostBuffer - a buffer that contains a shared or private bump
10 pool to either externally or internally managed host memory.
11
12 @details This HostBuffer can be used in multiple ways, most of which are
13 demonstrated in the examples below. Memory in the pool can
14 be managed or unmanged (e.g. internal or external) and can
15 be shared between multiple buffers or belong to a single buffer.
16
17 Example that uses HostBuffer::create inside io::readGrids to create a
18 full self-managed buffer, i.e. not shared and without padding, per grid in the file.
19 @code
20 auto handles = nanovdb::io::readGrids("file.nvdb");
21 @endcode
22
23 Example that uses HostBuffer::createFull. Assuming you have a raw pointer
24 to a NanoVDB grid of unknown type, this examples shows how to create its
25 GridHandle which can be used to enquire about the grid type and meta data.
26 @code
27 void *data;// pointer to a NanoVDB grid of unknown type
28 uint64_t size;// byte size of NanoVDB grid of unknown type
29 auto buffer = nanovdb::HostBuffer::createFull(size, data);
30 nanovdb::GridHandle<> gridHandle(std::move(buffer));
31 @endcode
32
33 Example that uses HostBuffer::createPool for internally managed host memory.
34 Suppose you want to read multiple grids in multiple files, but reuse the same
35 fixed sized memory buffer to both avoid memory fragmentation as well as
36 exceeding the fixed memory ceiling!
37 @code
38 auto pool = nanovdb::HostBuffer::createPool(1 << 30);// 1 GB memory pool
39 std::vector<std::string>> frames;// vector of grid names
40 for (int i=0; i<frames.size(); ++i) {
41 auto handles = nanovdb::io::readGrids(frames[i], 0, pool);// throws if grids in file exceed 1 GB
42 ...
43 pool.reset();// clears all handles and resets the memory pool for reuse
44 }
45 @endcode
46
47 Example that uses HostBuffer::createPool for externally managed host memory.
48 Note that in this example @c handles are allowed to outlive @c pool since
49 they internally store a shared pointer to the memory pool. However @c data
50 MUST outlive @c handles since the pool does not own its memory in this example.
51 @code
52 const size_t poolSize = 1 << 30;// 1 GB
53 void *data = std::malloc(size + NANOVDB_DATA_ALIGNMENT);// 1 GB pool with padding
54 void *buffer = nanovdb::alignPtr(data);// 32B aligned buffer
55 //void *buffer = std::aligned_alloc(NANOVDB_DATA_ALIGNMENT, poolSize);// in C++17
56 auto pool = nanovdb::HostBuffer::createPool(poolSize, buffer);
57 auto handles1 = nanovdb::io::readGrids("file1.nvdb", 0, pool);
58 auto handles2 = nanovdb::io::readGrids("file2.nvdb", 0, pool);
59 ....
60 std::free(data);
61 //std::free(buffer);
62 @endcode
63
64 Example that uses HostBuffer::createPool for externally managed host memory.
65 Note that in this example @c handles are allowed to outlive @c pool since
66 they internally store a shared pointer to the memory pool. However @c array
67 MUST outlive @c handles since the pool does not own its memory in this example.
68 @code
69 const size_t poolSize = 1 << 30;// 1 GB
70 std::unique_ptr<char[]> array(new char[size + NANOVDB_DATA_ALIGNMENT]);// scoped pool of 1 GB with padding
71 void *buffer = nanovdb::alignPtr(array.get());// 32B aligned buffer
72 auto pool = nanovdb::HostBuffer::createPool(poolSize, buffer);
73 auto handles = nanovdb::io::readGrids("file.nvdb", 0, pool);
74 @endcode
75*/
76
77#ifndef NANOVDB_HOSTBUFFER_H_HAS_BEEN_INCLUDED
78#define NANOVDB_HOSTBUFFER_H_HAS_BEEN_INCLUDED
79
80#include <nanovdb/NanoVDB.h>// for NANOVDB_DATA_ALIGNMENT;
81#include <stdint.h> // for types like int32_t etc
82#include <cstdio> // for fprintf
83#include <cstdlib> // for std::malloc/std::realloc/std::free
84#include <memory>// for std::make_shared
85#include <mutex>// for std::mutex
86#include <unordered_set>// for std::unordered_set
87#include <cassert>// for assert
88#include <sstream>// for std::stringstream
89#include <cstring>// for memcpy
90
91#define checkPtr(ptr, msg) \
92 { \
93 ptrAssert((ptr), (msg), __FILE__, __LINE__); \
94 }
95
96namespace nanovdb {
97
98template<typename BufferT>
100{
101 static constexpr bool hasDeviceDual = false;
102};
103
104// ----------------------------> HostBuffer <--------------------------------------
105
106/// @brief This is a buffer that contains a shared or private pool
107/// to either externally or internally managed host memory.
108///
109/// @note Terminology:
110/// Pool: 0 = buffer.size() < buffer.poolSize()
111/// Buffer: 0 < buffer.size() < buffer.poolSize()
112/// Full: 0 < buffer.size() = buffer.poolSize()
113/// Empty: 0 = buffer.size() = buffer.poolSize()
115{
116 struct Pool;// forward declaration of private pool struct
117 std::shared_ptr<Pool> mPool;
118 uint64_t mSize; // total number of bytes for the NanoVDB grid.
119 void* mData; // raw buffer for the NanoVDB grid.
120
121#if defined(DEBUG) || defined(_DEBUG)
122 static inline void ptrAssert(void* ptr, const char* msg, const char* file, int line, bool abort = true)
123 {
124 if (ptr == nullptr) {
125 fprintf(stderr, "NULL pointer error: %s %s %d\n", msg, file, line);
126 if (abort)
127 exit(1);
128 }
129 if (uint64_t(ptr) % NANOVDB_DATA_ALIGNMENT) {
130 fprintf(stderr, "Alignment pointer error: %s %s %d\n", msg, file, line);
131 if (abort)
132 exit(1);
133 }
134 }
135#else
136 static inline void ptrAssert(void*, const char*, const char*, int, bool = true)
137 {
138 }
139#endif
140
141public:
142 /// @brief Return a full buffer or an empty buffer
143 HostBuffer(uint64_t bufferSize = 0);
144
145 /// @brief Move copy-constructor
146 HostBuffer(HostBuffer&& other);
147
148 /// @brief Custom descructor
149 ~HostBuffer() { this->clear(); }
150
151 /// @brief Move copy assignment operation
153
154 /// @brief Disallow copy-construction
155 HostBuffer(const HostBuffer&) = delete;
156
157 /// @brief Disallow copy assignment operation
158 HostBuffer& operator=(const HostBuffer&) = delete;
159
160 /// @brief Return a pool buffer which satisfies: buffer.size == 0,
161 /// buffer.poolSize() == poolSize, and buffer.data() == nullptr.
162 /// If data==nullptr, memory for the pool will be allocated.
163 ///
164 /// @throw If poolSize is zero.
165 static HostBuffer createPool(uint64_t poolSize, void *data = nullptr);
166
167 /// @brief Return a full buffer which satisfies: buffer.size == bufferSize,
168 /// buffer.poolSize() == bufferSize, and buffer.data() == data.
169 /// If data==nullptr, memory for the pool will be allocated.
170 ///
171 /// @throw If bufferSize is zero.
172 static HostBuffer createFull(uint64_t bufferSize, void *data = nullptr);
173
174 /// @brief Return a buffer with @c bufferSize bytes managed by
175 /// the specified memory @c pool. If none is provided, i.e.
176 /// @c pool == nullptr or @c pool->poolSize() == 0, one is
177 /// created with size @c bufferSize, i.e. a full buffer is returned.
178 ///
179 /// @throw If the specified @c pool has insufficient memory for
180 /// the requested buffer size.
181 static HostBuffer create(uint64_t bufferSize, const HostBuffer* pool = nullptr);
182
183 /// @brief Initialize as a full buffer with the specified size. If data is NULL
184 /// the memory is internally allocated.
185 void init(uint64_t bufferSize, void *data = nullptr);
186
187 //@{
188 /// @brief Retuns a pointer to the raw memory buffer managed by this allocator.
189 ///
190 /// @warning Note that the pointer can be NULL if the allocator was not initialized!
191 const void* data() const { return mData; }
192 void* data() { return mData; }
193 //@}
194
195 /// @brief Returns an offset pointer of a specific type from the allocated host memory
196 /// @tparam T Type of the pointer returned
197 /// @param count Numbers of elements of @c parameter type T to skip
198 /// @warning might return NULL
199 template <typename T>
200 T* data(ptrdiff_t count = 0) const {return mData ? reinterpret_cast<T*>(mData) + count : nullptr;}
201
202 //@{
203 /// @brief Returns the size in bytes associated with this buffer.
204 uint64_t bufferSize() const { return mSize; }
205 uint64_t size() const { return this->bufferSize(); }
206 //@}
207
208 /// @brief Returns the size in bytes of the memory pool shared with this instance.
209 uint64_t poolSize() const;
210
211 /// @brief Return true if memory is managed (using std::malloc and std:free) by the
212 /// shared pool in this buffer. Else memory is assumed to be managed externally.
213 bool isManaged() const;
214
215 //@{
216 /// @brief Returns true if this buffer has no memory associated with it
217 bool isEmpty() const { return !mPool || mSize == 0 || mData == nullptr; }
218 bool empty() const { return this->isEmpty(); }
219 //@}
220
221 /// @brief Return true if this is a pool, i.e. an empty buffer with a nonempty
222 /// internal pool, i.e. this->size() == 0 and this->poolSize() != 0
223 bool isPool() const { return mSize == 0 && this->poolSize() > 0; }
224
225 /// @brief Return true if the pool exists, is nonempty but has no more available memory
226 bool isFull() const;
227
228 /// @brief Clear this buffer so it is empty.
229 void clear();
230
231 /// @brief Clears all existing buffers that are registered against the memory pool
232 /// and resets the pool so it can be reused to create new buffers.
233 ///
234 /// @throw If this instance is not empty or contains no pool.
235 ///
236 /// @warning This method is not thread-safe!
237 void reset();
238
239 /// @brief Total number of bytes from the pool currently in use by buffers
240 uint64_t poolUsage() const;
241
242 /// @brief resize the pool size. It will attempt to resize the existing
243 /// memory block, but if that fails a deep copy is performed.
244 /// If @c data is not NULL it will be used as new externally
245 /// managed memory for the pool. All registered buffers are
246 /// updated so GridHandle::grid might return a new address (if
247 /// deep copy was performed).
248 ///
249 /// @note This method can be use to resize the memory pool and even
250 /// change it from internally to externally managed memory or vice versa.
251 ///
252 /// @throw if @c poolSize is less than this->poolUsage() the used memory
253 /// or allocations fail.
254 void resizePool(uint64_t poolSize, void *data = nullptr);
255
256}; // HostBuffer class
257
258// --------------------------> Implementation of HostBuffer::Pool <------------------------------------
259
260// This is private struct of HostBuffer so you can safely ignore the API
262{
263 using HashTableT = std::unordered_set<HostBuffer*>;
264 std::mutex mMutex; // mutex for updating mRegister and mFree
266 void *mData, *mFree;
267 uint64_t mSize, mPadding;
269
270 /// @brief External memory ctor
271 Pool(uint64_t size = 0, void* data = nullptr)
272 : mData(data)
273 , mFree(mData)
274 , mSize(size)
275 , mPadding(0)
276 , mManaged(data == nullptr)
277 {
278 if (mManaged) {
279 mData = Pool::alloc(mSize);
280 if (mData == nullptr) throw std::runtime_error("Pool::Pool malloc failed");
281 }
283 if (!mManaged && mPadding != 0) {
284 throw std::runtime_error("Pool::Pool: external memory buffer is not aligned to " +
285 std::to_string(NANOVDB_DATA_ALIGNMENT) +
286 " bytes.\nHint: use nanovdb::alignPtr or std::aligned_alloc (C++17 only)");
287 }
289 }
290
291 /// @brief Custom destructor
293 {
294 assert(mRegister.empty());
295 if (mManaged) std::free(mData);
296 }
297
298 /// @brief Disallow copy-construction
299 Pool(const Pool&) = delete;
300
301 /// @brief Disallow move-construction
302 Pool(const Pool&&) = delete;
303
304 /// @brief Disallow copy assignment operation
305 Pool& operator=(const Pool&) = delete;
306
307 /// @brief Disallow move assignment operation
308 Pool& operator=(const Pool&&) = delete;
309
310 /// @brief Return the total number of bytes used from this Pool by buffers
311 uint64_t usage() const { return util::PtrDiff(mFree, mData) - mPadding; }
312
313 /// @brief Allocate a buffer of the specified size and add it to the register
314 void add(HostBuffer* buffer, uint64_t size)
315 {
316 void *alignedFree = util::PtrAdd(mFree, alignmentPadding(mFree));
317
318 if (util::PtrAdd(alignedFree, size) > util::PtrAdd(mData, mPadding + mSize)) {
319 std::stringstream ss;
320 ss << "HostBuffer::Pool: insufficient memory\n"
321 << "\tA buffer requested " << size << " bytes with " << NANOVDB_DATA_ALIGNMENT
322 << "-bytes alignment from a pool with "
323 << mSize << " bytes of which\n\t" << (util::PtrDiff(alignedFree, mData) - mPadding)
324 << " bytes are used by " << mRegister.size() << " other buffer(s). "
325 << "Pool is " << (mManaged ? "internally" : "externally") << " managed.\n";
326 throw std::runtime_error(ss.str());
327 }
328 buffer->mSize = size;
329 const std::lock_guard<std::mutex> lock(mMutex);
330 mRegister.insert(buffer);
331 buffer->mData = alignedFree;
332 mFree = util::PtrAdd(alignedFree, size);
333 }
334
335 /// @brief Remove the specified buffer from the register
336 void remove(HostBuffer *buffer)
337 {
338 const std::lock_guard<std::mutex> lock(mMutex);
339 mRegister.erase(buffer);
340 }
341
342 /// @brief Replaces buffer1 with buffer2 in the register
343 void replace(HostBuffer *buffer1, HostBuffer *buffer2)
344 {
345 const std::lock_guard<std::mutex> lock(mMutex);
346 mRegister.erase( buffer1);
347 mRegister.insert(buffer2);
348 }
349
350 /// @brief Reset the register and all its buffers
351 void reset()
352 {
353 for (HostBuffer *buffer : mRegister) {
354 buffer->mPool.reset();
355 buffer->mSize = 0;
356 buffer->mData = nullptr;
357 }
358 mRegister.clear();
360 }
361
362 /// @brief Resize this Pool and update registered buffers as needed. If data is no NULL
363 /// it is used as externally managed memory.
364 void resize(uint64_t size, void *data = nullptr)
365 {
366 const uint64_t memUsage = this->usage();
367
368 const bool managed = (data == nullptr);
369
370 if (!managed && alignmentPadding(data) != 0) {
371 throw std::runtime_error("Pool::resize: external memory buffer is not aligned to " +
372 std::to_string(NANOVDB_DATA_ALIGNMENT) + " bytes");
373 }
374
375 if (memUsage > size) {
376 throw std::runtime_error("Pool::resize: insufficient memory");
377 }
378
379 uint64_t padding = 0;
380 if (mManaged && managed && size != mSize) { // managed -> managed
381 padding = mPadding;
382 data = Pool::realloc(mData, memUsage, size, padding); // performs both copy and free of mData
383 } else if (!mManaged && managed) { // un-managed -> managed
384 data = Pool::alloc(size);
385 padding = alignmentPadding(data);
386 }
387
388 if (data == nullptr) {
389 throw std::runtime_error("Pool::resize: allocation failed");
390 } else if (data != mData) {
391 void* paddedData = util::PtrAdd(data, padding);
392
393 if (!(mManaged && managed)) { // no need to copy if managed -> managed
394 memcpy(paddedData, util::PtrAdd(mData, mPadding), memUsage);
395 }
396
397 for (HostBuffer* buffer : mRegister) { // update registered buffers
398 buffer->mData = util::PtrAdd(paddedData, util::PtrDiff(buffer->mData, util::PtrAdd(mData, mPadding)));
399 }
400 mFree = util::PtrAdd(paddedData, memUsage); // update the free pointer
401 if (mManaged && !managed) {// only free if managed -> un-managed
402 std::free(mData);
403 }
404
405 mData = data;
406 mPadding = padding;
407 }
408 mSize = size;
409 mManaged = managed;
410 }
411 /// @brief Return true is all the memory in this pool is in use.
412 bool isFull() const
413 {
414 assert(mFree <= util::PtrAdd(mData, mPadding + mSize));
415 return mSize > 0 ? mFree == util::PtrAdd(mData, mPadding + mSize) : false;
416 }
417
418private:
419
420 static void* alloc(uint64_t size)
421 {
422 // make sure we alloc enough space to align the result
423 return std::malloc(size + NANOVDB_DATA_ALIGNMENT);
424 }
425
426 static void* realloc(void* const origData,
427 uint64_t origSize,
428 uint64_t desiredSize,
429 uint64_t& padding)
430 {
431 // make sure we alloc enough space to align the result
432 void* data = std::realloc(origData, desiredSize + NANOVDB_DATA_ALIGNMENT);
433
434 if (data != nullptr && data != origData) {
435 uint64_t newPadding = alignmentPadding(data);
436 // Number of padding bytes may have changed -- move data if that's the case
437 if (newPadding != padding) {
438 // Realloc should not happen when shrinking down buffer, but let's be safe
439 std::memmove(util::PtrAdd(data, newPadding),
440 util::PtrAdd(data, padding),
441 math::Min(origSize, desiredSize));
442 padding = newPadding;
443 }
444 }
445
446 return data;
447 }
448
449};// struct HostBuffer::Pool
450
451// --------------------------> Implementation of HostBuffer <------------------------------------
452
453inline HostBuffer::HostBuffer(uint64_t size) : mPool(nullptr), mSize(size), mData(nullptr)
454{
455 if (size>0) {
456 mPool = std::make_shared<Pool>(size);
457 mData = mPool->mFree;
458 mPool->mRegister.insert(this);
459 mPool->mFree = util::PtrAdd(mPool->mFree, size);
460 }
461}
462
463inline HostBuffer::HostBuffer(HostBuffer&& other) : mPool(other.mPool), mSize(other.mSize), mData(other.mData)
464{
465 if (mPool && mSize != 0) {
466 mPool->replace(&other, this);
467 }
468 other.mPool.reset();
469 other.mSize = 0;
470 other.mData = nullptr;
471}
472
473inline void HostBuffer::init(uint64_t bufferSize, void *data)
474{
475 if (bufferSize == 0) {
476 throw std::runtime_error("HostBuffer: invalid buffer size");
477 }
478 if (mPool) {
479 mPool.reset();
480 }
481 if (!mPool || mPool->mSize != bufferSize) {
482 mPool = std::make_shared<Pool>(bufferSize, data);
483 }
484 mPool->add(this, bufferSize);
485}
486
488{
489 if (mPool) {
490 mPool->remove(this);
491 }
492 mPool = other.mPool;
493 mSize = other.mSize;
494 mData = other.mData;
495 if (mPool && mSize != 0) {
496 mPool->replace(&other, this);
497 }
498 other.mPool.reset();
499 other.mSize = 0;
500 other.mData = nullptr;
501 return *this;
502}
503
504inline uint64_t HostBuffer::poolSize() const
505{
506 return mPool ? mPool->mSize : 0u;
507}
508
509inline uint64_t HostBuffer::poolUsage() const
510{
511 return mPool ? mPool->usage(): 0u;
512}
513
514inline bool HostBuffer::isManaged() const
515{
516 return mPool ? mPool->mManaged : false;
517}
518
519inline bool HostBuffer::isFull() const
520{
521 return mPool ? mPool->isFull() : false;
522}
523
525{
526 if (poolSize == 0) {
527 throw std::runtime_error("HostBuffer: invalid pool size");
528 }
529 HostBuffer buffer;
530 buffer.mPool = std::make_shared<Pool>(poolSize, data);
531 // note the buffer is NOT registered by its pool since it is not using its memory
532 buffer.mSize = 0;
533 buffer.mData = nullptr;
534 return buffer;
535}
536
538{
539 if (bufferSize == 0) {
540 throw std::runtime_error("HostBuffer: invalid buffer size");
541 }
542 HostBuffer buffer;
543 buffer.mPool = std::make_shared<Pool>(bufferSize, data);
544 buffer.mPool->add(&buffer, bufferSize);
545 return buffer;
546}
547
549{
550 HostBuffer buffer;
551 if (pool == nullptr || !pool->mPool) {
552 buffer.mPool = std::make_shared<Pool>(bufferSize);
553 } else {
554 buffer.mPool = pool->mPool;
555 }
556 buffer.mPool->add(&buffer, bufferSize);
557 return buffer;
558}
559
560inline void HostBuffer::clear()
561{
562 if (mPool) {// remove self from the buffer register in the pool
563 mPool->remove(this);
564 }
565 mPool.reset();
566 mSize = 0;
567 mData = nullptr;
568}
569
570inline void HostBuffer::reset()
571{
572 if (this->size()>0) {
573 throw std::runtime_error("HostBuffer: only empty buffers can call reset");
574 }
575 if (!mPool) {
576 throw std::runtime_error("HostBuffer: this buffer contains no pool to reset");
577 }
578 mPool->reset();
579}
580
581inline void HostBuffer::resizePool(uint64_t size, void *data)
582{
583 if (!mPool) {
584 throw std::runtime_error("HostBuffer: this buffer contains no pool to resize");
585 }
586 mPool->resize(size, data);
587}
588
589} // namespace nanovdb
590
591#endif // end of NANOVDB_HOSTBUFFER_H_HAS_BEEN_INCLUDED
Implements a light-weight self-contained VDB data-structure in a single file! In other words,...
#define NANOVDB_DATA_ALIGNMENT
Definition NanoVDB.h:133
This is a buffer that contains a shared or private pool to either externally or internally managed ho...
Definition HostBuffer.h:115
void * data()
Definition HostBuffer.h:192
~HostBuffer()
Custom descructor.
Definition HostBuffer.h:149
HostBuffer(const HostBuffer &)=delete
Disallow copy-construction.
const void * data() const
Retuns a pointer to the raw memory buffer managed by this allocator.
Definition HostBuffer.h:191
T * data(ptrdiff_t count=0) const
Returns an offset pointer of a specific type from the allocated host memory.
Definition HostBuffer.h:200
HostBuffer(uint64_t bufferSize=0)
Return a full buffer or an empty buffer.
Definition HostBuffer.h:453
HostBuffer & operator=(HostBuffer &&other)
Move copy assignment operation.
Definition HostBuffer.h:487
uint64_t bufferSize() const
Returns the size in bytes associated with this buffer.
Definition HostBuffer.h:204
bool empty() const
Definition HostBuffer.h:218
static HostBuffer createFull(uint64_t bufferSize, void *data=nullptr)
Return a full buffer which satisfies: buffer.size == bufferSize, buffer.poolSize() == bufferSize,...
Definition HostBuffer.h:537
uint64_t poolSize() const
Returns the size in bytes of the memory pool shared with this instance.
Definition HostBuffer.h:504
uint64_t size() const
Definition HostBuffer.h:205
void init(uint64_t bufferSize, void *data=nullptr)
Initialize as a full buffer with the specified size. If data is NULL the memory is internally allocat...
Definition HostBuffer.h:473
HostBuffer & operator=(const HostBuffer &)=delete
Disallow copy assignment operation.
uint64_t poolUsage() const
Total number of bytes from the pool currently in use by buffers.
Definition HostBuffer.h:509
bool isPool() const
Return true if this is a pool, i.e. an empty buffer with a nonempty internal pool,...
Definition HostBuffer.h:223
bool isManaged() const
Return true if memory is managed (using std::malloc and std:free) by the shared pool in this buffer....
Definition HostBuffer.h:514
static HostBuffer create(uint64_t bufferSize, const HostBuffer *pool=nullptr)
Return a buffer with bufferSize bytes managed by the specified memory pool. If none is provided,...
Definition HostBuffer.h:548
void clear()
Clear this buffer so it is empty.
Definition HostBuffer.h:560
bool isEmpty() const
Returns true if this buffer has no memory associated with it.
Definition HostBuffer.h:217
void reset()
Clears all existing buffers that are registered against the memory pool and resets the pool so it can...
Definition HostBuffer.h:570
bool isFull() const
Return true if the pool exists, is nonempty but has no more available memory.
Definition HostBuffer.h:519
void resizePool(uint64_t poolSize, void *data=nullptr)
resize the pool size. It will attempt to resize the existing memory block, but if that fails a deep c...
Definition HostBuffer.h:581
static HostBuffer createPool(uint64_t poolSize, void *data=nullptr)
Return a pool buffer which satisfies: buffer.size == 0, buffer.poolSize() == poolSize,...
Definition HostBuffer.h:524
static DstT * PtrAdd(void *p, int64_t offset)
Adds a byte offset to a non-const pointer to produce another non-const pointer.
Definition Util.h:478
static int64_t PtrDiff(const void *p, const void *q)
Compute the distance, in bytes, between two pointers, dist = p - q.
Definition Util.h:464
Definition GridHandle.h:27
static __hostdev__ uint64_t alignmentPadding(const void *p)
return the smallest number of bytes that when added to the specified pointer results in a 32 byte ali...
Definition NanoVDB.h:545
Definition HostBuffer.h:100
static constexpr bool hasDeviceDual
Definition HostBuffer.h:101
Definition HostBuffer.h:262
std::unordered_set< HostBuffer * > HashTableT
Definition HostBuffer.h:263
void resize(uint64_t size, void *data=nullptr)
Resize this Pool and update registered buffers as needed. If data is no NULL it is used as externally...
Definition HostBuffer.h:364
uint64_t usage() const
Return the total number of bytes used from this Pool by buffers.
Definition HostBuffer.h:311
void replace(HostBuffer *buffer1, HostBuffer *buffer2)
Replaces buffer1 with buffer2 in the register.
Definition HostBuffer.h:343
Pool(uint64_t size=0, void *data=nullptr)
External memory ctor.
Definition HostBuffer.h:271
uint64_t mSize
Definition HostBuffer.h:267
void * mData
Definition HostBuffer.h:266
Pool(const Pool &)=delete
Disallow copy-construction.
void add(HostBuffer *buffer, uint64_t size)
Allocate a buffer of the specified size and add it to the register.
Definition HostBuffer.h:314
void remove(HostBuffer *buffer)
Remove the specified buffer from the register.
Definition HostBuffer.h:336
void * mFree
Definition HostBuffer.h:266
Pool & operator=(const Pool &&)=delete
Disallow move assignment operation.
std::mutex mMutex
Definition HostBuffer.h:264
Pool(const Pool &&)=delete
Disallow move-construction.
HashTableT mRegister
Definition HostBuffer.h:265
uint64_t mPadding
Definition HostBuffer.h:267
Pool & operator=(const Pool &)=delete
Disallow copy assignment operation.
void reset()
Reset the register and all its buffers.
Definition HostBuffer.h:351
~Pool()
Custom destructor.
Definition HostBuffer.h:292
bool isFull() const
Return true is all the memory in this pool is in use.
Definition HostBuffer.h:412
bool mManaged
Definition HostBuffer.h:268