73 #ifndef NANOVDB_HOSTBUFFER_H_HAS_BEEN_INCLUDED 74 #define NANOVDB_HOSTBUFFER_H_HAS_BEEN_INCLUDED 81 #include <unordered_set> 86 #define checkPtr(ptr, msg) \ 88 ptrAssert((ptr), (msg), __FILE__, __LINE__); \ 93 template<
typename BufferT>
112 std::shared_ptr<Pool> mPool;
116 #if defined(DEBUG) || defined(_DEBUG) 117 static inline void ptrAssert(
void* ptr,
const char* msg,
const char* file,
int line,
bool abort =
true)
119 if (ptr ==
nullptr) {
120 fprintf(stderr,
"NULL pointer error: %s %s %d\n", msg, file, line);
126 static inline void ptrAssert(
void*,
const char*,
const char*,
int,
bool =
true)
155 static HostBuffer createPool(uint64_t poolSize,
void *data =
nullptr);
162 static HostBuffer createFull(uint64_t bufferSize,
void *data =
nullptr);
175 void init(uint64_t bufferSize,
void *data =
nullptr);
181 const uint8_t*
data()
const {
return mData; }
182 uint8_t*
data() {
return mData; }
188 uint64_t
size()
const {
return this->bufferSize(); }
192 uint64_t poolSize()
const;
196 bool isManaged()
const;
200 bool isEmpty()
const {
return !mPool || mSize == 0 || mData ==
nullptr; }
201 bool empty()
const {
return this->isEmpty(); }
206 bool isPool()
const {
return mSize == 0 && this->poolSize() > 0; }
223 uint64_t poolUsage()
const;
237 void resizePool(uint64_t poolSize,
void *data =
nullptr);
255 Pool(uint64_t size = 0,
void *data =
nullptr) : mData((uint8_t*)data), mFree(mData), mSize(size), mManaged(data==nullptr)
258 mData = mFree =
static_cast<uint8_t*
>(std::malloc(size));
259 if (mData ==
nullptr) {
260 throw std::runtime_error(
"Pool::Pool malloc failed");
268 assert(mRegister.empty());
281 Pool& operator=(
const Pool&) =
delete;
284 Pool& operator=(
const Pool&&) =
delete;
287 uint64_t
usage()
const {
return static_cast<uint64_t
>(mFree - mData); }
292 if (mFree + size > mData + mSize) {
293 std::stringstream ss;
294 ss <<
"HostBuffer::Pool: insufficient memory\n" 295 <<
"\tA buffer requested " << size <<
" bytes from a pool with " 296 << mSize <<
" bytes of which\n\t" << (mFree-mData)
297 <<
" bytes are used by " << mRegister.size() <<
" other buffer(s). " 298 <<
"Pool is " << (mManaged ?
"internally" :
"externally") <<
" managed.\n";
300 throw std::runtime_error(ss.str());
302 buffer->mSize = size;
303 const std::lock_guard<std::mutex> lock(mMutex);
304 mRegister.insert(buffer);
305 buffer->mData = mFree;
312 const std::lock_guard<std::mutex> lock(mMutex);
313 mRegister.erase(buffer);
319 const std::lock_guard<std::mutex> lock(mMutex);
320 mRegister.erase( buffer1);
321 mRegister.insert(buffer2);
328 buffer->mPool.reset();
330 buffer->mData =
nullptr;
338 void resize(uint64_t size,
void *data =
nullptr)
340 const uint64_t
memUsage = this->usage();
341 if (memUsage > size) {
342 throw std::runtime_error(
"Pool::resize: insufficient memory");
344 const bool managed = (data ==
nullptr);
345 if (mManaged && managed && size != mSize) {
346 data = std::realloc(mData, size);
347 }
else if (!mManaged && managed) {
348 data = std::malloc(size);
350 if (data ==
nullptr) {
351 throw std::runtime_error(
"Pool::resize: allocation failed");
352 }
else if (data != mData) {
353 if (!(mManaged && managed)) {
354 memcpy(data, mData, memUsage);
357 buffer->mData =
static_cast<uint8_t*
>(data) + ptrdiff_t(buffer->mData - mData);
359 mFree =
static_cast<uint8_t*
>(data) + memUsage;
360 if (mManaged && !managed) {
363 mData =
static_cast<uint8_t*
>(data);
371 assert(mFree <= mData + mSize);
372 return mSize > 0 ? mFree == mData + mSize :
false;
381 mPool = std::make_shared<Pool>(
size);
382 mData = mPool->mFree;
383 mPool->mRegister.insert(
this);
384 mPool->mFree +=
size;
390 if (mPool && mSize != 0) {
391 mPool->replace(&other,
this);
395 other.mData =
nullptr;
400 if (bufferSize == 0) {
401 throw std::runtime_error(
"HostBuffer: invalid buffer size");
406 if (!mPool || mPool->mSize != bufferSize) {
409 mPool->add(
this, bufferSize);
420 if (mPool && mSize != 0) {
421 mPool->replace(&other,
this);
425 other.mData =
nullptr;
431 return mPool ? mPool->mSize : 0u;
436 return mPool ? mPool->usage(): 0u;
441 return mPool ? mPool->mManaged :
false;
446 return mPool ? mPool->isFull() :
false;
452 throw std::runtime_error(
"HostBuffer: invalid pool size");
458 buffer.mData =
nullptr;
464 if (bufferSize == 0) {
465 throw std::runtime_error(
"HostBuffer: invalid buffer size");
469 buffer.mPool->add(&buffer, bufferSize);
476 if (pool ==
nullptr || !pool->mPool) {
477 buffer.mPool = std::make_shared<Pool>(
bufferSize);
479 buffer.mPool = pool->mPool;
481 buffer.mPool->add(&buffer, bufferSize);
497 if (this->
size()>0) {
498 throw std::runtime_error(
"HostBuffer: only empty buffers can call reset");
501 throw std::runtime_error(
"HostBuffer: this buffer contains no pool to reset");
509 throw std::runtime_error(
"HostBuffer: this buffer contains no pool to resize");
511 mPool->resize(size, data);
516 #endif // end of NANOVDB_HOSTBUFFER_H_HAS_BEEN_INCLUDED
Definition: HostBuffer.h:94
void reset()
Reset the register and all its buffers.
Definition: HostBuffer.h:325
void replace(HostBuffer *buffer1, HostBuffer *buffer2)
Replaces buffer1 with buffer2 in the register.
Definition: HostBuffer.h:317
void add(HostBuffer *buffer, uint64_t size)
Allocate a buffer of the specified size and add it to the register.
Definition: HostBuffer.h:290
HashTableT mRegister
Definition: HostBuffer.h:248
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:338
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:449
~HostBuffer()
Custom descructor.
Definition: HostBuffer.h:139
uint64_t poolSize() const
Returns the size in bytes of the memory pool shared with this instance.
Definition: HostBuffer.h:429
std::mutex mMutex
Definition: HostBuffer.h:247
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:398
bool isFull() const
Return true is all the memory in this pool is in use.
Definition: HostBuffer.h:369
Definition: NanoVDB.h:184
Pool(uint64_t size=0, void *data=nullptr)
External memory ctor.
Definition: HostBuffer.h:255
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:206
Definition: HostBuffer.h:244
void clear()
Clear this buffer so it is empty.
Definition: HostBuffer.h:485
static HostBuffer createFull(uint64_t bufferSize, void *data=nullptr)
Return a full buffer which satisfies: buffer.size == bufferSize, buffer.poolSize() == bufferSize...
Definition: HostBuffer.h:462
HostBuffer & operator=(HostBuffer &&other)
Move copy assignment operation.
Definition: HostBuffer.h:412
uint64_t poolUsage() const
Total number of bytes from the pool currently in use by buffers.
Definition: HostBuffer.h:434
uint8_t * mData
Definition: HostBuffer.h:249
static const bool hasDeviceDual
Definition: HostBuffer.h:96
This is a buffer that contains a shared or private pool to either externally or internally managed ho...
Definition: HostBuffer.h:109
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:439
uint64_t size() const
Returns the size in bytes associated with this buffer.
Definition: HostBuffer.h:188
bool mManaged
Definition: HostBuffer.h:252
uint8_t * mFree
Definition: HostBuffer.h:250
void reset()
Clears all existing buffers that are registered against the memory pool and resets the pool so it can...
Definition: HostBuffer.h:495
const uint8_t * data() const
Retuns a pointer to the raw memory buffer managed by this allocator.
Definition: HostBuffer.h:181
uint64_t bufferSize() const
Returns the size in bytes associated with this buffer.
Definition: HostBuffer.h:187
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:506
uint8_t * data()
Retuns a pointer to the raw memory buffer managed by this allocator.
Definition: HostBuffer.h:182
uint64_t usage() const
Return the total number of bytes used from this Pool by buffers.
Definition: HostBuffer.h:287
bool empty() const
Returns true if this buffer has no memory associated with it.
Definition: HostBuffer.h:201
HostBuffer(uint64_t bufferSize=0)
Return a full buffer or an empty buffer.
Definition: HostBuffer.h:378
bool isFull() const
Return true if the pool exists, is nonempty but has no more available memory.
Definition: HostBuffer.h:444
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:473
~Pool()
Custom destructor.
Definition: HostBuffer.h:266
std::unordered_set< HostBuffer * > HashTableT
Definition: HostBuffer.h:246
uint64_t mSize
Definition: HostBuffer.h:251
bool isEmpty() const
Returns true if this buffer has no memory associated with it.
Definition: HostBuffer.h:200