OpenVDB  12.1.0
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 
96 namespace nanovdb {
97 
98 template<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 
141 public:
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
152  HostBuffer& operator=(HostBuffer&& other);
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;
268  bool mManaged;
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  }
282  mPadding = alignmentPadding(mData);
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  }
288  mFree = util::PtrAdd(mData, mPadding);
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();
359  mFree = util::PtrAdd(mData, mPadding);
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 
418 private:
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 
453 inline 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 
463 inline 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 
473 inline 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 
504 inline uint64_t HostBuffer::poolSize() const
505 {
506  return mPool ? mPool->mSize : 0u;
507 }
508 
509 inline uint64_t HostBuffer::poolUsage() const
510 {
511  return mPool ? mPool->usage(): 0u;
512 }
513 
514 inline bool HostBuffer::isManaged() const
515 {
516  return mPool ? mPool->mManaged : false;
517 }
518 
519 inline 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 
548 inline HostBuffer HostBuffer::create(uint64_t bufferSize, const HostBuffer* pool)
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 
560 inline 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 
570 inline 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 
581 inline 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
Definition: HostBuffer.h:99
void reset()
Reset the register and all its buffers.
Definition: HostBuffer.h:351
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
void replace(HostBuffer *buffer1, HostBuffer *buffer2)
Replaces buffer1 with buffer2 in the register.
Definition: HostBuffer.h:343
void add(HostBuffer *buffer, uint64_t size)
Allocate a buffer of the specified size and add it to the register.
Definition: HostBuffer.h:314
HashTableT mRegister
Definition: HostBuffer.h:265
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
static HostBuffer createPool(uint64_t poolSize, void *data=nullptr)
Return a pool buffer which satisfies: buffer.size == 0, buffer.poolSize() == poolSize, and buffer.data() == nullptr. If data==nullptr, memory for the pool will be allocated.
Definition: HostBuffer.h:524
~HostBuffer()
Custom descructor.
Definition: HostBuffer.h:149
void * mFree
Definition: HostBuffer.h:266
uint64_t poolSize() const
Returns the size in bytes of the memory pool shared with this instance.
Definition: HostBuffer.h:504
#define NANOVDB_DATA_ALIGNMENT
Definition: NanoVDB.h:133
void * data()
Retuns a pointer to the raw memory buffer managed by this allocator.
Definition: HostBuffer.h:192
std::mutex mMutex
Definition: HostBuffer.h:264
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
Implements a light-weight self-contained VDB data-structure in a single file! In other words...
bool isFull() const
Return true is all the memory in this pool is in use.
Definition: HostBuffer.h:412
Definition: GridHandle.h:27
Pool(uint64_t size=0, void *data=nullptr)
External memory ctor.
Definition: HostBuffer.h:271
Index64 memUsage(const TreeT &tree, bool threaded=true)
Return the total amount of memory in bytes occupied by this tree.
Definition: Count.h:493
bool isPool() const
Return true if this is a pool, i.e. an empty buffer with a nonempty internal pool, i.e. this->size() == 0 and this->poolSize() != 0.
Definition: HostBuffer.h:223
static constexpr bool hasDeviceDual
Definition: HostBuffer.h:101
Definition: HostBuffer.h:261
void clear()
Clear this buffer so it is empty.
Definition: HostBuffer.h:560
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
HostBuffer & operator=(HostBuffer &&other)
Move copy assignment operation.
Definition: HostBuffer.h:487
uint64_t poolUsage() const
Total number of bytes from the pool currently in use by buffers.
Definition: HostBuffer.h:509
This is a buffer that contains a shared or private pool to either externally or internally managed ho...
Definition: HostBuffer.h:114
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
uint64_t size() const
Returns the size in bytes associated with this buffer.
Definition: HostBuffer.h:205
bool mManaged
Definition: HostBuffer.h:268
void reset()
Clears all existing buffers that are registered against the memory pool and resets the pool so it can...
Definition: HostBuffer.h:570
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
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
const Type & Min(const Type &a, const Type &b)
Return the minimum of two values.
Definition: Math.h:656
uint64_t bufferSize() const
Returns the size in bytes associated with this buffer.
Definition: HostBuffer.h:204
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
const void * data() const
Retuns a pointer to the raw memory buffer managed by this allocator.
Definition: HostBuffer.h:191
uint64_t usage() const
Return the total number of bytes used from this Pool by buffers.
Definition: HostBuffer.h:311
bool empty() const
Returns true if this buffer has no memory associated with it.
Definition: HostBuffer.h:218
HostBuffer(uint64_t bufferSize=0)
Return a full buffer or an empty buffer.
Definition: HostBuffer.h:453
bool isFull() const
Return true if the pool exists, is nonempty but has no more available memory.
Definition: HostBuffer.h:519
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
~Pool()
Custom destructor.
Definition: HostBuffer.h:292
std::unordered_set< HostBuffer * > HashTableT
Definition: HostBuffer.h:263
uint64_t mSize
Definition: HostBuffer.h:267
T * data(ptrdiff_t count=0) const
Returns an offset pointer of a specific type from the allocated host memory.
Definition: HostBuffer.h:200
bool isEmpty() const
Returns true if this buffer has no memory associated with it.
Definition: HostBuffer.h:217