diff --git a/include/flatbuffers/flatbuffers.h b/include/flatbuffers/flatbuffers.h index da1c2c9c2..107dc250e 100644 --- a/include/flatbuffers/flatbuffers.h +++ b/include/flatbuffers/flatbuffers.h @@ -402,20 +402,39 @@ class Allocator { // DefaultAllocator uses new/delete to allocate memory regions class DefaultAllocator : public Allocator { public: - virtual uint8_t *allocate(size_t size) FLATBUFFERS_OVERRIDE { + uint8_t *allocate(size_t size) FLATBUFFERS_OVERRIDE { return new uint8_t[size]; } - virtual void deallocate(uint8_t *p, size_t) FLATBUFFERS_OVERRIDE { + void deallocate(uint8_t *p, size_t) FLATBUFFERS_OVERRIDE { delete[] p; } - - static DefaultAllocator &instance() { - static DefaultAllocator inst; - return inst; - } }; +// These functions allow for a null allocator to mean use the default allocator, +// as used by DetachedBuffer and vector_downward below. +// This is to avoid having a statically or dynamically allocated default +// allocator, or having to move it between the classes that may own it. +inline uint8_t *Allocate(Allocator *allocator, size_t size) { + return allocator ? allocator->allocate(size) + : DefaultAllocator().allocate(size); +} + +inline void Deallocate(Allocator *allocator, uint8_t *p, size_t size) { + if (allocator) allocator->deallocate(p, size); + else DefaultAllocator().deallocate(p, size); +} + +inline uint8_t *ReallocateDownward(Allocator *allocator, uint8_t *old_p, + size_t old_size, size_t new_size, + size_t in_use_back, size_t in_use_front) { + return allocator + ? allocator->reallocate_downward(old_p, old_size, new_size, + in_use_back, in_use_front) + : DefaultAllocator().reallocate_downward(old_p, old_size, new_size, + in_use_back, in_use_front); +} + // DetachedBuffer is a finished flatbuffer memory region, detached from its // builder. The original memory region and allocator are also stored so that // the DetachedBuffer can manage the memory lifetime. @@ -436,9 +455,7 @@ class DetachedBuffer { buf_(buf), reserved_(reserved), cur_(cur), - size_(sz) { - FLATBUFFERS_ASSERT(allocator_); - } + size_(sz) {} DetachedBuffer(DetachedBuffer &&other) : allocator_(other.allocator_), @@ -507,12 +524,8 @@ class DetachedBuffer { size_t size_; inline void destroy() { - if (buf_) { - FLATBUFFERS_ASSERT(allocator_); - allocator_->deallocate(buf_, reserved_); - } + if (buf_) Deallocate(allocator_, buf_, reserved_); if (own_allocator_ && allocator_) { delete allocator_; } - reset(); } @@ -538,29 +551,23 @@ class vector_downward { Allocator *allocator, bool own_allocator, size_t buffer_minalign) - : allocator_(allocator ? allocator : &DefaultAllocator::instance()), + : allocator_(allocator), own_allocator_(own_allocator), initial_size_(initial_size), buffer_minalign_(buffer_minalign), reserved_(0), buf_(nullptr), cur_(nullptr), - scratch_(nullptr) { - FLATBUFFERS_ASSERT(allocator_); - } + scratch_(nullptr) {} ~vector_downward() { - if (buf_) { - FLATBUFFERS_ASSERT(allocator_); - allocator_->deallocate(buf_, reserved_); - } + if (buf_) Deallocate(allocator_, buf_, reserved_); if (own_allocator_ && allocator_) { delete allocator_; } } void reset() { if (buf_) { - FLATBUFFERS_ASSERT(allocator_); - allocator_->deallocate(buf_, reserved_); + Deallocate(allocator_, buf_, reserved_); buf_ = nullptr; } clear(); @@ -606,7 +613,8 @@ class vector_downward { return cur_; } - Allocator &get_allocator() { return *allocator_; } + // Returns nullptr if using the DefaultAllocator. + Allocator *get_custom_allocator() { return allocator_; } uoffset_t size() const { return static_cast(reserved_ - (cur_ - buf_)); @@ -681,7 +689,6 @@ class vector_downward { uint8_t *scratch_; // Points to the end of the scratchpad in use. void reallocate(size_t len) { - FLATBUFFERS_ASSERT(allocator_); auto old_reserved = reserved_; auto old_size = size(); auto old_scratch_size = scratch_size(); @@ -689,10 +696,10 @@ class vector_downward { old_reserved ? old_reserved / 2 : initial_size_); reserved_ = (reserved_ + buffer_minalign_ - 1) & ~(buffer_minalign_ - 1); if (buf_) { - buf_ = allocator_->reallocate_downward(buf_, old_reserved, reserved_, - old_size, old_scratch_size); + buf_ = ReallocateDownward(allocator_, buf_, old_reserved, reserved_, + old_size, old_scratch_size); } else { - buf_ = allocator_->allocate(reserved_); + buf_ = Allocate(allocator_, reserved_); } cur_ = buf_ + reserved_ - old_size; scratch_ = buf_ + old_scratch_size; @@ -730,8 +737,8 @@ class FlatBufferBuilder { /// @brief Default constructor for FlatBufferBuilder. /// @param[in] initial_size The initial size of the buffer, in bytes. Defaults /// to `1024`. - /// @param[in] allocator An `Allocator` to use. Defaults to a new instance of - /// a `DefaultAllocator`. + /// @param[in] allocator An `Allocator` to use. If null will use + /// `DefaultAllocator`. /// @param[in] own_allocator Whether the builder/vector should own the /// allocator. Defaults to / `false`. /// @param[in] buffer_minalign Force the buffer to be aligned to the given