OpenVDB 13.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#include <type_traits>// for std::void_t
91
92#define checkPtr(ptr, msg) \
93 { \
94 ptrAssert((ptr), (msg), __FILE__, __LINE__); \
95 }
96
97namespace nanovdb {
98
99template<typename BufferT>
101{
102 static constexpr bool hasDeviceDual = false;
103 static constexpr bool hasDeviceSingle = false;
104};
105
106/// @brief Detects whether @c BufferTraits<BufferT> defines @c hasDeviceSingle,
107/// i.e. whether the buffer manages a single device-resident allocation.
108/// @details Defaults to false when the trait member is absent, so pre-existing
109/// BufferTraits specializations (in or out of tree) that only define
110/// hasDeviceDual keep compiling unchanged.
111template<typename BufferT, typename = void>
112struct BufferHasDeviceSingle { static constexpr bool value = false; };
113template<typename BufferT>
114struct BufferHasDeviceSingle<BufferT, std::void_t<decltype(BufferTraits<BufferT>::hasDeviceSingle)>>
116
117/// @brief Companion detection for BufferTraits<...>::hasHostSingle: a
118/// single-space buffer whose storage is host-accessible (e.g. a
119/// pinned-resource cuda::Buffer).
120template<typename BufferT, typename = void>
121struct BufferHasHostSingle { static constexpr bool value = false; };
122template<typename BufferT>
123struct BufferHasHostSingle<BufferT, std::void_t<decltype(BufferTraits<BufferT>::hasHostSingle)>>
124{ static constexpr bool value = BufferTraits<BufferT>::hasHostSingle; };
125
126/// @brief A single-space buffer whose storage the host cannot read: the
127/// device-single family minus its host-accessible members (managed or
128/// pinned resources). This is the predicate that gates the handles'
129/// host accessors off.
130template<typename BufferT>
133
134/// @brief Detects whether a buffer exposes a retained stream (a stream()
135/// member), i.e. whether its resource is stream-ordered. Used to pick
136/// the buffer's stream-taking constructor without naming CUDA types.
137template<typename BufferT, typename = void>
138struct BufferHasStream { static constexpr bool value = false; };
139template<typename BufferT>
140struct BufferHasStream<BufferT, std::void_t<decltype(std::declval<const BufferT&>().stream())>>
141{ static constexpr bool value = true; };
142
143/// @brief Detects whether a buffer's elements are byte-sized. Buffers that
144/// expose no ElementType (e.g. HostBuffer) address raw bytes by
145/// definition, so the primary defaults to true.
146template<typename BufferT, typename = void>
147struct BufferHasByteElements { static constexpr bool value = true; };
148template<typename BufferT>
149struct BufferHasByteElements<BufferT, std::void_t<typename BufferT::ElementType>>
150{ static constexpr bool value = sizeof(typename BufferT::ElementType) == 1; };
151
152/// @brief Detects whether a buffer type is default-constructible, so
153/// consumers can name that requirement in a static_assert instead of
154/// failing wherever the default construction happens to occur.
155template<typename BufferT, typename = void>
156struct BufferIsDefaultConstructible { static constexpr bool value = false; };
157template<typename BufferT>
158struct BufferIsDefaultConstructible<BufferT, std::void_t<decltype(BufferT())>>
159{ static constexpr bool value = true; };
160
161/// @brief Detects whether a buffer provides destroy(), the cuda::Buffer
162/// spelling for releasing its storage. Handle reset() dispatches to it
163/// when present and falls back to the legacy clear() otherwise.
164template<typename BufferT, typename = void>
165struct BufferHasDestroy { static constexpr bool value = false; };
166template<typename BufferT>
167struct BufferHasDestroy<BufferT, std::void_t<decltype(std::declval<BufferT&>().destroy())>>
168{ static constexpr bool value = true; };
169
170// ----------------------------> HostBuffer <--------------------------------------
171
172/// @brief This is a buffer that contains a shared or private pool
173/// to either externally or internally managed host memory.
174///
175/// @note Terminology:
176/// Pool: 0 = buffer.size() < buffer.poolSize()
177/// Buffer: 0 < buffer.size() < buffer.poolSize()
178/// Full: 0 < buffer.size() = buffer.poolSize()
179/// Empty: 0 = buffer.size() = buffer.poolSize()
181{
182 struct Pool;// forward declaration of private pool struct
183 std::shared_ptr<Pool> mPool;
184 uint64_t mSize; // total number of bytes for the NanoVDB grid.
185 void* mData; // raw buffer for the NanoVDB grid.
186
187#if defined(DEBUG) || defined(_DEBUG)
188 static inline void ptrAssert(void* ptr, const char* msg, const char* file, int line, bool abort = true)
189 {
190 if (ptr == nullptr) {
191 fprintf(stderr, "NULL pointer error: %s %s %d\n", msg, file, line);
192 if (abort)
193 exit(1);
194 }
195 if (uint64_t(ptr) % NANOVDB_DATA_ALIGNMENT) {
196 fprintf(stderr, "Alignment pointer error: %s %s %d\n", msg, file, line);
197 if (abort)
198 exit(1);
199 }
200 }
201#else
202 static inline void ptrAssert(void*, const char*, const char*, int, bool = true)
203 {
204 }
205#endif
206
207public:
208 /// @brief Return a full buffer or an empty buffer
209 HostBuffer(uint64_t bufferSize = 0);
210
211 /// @brief Move copy-constructor
212 HostBuffer(HostBuffer&& other);
213
214 /// @brief Custom descructor
215 ~HostBuffer() { this->clear(); }
216
217 /// @brief Move copy assignment operation
219
220 /// @brief Disallow copy-construction
221 HostBuffer(const HostBuffer&) = delete;
222
223 /// @brief Disallow copy assignment operation
224 HostBuffer& operator=(const HostBuffer&) = delete;
225
226 /// @brief Return a pool buffer which satisfies: buffer.size == 0,
227 /// buffer.poolSize() == poolSize, and buffer.data() == nullptr.
228 /// If data==nullptr, memory for the pool will be allocated.
229 ///
230 /// @throw If poolSize is zero.
231 static HostBuffer createPool(uint64_t poolSize, void *data = nullptr);
232
233 /// @brief Return a full buffer which satisfies: buffer.size == bufferSize,
234 /// buffer.poolSize() == bufferSize, and buffer.data() == data.
235 /// If data==nullptr, memory for the pool will be allocated.
236 ///
237 /// @throw If bufferSize is zero.
238 static HostBuffer createFull(uint64_t bufferSize, void *data = nullptr);
239
240 /// @brief Return a buffer with @c bufferSize bytes managed by
241 /// the specified memory @c pool. If none is provided, i.e.
242 /// @c pool == nullptr or @c pool->poolSize() == 0, one is
243 /// created with size @c bufferSize, i.e. a full buffer is returned.
244 ///
245 /// @throw If the specified @c pool has insufficient memory for
246 /// the requested buffer size.
247 static HostBuffer create(uint64_t bufferSize, const HostBuffer* pool = nullptr);
248
249 /// @brief Initialize as a full buffer with the specified size. If data is NULL
250 /// the memory is internally allocated.
251 void init(uint64_t bufferSize, void *data = nullptr);
252
253 //@{
254 /// @brief Retuns a pointer to the raw memory buffer managed by this allocator.
255 ///
256 /// @warning Note that the pointer can be NULL if the allocator was not initialized!
257 const void* data() const { return mData; }
258 void* data() { return mData; }
259 //@}
260
261 /// @brief Returns an offset pointer of a specific type from the allocated host memory
262 /// @tparam T Type of the pointer returned
263 /// @param count Numbers of elements of @c parameter type T to skip
264 /// @warning might return NULL
265 template <typename T>
266 T* data(ptrdiff_t count = 0) const {return mData ? reinterpret_cast<T*>(mData) + count : nullptr;}
267
268 //@{
269 /// @brief Returns the size in bytes associated with this buffer.
270 uint64_t bufferSize() const { return mSize; }
271 uint64_t size() const { return this->bufferSize(); }
272 //@}
273
274 /// @brief Returns the size in bytes of the memory pool shared with this instance.
275 uint64_t poolSize() const;
276
277 /// @brief Return true if memory is managed (using std::malloc and std:free) by the
278 /// shared pool in this buffer. Else memory is assumed to be managed externally.
279 bool isManaged() const;
280
281 //@{
282 /// @brief Returns true if this buffer has no memory associated with it
283 bool isEmpty() const { return !mPool || mSize == 0 || mData == nullptr; }
284 bool empty() const { return this->isEmpty(); }
285 //@}
286
287 /// @brief Return true if this is a pool, i.e. an empty buffer with a nonempty
288 /// internal pool, i.e. this->size() == 0 and this->poolSize() != 0
289 bool isPool() const { return mSize == 0 && this->poolSize() > 0; }
290
291 /// @brief Return true if the pool exists, is nonempty but has no more available memory
292 bool isFull() const;
293
294 /// @brief Clear this buffer so it is empty.
295 void clear();
296
297 /// @brief Clears all existing buffers that are registered against the memory pool
298 /// and resets the pool so it can be reused to create new buffers.
299 ///
300 /// @throw If this instance is not empty or contains no pool.
301 ///
302 /// @warning This method is not thread-safe!
303 void reset();
304
305 /// @brief Total number of bytes from the pool currently in use by buffers
306 uint64_t poolUsage() const;
307
308 /// @brief resize the pool size. It will attempt to resize the existing
309 /// memory block, but if that fails a deep copy is performed.
310 /// If @c data is not NULL it will be used as new externally
311 /// managed memory for the pool. All registered buffers are
312 /// updated so GridHandle::grid might return a new address (if
313 /// deep copy was performed).
314 ///
315 /// @note This method can be use to resize the memory pool and even
316 /// change it from internally to externally managed memory or vice versa.
317 ///
318 /// @throw if @c poolSize is less than this->poolUsage() the used memory
319 /// or allocations fail.
320 void resizePool(uint64_t poolSize, void *data = nullptr);
321
322}; // HostBuffer class
323
324// --------------------------> Implementation of HostBuffer::Pool <------------------------------------
325
326// This is private struct of HostBuffer so you can safely ignore the API
328{
329 using HashTableT = std::unordered_set<HostBuffer*>;
330 std::mutex mMutex; // mutex for updating mRegister and mFree
332 void *mData, *mFree;
333 uint64_t mSize, mPadding;
335
336 /// @brief External memory ctor
337 Pool(uint64_t size = 0, void* data = nullptr)
338 : mData(data)
339 , mFree(mData)
340 , mSize(size)
341 , mPadding(0)
342 , mManaged(data == nullptr)
343 {
344 if (mManaged) {
345 mData = Pool::alloc(mSize);
346 if (mData == nullptr) throw std::runtime_error("Pool::Pool malloc failed");
347 }
349 if (!mManaged && mPadding != 0) {
350 throw std::runtime_error("Pool::Pool: external memory buffer is not aligned to " +
351 std::to_string(NANOVDB_DATA_ALIGNMENT) +
352 " bytes.\nHint: use nanovdb::alignPtr or std::aligned_alloc (C++17 only)");
353 }
355 }
356
357 /// @brief Custom destructor
359 {
360 assert(mRegister.empty());
361 if (mManaged) std::free(mData);
362 }
363
364 /// @brief Disallow copy-construction
365 Pool(const Pool&) = delete;
366
367 /// @brief Disallow move-construction
368 Pool(const Pool&&) = delete;
369
370 /// @brief Disallow copy assignment operation
371 Pool& operator=(const Pool&) = delete;
372
373 /// @brief Disallow move assignment operation
374 Pool& operator=(const Pool&&) = delete;
375
376 /// @brief Return the total number of bytes used from this Pool by buffers
377 uint64_t usage() const { return util::PtrDiff(mFree, mData) - mPadding; }
378
379 /// @brief Allocate a buffer of the specified size and add it to the register
380 void add(HostBuffer* buffer, uint64_t size)
381 {
382 void *alignedFree = util::PtrAdd(mFree, alignmentPadding(mFree));
383
384 if (util::PtrAdd(alignedFree, size) > util::PtrAdd(mData, mPadding + mSize)) {
385 std::stringstream ss;
386 ss << "HostBuffer::Pool: insufficient memory\n"
387 << "\tA buffer requested " << size << " bytes with " << NANOVDB_DATA_ALIGNMENT
388 << "-bytes alignment from a pool with "
389 << mSize << " bytes of which\n\t" << (util::PtrDiff(alignedFree, mData) - mPadding)
390 << " bytes are used by " << mRegister.size() << " other buffer(s). "
391 << "Pool is " << (mManaged ? "internally" : "externally") << " managed.\n";
392 throw std::runtime_error(ss.str());
393 }
394 buffer->mSize = size;
395 const std::lock_guard<std::mutex> lock(mMutex);
396 mRegister.insert(buffer);
397 buffer->mData = alignedFree;
398 mFree = util::PtrAdd(alignedFree, size);
399 }
400
401 /// @brief Remove the specified buffer from the register
402 void remove(HostBuffer *buffer)
403 {
404 const std::lock_guard<std::mutex> lock(mMutex);
405 mRegister.erase(buffer);
406 }
407
408 /// @brief Replaces buffer1 with buffer2 in the register
409 void replace(HostBuffer *buffer1, HostBuffer *buffer2)
410 {
411 const std::lock_guard<std::mutex> lock(mMutex);
412 mRegister.erase( buffer1);
413 mRegister.insert(buffer2);
414 }
415
416 /// @brief Reset the register and all its buffers
417 void reset()
418 {
419 for (HostBuffer *buffer : mRegister) {
420 buffer->mPool.reset();
421 buffer->mSize = 0;
422 buffer->mData = nullptr;
423 }
424 mRegister.clear();
426 }
427
428 /// @brief Resize this Pool and update registered buffers as needed. If data is no NULL
429 /// it is used as externally managed memory.
430 void resize(uint64_t size, void *data = nullptr)
431 {
432 const uint64_t memUsage = this->usage();
433
434 const bool managed = (data == nullptr);
435
436 if (!managed && alignmentPadding(data) != 0) {
437 throw std::runtime_error("Pool::resize: external memory buffer is not aligned to " +
438 std::to_string(NANOVDB_DATA_ALIGNMENT) + " bytes");
439 }
440
441 if (memUsage > size) {
442 throw std::runtime_error("Pool::resize: insufficient memory");
443 }
444
445 uint64_t padding = 0;
446 if (mManaged && managed && size != mSize) { // managed -> managed
447 padding = mPadding;
448 data = Pool::realloc(mData, memUsage, size, padding); // performs both copy and free of mData
449 } else if (!mManaged && managed) { // un-managed -> managed
450 data = Pool::alloc(size);
451 padding = alignmentPadding(data);
452 }
453
454 if (data == nullptr) {
455 throw std::runtime_error("Pool::resize: allocation failed");
456 } else if (data != mData) {
457 void* paddedData = util::PtrAdd(data, padding);
458
459 if (!(mManaged && managed)) { // no need to copy if managed -> managed
460 memcpy(paddedData, util::PtrAdd(mData, mPadding), memUsage);
461 }
462
463 for (HostBuffer* buffer : mRegister) { // update registered buffers
464 buffer->mData = util::PtrAdd(paddedData, util::PtrDiff(buffer->mData, util::PtrAdd(mData, mPadding)));
465 }
466 mFree = util::PtrAdd(paddedData, memUsage); // update the free pointer
467 if (mManaged && !managed) {// only free if managed -> un-managed
468 std::free(mData);
469 }
470
471 mData = data;
472 mPadding = padding;
473 }
474 mSize = size;
475 mManaged = managed;
476 }
477 /// @brief Return true is all the memory in this pool is in use.
478 bool isFull() const
479 {
480 assert(mFree <= util::PtrAdd(mData, mPadding + mSize));
481 return mSize > 0 ? mFree == util::PtrAdd(mData, mPadding + mSize) : false;
482 }
483
484private:
485
486 static void* alloc(uint64_t size)
487 {
488 // make sure we alloc enough space to align the result
489 return std::malloc(size + NANOVDB_DATA_ALIGNMENT);
490 }
491
492 static void* realloc(void* const origData,
493 uint64_t origSize,
494 uint64_t desiredSize,
495 uint64_t& padding)
496 {
497 // make sure we alloc enough space to align the result
498 void* data = std::realloc(origData, desiredSize + NANOVDB_DATA_ALIGNMENT);
499
500 if (data != nullptr && data != origData) {
501 uint64_t newPadding = alignmentPadding(data);
502 // Number of padding bytes may have changed -- move data if that's the case
503 if (newPadding != padding) {
504 // Realloc should not happen when shrinking down buffer, but let's be safe
505 std::memmove(util::PtrAdd(data, newPadding),
506 util::PtrAdd(data, padding),
507 math::Min(origSize, desiredSize));
508 padding = newPadding;
509 }
510 }
511
512 return data;
513 }
514
515};// struct HostBuffer::Pool
516
517// --------------------------> Implementation of HostBuffer <------------------------------------
518
519inline HostBuffer::HostBuffer(uint64_t size) : mPool(nullptr), mSize(size), mData(nullptr)
520{
521 if (size>0) {
522 mPool = std::make_shared<Pool>(size);
523 mData = mPool->mFree;
524 mPool->mRegister.insert(this);
525 mPool->mFree = util::PtrAdd(mPool->mFree, size);
526 }
527}
528
529inline HostBuffer::HostBuffer(HostBuffer&& other) : mPool(other.mPool), mSize(other.mSize), mData(other.mData)
530{
531 if (mPool && mSize != 0) {
532 mPool->replace(&other, this);
533 }
534 other.mPool.reset();
535 other.mSize = 0;
536 other.mData = nullptr;
537}
538
539inline void HostBuffer::init(uint64_t bufferSize, void *data)
540{
541 if (bufferSize == 0) {
542 throw std::runtime_error("HostBuffer: invalid buffer size");
543 }
544 if (mPool) {
545 mPool.reset();
546 }
547 if (!mPool || mPool->mSize != bufferSize) {
548 mPool = std::make_shared<Pool>(bufferSize, data);
549 }
550 mPool->add(this, bufferSize);
551}
552
554{
555 if (mPool) {
556 mPool->remove(this);
557 }
558 mPool = other.mPool;
559 mSize = other.mSize;
560 mData = other.mData;
561 if (mPool && mSize != 0) {
562 mPool->replace(&other, this);
563 }
564 other.mPool.reset();
565 other.mSize = 0;
566 other.mData = nullptr;
567 return *this;
568}
569
570inline uint64_t HostBuffer::poolSize() const
571{
572 return mPool ? mPool->mSize : 0u;
573}
574
575inline uint64_t HostBuffer::poolUsage() const
576{
577 return mPool ? mPool->usage(): 0u;
578}
579
580inline bool HostBuffer::isManaged() const
581{
582 return mPool ? mPool->mManaged : false;
583}
584
585inline bool HostBuffer::isFull() const
586{
587 return mPool ? mPool->isFull() : false;
588}
589
591{
592 if (poolSize == 0) {
593 throw std::runtime_error("HostBuffer: invalid pool size");
594 }
595 HostBuffer buffer;
596 buffer.mPool = std::make_shared<Pool>(poolSize, data);
597 // note the buffer is NOT registered by its pool since it is not using its memory
598 buffer.mSize = 0;
599 buffer.mData = nullptr;
600 return buffer;
601}
602
604{
605 if (bufferSize == 0) {
606 throw std::runtime_error("HostBuffer: invalid buffer size");
607 }
608 HostBuffer buffer;
609 buffer.mPool = std::make_shared<Pool>(bufferSize, data);
610 buffer.mPool->add(&buffer, bufferSize);
611 return buffer;
612}
613
615{
616 HostBuffer buffer;
617 if (pool == nullptr || !pool->mPool) {
618 buffer.mPool = std::make_shared<Pool>(bufferSize);
619 } else {
620 buffer.mPool = pool->mPool;
621 }
622 buffer.mPool->add(&buffer, bufferSize);
623 return buffer;
624}
625
626inline void HostBuffer::clear()
627{
628 if (mPool) {// remove self from the buffer register in the pool
629 mPool->remove(this);
630 }
631 mPool.reset();
632 mSize = 0;
633 mData = nullptr;
634}
635
636inline void HostBuffer::reset()
637{
638 if (this->size()>0) {
639 throw std::runtime_error("HostBuffer: only empty buffers can call reset");
640 }
641 if (!mPool) {
642 throw std::runtime_error("HostBuffer: this buffer contains no pool to reset");
643 }
644 mPool->reset();
645}
646
647inline void HostBuffer::resizePool(uint64_t size, void *data)
648{
649 if (!mPool) {
650 throw std::runtime_error("HostBuffer: this buffer contains no pool to resize");
651 }
652 mPool->resize(size, data);
653}
654
655} // namespace nanovdb
656
657#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:181
void * data()
Definition HostBuffer.h:258
~HostBuffer()
Custom descructor.
Definition HostBuffer.h:215
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:257
T * data(ptrdiff_t count=0) const
Returns an offset pointer of a specific type from the allocated host memory.
Definition HostBuffer.h:266
HostBuffer(uint64_t bufferSize=0)
Return a full buffer or an empty buffer.
Definition HostBuffer.h:519
HostBuffer & operator=(HostBuffer &&other)
Move copy assignment operation.
Definition HostBuffer.h:553
uint64_t bufferSize() const
Returns the size in bytes associated with this buffer.
Definition HostBuffer.h:270
bool empty() const
Definition HostBuffer.h:284
static HostBuffer createFull(uint64_t bufferSize, void *data=nullptr)
Return a full buffer which satisfies: buffer.size == bufferSize, buffer.poolSize() == bufferSize,...
Definition HostBuffer.h:603
uint64_t poolSize() const
Returns the size in bytes of the memory pool shared with this instance.
Definition HostBuffer.h:570
uint64_t size() const
Definition HostBuffer.h:271
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:539
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:575
bool isPool() const
Return true if this is a pool, i.e. an empty buffer with a nonempty internal pool,...
Definition HostBuffer.h:289
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:580
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:614
void clear()
Clear this buffer so it is empty.
Definition HostBuffer.h:626
bool isEmpty() const
Returns true if this buffer has no memory associated with it.
Definition HostBuffer.h:283
void reset()
Clears all existing buffers that are registered against the memory pool and resets the pool so it can...
Definition HostBuffer.h:636
bool isFull() const
Return true if the pool exists, is nonempty but has no more available memory.
Definition HostBuffer.h:585
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:647
static HostBuffer createPool(uint64_t poolSize, void *data=nullptr)
Return a pool buffer which satisfies: buffer.size == 0, buffer.poolSize() == poolSize,...
Definition HostBuffer.h:590
__hostdev__ Type Min(Type a, Type b)
Definition Math.h:133
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:524
static int64_t PtrDiff(const void *p, const void *q)
Compute the distance, in bytes, between two pointers, dist = p - q.
Definition Util.h:510
Defines a simple memory pool used to call cub functions that use dynamic temporary storage.
Definition GridHandle.h:31
static 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:603
Definition Coord.h:590
static void ptrAssert(const void *ptr, const char *msg, const char *file, int line, bool abort=true)
Definition Util.h:32
Detects whether a buffer's elements are byte-sized. Buffers that expose no ElementType (e....
Definition HostBuffer.h:147
static constexpr bool value
Definition HostBuffer.h:147
Detects whether a buffer provides destroy(), the cuda::Buffer spelling for releasing its storage....
Definition HostBuffer.h:165
static constexpr bool value
Definition HostBuffer.h:165
Detects whether BufferTraits<BufferT> defines hasDeviceSingle, i.e. whether the buffer manages a sing...
Definition HostBuffer.h:112
static constexpr bool value
Definition HostBuffer.h:112
Companion detection for BufferTraits<...>::hasHostSingle: a single-space buffer whose storage is host...
Definition HostBuffer.h:121
static constexpr bool value
Definition HostBuffer.h:121
Detects whether a buffer exposes a retained stream (a stream() member), i.e. whether its resource is ...
Definition HostBuffer.h:138
static constexpr bool value
Definition HostBuffer.h:138
Detects whether a buffer type is default-constructible, so consumers can name that requirement in a s...
Definition HostBuffer.h:156
static constexpr bool value
Definition HostBuffer.h:156
A single-space buffer whose storage the host cannot read: the device-single family minus its host-acc...
Definition HostBuffer.h:132
static constexpr bool value
Definition HostBuffer.h:132
Definition HostBuffer.h:101
static constexpr bool hasDeviceSingle
Definition HostBuffer.h:103
static constexpr bool hasDeviceDual
Definition HostBuffer.h:102
Definition HostBuffer.h:328
std::unordered_set< HostBuffer * > HashTableT
Definition HostBuffer.h:329
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:430
uint64_t usage() const
Return the total number of bytes used from this Pool by buffers.
Definition HostBuffer.h:377
void replace(HostBuffer *buffer1, HostBuffer *buffer2)
Replaces buffer1 with buffer2 in the register.
Definition HostBuffer.h:409
Pool(uint64_t size=0, void *data=nullptr)
External memory ctor.
Definition HostBuffer.h:337
uint64_t mSize
Definition HostBuffer.h:333
void * mData
Definition HostBuffer.h:332
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:380
void remove(HostBuffer *buffer)
Remove the specified buffer from the register.
Definition HostBuffer.h:402
void * mFree
Definition HostBuffer.h:332
Pool & operator=(const Pool &&)=delete
Disallow move assignment operation.
std::mutex mMutex
Definition HostBuffer.h:330
Pool(const Pool &&)=delete
Disallow move-construction.
HashTableT mRegister
Definition HostBuffer.h:331
uint64_t mPadding
Definition HostBuffer.h:333
Pool & operator=(const Pool &)=delete
Disallow copy assignment operation.
void reset()
Reset the register and all its buffers.
Definition HostBuffer.h:417
~Pool()
Custom destructor.
Definition HostBuffer.h:358
bool isFull() const
Return true is all the memory in this pool is in use.
Definition HostBuffer.h:478
bool mManaged
Definition HostBuffer.h:334