77 #ifndef NANOVDB_HOSTBUFFER_H_HAS_BEEN_INCLUDED 78 #define NANOVDB_HOSTBUFFER_H_HAS_BEEN_INCLUDED 86 #include <unordered_set> 91 #define checkPtr(ptr, msg) \ 93 ptrAssert((ptr), (msg), __FILE__, __LINE__); \ 98 template<
typename BufferT>
117 std::shared_ptr<Pool> mPool;
121 #if defined(DEBUG) || defined(_DEBUG) 122 static inline void ptrAssert(
void* ptr,
const char* msg,
const char* file,
int line,
bool abort =
true)
124 if (ptr ==
nullptr) {
125 fprintf(stderr,
"NULL pointer error: %s %s %d\n", msg, file, line);
130 fprintf(stderr,
"Alignment pointer error: %s %s %d\n", msg, file, line);
136 static inline void ptrAssert(
void*,
const char*,
const char*,
int,
bool =
true)
165 static HostBuffer createPool(uint64_t poolSize,
void *data =
nullptr);
172 static HostBuffer createFull(uint64_t bufferSize,
void *data =
nullptr);
185 void init(uint64_t bufferSize,
void *data =
nullptr);
191 const void*
data()
const {
return mData; }
199 template <
typename T>
200 T*
data(ptrdiff_t count = 0)
const {
return mData ?
reinterpret_cast<T*
>(mData) + count :
nullptr;}
205 uint64_t
size()
const {
return this->bufferSize(); }
209 uint64_t poolSize()
const;
213 bool isManaged()
const;
217 bool isEmpty()
const {
return !mPool || mSize == 0 || mData ==
nullptr; }
218 bool empty()
const {
return this->isEmpty(); }
223 bool isPool()
const {
return mSize == 0 && this->poolSize() > 0; }
240 uint64_t poolUsage()
const;
254 void resizePool(uint64_t poolSize,
void *data =
nullptr);
271 Pool(uint64_t size = 0,
void* data =
nullptr)
276 , mManaged(data == nullptr)
279 mData = Pool::alloc(mSize);
280 if (mData ==
nullptr)
throw std::runtime_error(
"Pool::Pool malloc failed");
283 if (!mManaged && mPadding != 0) {
284 throw std::runtime_error(
"Pool::Pool: external memory buffer is not aligned to " +
286 " bytes.\nHint: use nanovdb::alignPtr or std::aligned_alloc (C++17 only)");
294 assert(mRegister.empty());
295 if (mManaged) std::free(mData);
305 Pool& operator=(
const Pool&) =
delete;
308 Pool& operator=(
const Pool&&) =
delete;
319 std::stringstream ss;
320 ss <<
"HostBuffer::Pool: insufficient memory\n" 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());
328 buffer->mSize = size;
329 const std::lock_guard<std::mutex> lock(mMutex);
330 mRegister.insert(buffer);
331 buffer->mData = alignedFree;
338 const std::lock_guard<std::mutex> lock(mMutex);
339 mRegister.erase(buffer);
345 const std::lock_guard<std::mutex> lock(mMutex);
346 mRegister.erase( buffer1);
347 mRegister.insert(buffer2);
354 buffer->mPool.reset();
356 buffer->mData =
nullptr;
364 void resize(uint64_t size,
void *data =
nullptr)
366 const uint64_t
memUsage = this->usage();
368 const bool managed = (data ==
nullptr);
371 throw std::runtime_error(
"Pool::resize: external memory buffer is not aligned to " +
375 if (memUsage > size) {
376 throw std::runtime_error(
"Pool::resize: insufficient memory");
379 uint64_t padding = 0;
380 if (mManaged && managed && size != mSize) {
382 data = Pool::realloc(mData, memUsage, size, padding);
383 }
else if (!mManaged && managed) {
384 data = Pool::alloc(size);
388 if (data ==
nullptr) {
389 throw std::runtime_error(
"Pool::resize: allocation failed");
390 }
else if (data != mData) {
393 if (!(mManaged && managed)) {
394 memcpy(paddedData,
util::PtrAdd(mData, mPadding), memUsage);
401 if (mManaged && !managed) {
415 return mSize > 0 ? mFree ==
util::PtrAdd(mData, mPadding + mSize) :
false;
420 static void* alloc(uint64_t size)
426 static void* realloc(
void*
const origData,
428 uint64_t desiredSize,
434 if (data !=
nullptr && data != origData) {
437 if (newPadding != padding) {
442 padding = newPadding;
456 mPool = std::make_shared<Pool>(
size);
457 mData = mPool->mFree;
458 mPool->mRegister.insert(
this);
465 if (mPool && mSize != 0) {
466 mPool->replace(&other,
this);
470 other.mData =
nullptr;
475 if (bufferSize == 0) {
476 throw std::runtime_error(
"HostBuffer: invalid buffer size");
481 if (!mPool || mPool->mSize != bufferSize) {
484 mPool->add(
this, bufferSize);
495 if (mPool && mSize != 0) {
496 mPool->replace(&other,
this);
500 other.mData =
nullptr;
506 return mPool ? mPool->mSize : 0u;
511 return mPool ? mPool->usage(): 0u;
516 return mPool ? mPool->mManaged :
false;
521 return mPool ? mPool->isFull() :
false;
527 throw std::runtime_error(
"HostBuffer: invalid pool size");
533 buffer.mData =
nullptr;
539 if (bufferSize == 0) {
540 throw std::runtime_error(
"HostBuffer: invalid buffer size");
544 buffer.mPool->add(&buffer, bufferSize);
551 if (pool ==
nullptr || !pool->mPool) {
552 buffer.mPool = std::make_shared<Pool>(
bufferSize);
554 buffer.mPool = pool->mPool;
556 buffer.mPool->add(&buffer, bufferSize);
572 if (this->
size()>0) {
573 throw std::runtime_error(
"HostBuffer: only empty buffers can call reset");
576 throw std::runtime_error(
"HostBuffer: this buffer contains no pool to reset");
584 throw std::runtime_error(
"HostBuffer: this buffer contains no pool to resize");
586 mPool->resize(size, data);
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
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