141 ChunkHeader *chunkHead;
142 BaseAllocator* ownBaseAllocator;
147 static const size_t SIZEOF_SHARED_DATA =
RAPIDJSON_ALIGN(
sizeof(SharedData));
148 static const size_t SIZEOF_CHUNK_HEADER =
RAPIDJSON_ALIGN(
sizeof(ChunkHeader));
150 static inline ChunkHeader *GetChunkHead(SharedData *shared)
152 return reinterpret_cast<ChunkHeader*
>(
reinterpret_cast<uint8_t*
>(shared) + SIZEOF_SHARED_DATA);
154 static inline uint8_t *GetChunkBuffer(SharedData *shared)
156 return reinterpret_cast<uint8_t*
>(shared->chunkHead) + SIZEOF_CHUNK_HEADER;
171 chunk_capacity_(chunkSize),
172 baseAllocator_(baseAllocator ? baseAllocator :
RAPIDJSON_NEW(BaseAllocator)()),
173 shared_(static_cast<SharedData*>(baseAllocator_ ? baseAllocator_->
Malloc(SIZEOF_SHARED_DATA + SIZEOF_CHUNK_HEADER) : 0))
178 shared_->ownBaseAllocator = 0;
181 shared_->ownBaseAllocator = baseAllocator_;
183 shared_->chunkHead = GetChunkHead(shared_);
184 shared_->chunkHead->capacity = 0;
185 shared_->chunkHead->size = 0;
186 shared_->chunkHead->next = 0;
187 shared_->ownBuffer =
true;
188 shared_->refcount = 1;
201 MemoryPoolAllocator(
void *buffer,
size_t size,
size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) :
202 chunk_capacity_(chunkSize),
203 baseAllocator_(baseAllocator),
204 shared_(static_cast<SharedData*>(AlignBuffer(buffer, size)))
207 shared_->chunkHead = GetChunkHead(shared_);
208 shared_->chunkHead->capacity = size - SIZEOF_SHARED_DATA - SIZEOF_CHUNK_HEADER;
209 shared_->chunkHead->size = 0;
210 shared_->chunkHead->next = 0;
211 shared_->ownBaseAllocator = 0;
212 shared_->ownBuffer =
false;
213 shared_->refcount = 1;
217 chunk_capacity_(rhs.chunk_capacity_),
218 baseAllocator_(rhs.baseAllocator_),
224 MemoryPoolAllocator& operator=(
const MemoryPoolAllocator& rhs) RAPIDJSON_NOEXCEPT
227 ++rhs.shared_->refcount;
228 this->~MemoryPoolAllocator();
229 baseAllocator_ = rhs.baseAllocator_;
230 chunk_capacity_ = rhs.chunk_capacity_;
231 shared_ = rhs.shared_;
235#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
236 MemoryPoolAllocator(MemoryPoolAllocator&& rhs) RAPIDJSON_NOEXCEPT :
237 chunk_capacity_(rhs.chunk_capacity_),
238 baseAllocator_(rhs.baseAllocator_),
244 MemoryPoolAllocator& operator=(MemoryPoolAllocator&& rhs) RAPIDJSON_NOEXCEPT
247 this->~MemoryPoolAllocator();
248 baseAllocator_ = rhs.baseAllocator_;
249 chunk_capacity_ = rhs.chunk_capacity_;
250 shared_ = rhs.shared_;
264 if (shared_->refcount > 1) {
269 BaseAllocator *a = shared_->ownBaseAllocator;
270 if (shared_->ownBuffer) {
271 baseAllocator_->Free(shared_);
280 ChunkHeader* c = shared_->chunkHead;
284 shared_->chunkHead = c->next;
285 baseAllocator_->Free(c);
287 shared_->chunkHead->size = 0;
296 for (ChunkHeader* c = shared_->chunkHead; c != 0; c = c->next)
297 capacity += c->capacity;
304 size_t Size() const RAPIDJSON_NOEXCEPT {
307 for (ChunkHeader* c = shared_->chunkHead; c != 0; c = c->next)
317 return shared_->refcount > 1;
327 if (
RAPIDJSON_UNLIKELY(shared_->chunkHead->size + size > shared_->chunkHead->capacity))
328 if (!AddChunk(chunk_capacity_ > size ? chunk_capacity_ : size))
331 void *buffer = GetChunkBuffer(shared_) + shared_->chunkHead->size;
332 shared_->chunkHead->size += size;
337 void*
Realloc(
void* originalPtr,
size_t originalSize,
size_t newSize) {
338 if (originalPtr == 0)
349 if (originalSize >= newSize)
353 if (originalPtr == GetChunkBuffer(shared_) + shared_->chunkHead->size - originalSize) {
354 size_t increment =
static_cast<size_t>(newSize - originalSize);
355 if (shared_->chunkHead->size + increment <= shared_->chunkHead->capacity) {
356 shared_->chunkHead->size += increment;
362 if (
void* newBuffer =
Malloc(newSize)) {
364 std::memcpy(newBuffer, originalPtr, originalSize);
372 static void Free(
void *ptr) RAPIDJSON_NOEXCEPT { (void)ptr; }
378 return shared_ == rhs.shared_;
390 bool AddChunk(
size_t capacity) {
392 shared_->ownBaseAllocator = baseAllocator_ =
RAPIDJSON_NEW(BaseAllocator)();
393 if (ChunkHeader* chunk =
static_cast<ChunkHeader*
>(baseAllocator_->Malloc(SIZEOF_CHUNK_HEADER + capacity))) {
394 chunk->capacity = capacity;
396 chunk->next = shared_->chunkHead;
397 shared_->chunkHead = chunk;
404 static inline void* AlignBuffer(
void* buf,
size_t &size)
407 const uintptr_t mask =
sizeof(
void*) - 1;
408 const uintptr_t ubuf =
reinterpret_cast<uintptr_t
>(buf);
410 const uintptr_t abuf = (ubuf + mask) & ~mask;
412 buf =
reinterpret_cast<void*
>(abuf);
418 size_t chunk_capacity_;
419 BaseAllocator* baseAllocator_;
460 public std::allocator<T>
462 typedef std::allocator<T> allocator_type;
463#if RAPIDJSON_HAS_CXX11
464 typedef std::allocator_traits<allocator_type> traits_type;
466 typedef allocator_type traits_type;
470 typedef BaseAllocator BaseAllocatorType;
472 StdAllocator() RAPIDJSON_NOEXCEPT :
477 StdAllocator(
const StdAllocator& rhs) RAPIDJSON_NOEXCEPT :
479 baseAllocator_(rhs.baseAllocator_)
483 StdAllocator(
const StdAllocator<U, BaseAllocator>& rhs) RAPIDJSON_NOEXCEPT :
485 baseAllocator_(rhs.baseAllocator_)
488#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
489 StdAllocator(StdAllocator&& rhs) RAPIDJSON_NOEXCEPT :
490 allocator_type(std::move(rhs)),
491 baseAllocator_(std::move(rhs.baseAllocator_))
494#if RAPIDJSON_HAS_CXX11
495 using propagate_on_container_move_assignment = std::true_type;
496 using propagate_on_container_swap = std::true_type;
500 StdAllocator(
const BaseAllocator& baseAllocator) RAPIDJSON_NOEXCEPT :
502 baseAllocator_(baseAllocator)
505 ~StdAllocator() RAPIDJSON_NOEXCEPT
510 typedef StdAllocator<U, BaseAllocator> other;
513 typedef typename traits_type::size_type size_type;
514 typedef typename traits_type::difference_type difference_type;
516 typedef typename traits_type::value_type value_type;
517 typedef typename traits_type::pointer pointer;
518 typedef typename traits_type::const_pointer const_pointer;
520#if RAPIDJSON_HAS_CXX11
522 typedef typename std::add_lvalue_reference<value_type>::type &reference;
523 typedef typename std::add_lvalue_reference<typename std::add_const<value_type>::type>::type &const_reference;
525 pointer address(reference r)
const RAPIDJSON_NOEXCEPT
527 return std::addressof(r);
529 const_pointer address(const_reference r)
const RAPIDJSON_NOEXCEPT
531 return std::addressof(r);
534 size_type max_size() const RAPIDJSON_NOEXCEPT
536 return traits_type::max_size(*
this);
539 template <
typename ...Args>
540 void construct(pointer p, Args&&... args)
542 traits_type::construct(*
this, p, std::forward<Args>(args)...);
544 void destroy(pointer p)
546 traits_type::destroy(*
this, p);
551 typedef typename allocator_type::reference reference;
552 typedef typename allocator_type::const_reference const_reference;
554 pointer address(reference r)
const RAPIDJSON_NOEXCEPT
556 return allocator_type::address(r);
558 const_pointer address(const_reference r)
const RAPIDJSON_NOEXCEPT
560 return allocator_type::address(r);
563 size_type max_size() const RAPIDJSON_NOEXCEPT
565 return allocator_type::max_size();
568 void construct(pointer p, const_reference r)
570 allocator_type::construct(p, r);
572 void destroy(pointer p)
574 allocator_type::destroy(p);
579 template <
typename U>
580 U* allocate(size_type n = 1,
const void* = 0)
582 return RAPIDJSON_NAMESPACE::Malloc<U>(baseAllocator_, n);
584 template <
typename U>
585 void deallocate(U* p, size_type n = 1)
587 RAPIDJSON_NAMESPACE::Free<U>(baseAllocator_, p, n);
590 pointer allocate(size_type n = 1,
const void* = 0)
592 return allocate<value_type>(n);
594 void deallocate(pointer p, size_type n = 1)
596 deallocate<value_type>(p, n);
599#if RAPIDJSON_HAS_CXX11
600 using is_always_equal = std::is_empty<BaseAllocator>;
604 bool operator==(
const StdAllocator<U, BaseAllocator>& rhs)
const RAPIDJSON_NOEXCEPT
606 return baseAllocator_ == rhs.baseAllocator_;
609 bool operator!=(
const StdAllocator<U, BaseAllocator>& rhs)
const RAPIDJSON_NOEXCEPT
611 return !operator==(rhs);
616 static const bool kRefCounted = internal::IsRefCounted<BaseAllocator>::Value;
617 void* Malloc(
size_t size)
619 return baseAllocator_.Malloc(size);
621 void* Realloc(
void* originalPtr,
size_t originalSize,
size_t newSize)
623 return baseAllocator_.Realloc(originalPtr, originalSize, newSize);
625 static void Free(
void *ptr) RAPIDJSON_NOEXCEPT
627 BaseAllocator::Free(ptr);
631 template <
typename,
typename>
632 friend class StdAllocator;
634 BaseAllocator baseAllocator_;
639class StdAllocator<void, BaseAllocator> :
640 public std::allocator<void>
642 typedef std::allocator<void> allocator_type;
645 typedef BaseAllocator BaseAllocatorType;
647 StdAllocator() RAPIDJSON_NOEXCEPT :
652 StdAllocator(
const StdAllocator& rhs) RAPIDJSON_NOEXCEPT :
654 baseAllocator_(rhs.baseAllocator_)
658 StdAllocator(
const StdAllocator<U, BaseAllocator>& rhs) RAPIDJSON_NOEXCEPT :
660 baseAllocator_(rhs.baseAllocator_)
664 StdAllocator(
const BaseAllocator& baseAllocator) RAPIDJSON_NOEXCEPT :
666 baseAllocator_(baseAllocator)
669 ~StdAllocator() RAPIDJSON_NOEXCEPT
674 typedef StdAllocator<U, BaseAllocator> other;
677 typedef typename allocator_type::value_type value_type;
680 template <
typename,
typename>
681 friend class StdAllocator;
683 BaseAllocator baseAllocator_;