// Tencent is pleased to support the open source community by making RapidJSON available. // // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. // // Licensed under the MIT License (the "License"); you may not use this file except // in compliance with the License. You may obtain a copy of the License at // // http://opensource.org/licenses/MIT // // Unless required by applicable law or agreed to in writing, software distributed // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR // CONDITIONS OF ANY KIND, either express or implied. See the License for the // specific language governing permissions and limitations under the License.
\code conceptAllocator{ staticconstboolkNeedFree;//!< Whether this allocator needs to call Free().
// Allocate a memory block. // \param size of the memory block in bytes. // \returns pointer to the memory block. void*Malloc(size_tsize);
// Resize a memory block. // \param originalPtr The pointer to current memory block. Null pointer is permitted. // \param originalSize The current size in bytes. (Design issue: since some allocator may not book-keep this, explicitly pass to it can save memory.) // \param newSize the new size in bytes. void*Realloc(void*originalPtr,size_toriginalSize,size_tnewSize);
// Free a memory block. // \param pointer to the memory block. Null pointer is permitted. staticvoidFree(void*ptr); }; \endcode
*/
\tparamBaseAllocatortheallocatortypeforallocatingmemorychunks.DefaultisCrtAllocator. \noteimplementsAllocatorconcept
*/ template <typename BaseAllocator = CrtAllocator> class MemoryPoolAllocator { public: staticconstbool kNeedFree = false; //!< Tell users that no need to call Free() with this allocator. (concept Allocator)
//! Constructor with chunkSize. /*! \param chunkSize The size of memory chunk. The default is kDefaultChunkSize. \parambaseAllocatorTheallocatorforallocatingmemorychunks.
*/
MemoryPoolAllocator(size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) :
chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(0), baseAllocator_(baseAllocator), ownBaseAllocator_(0)
{
}
//! Constructor with user-supplied buffer. /*! The user buffer will be used firstly. When it is full, memory pool allocates new chunk with chunk size.
//! Destructor. /*! This deallocates all memory chunks, excluding the user-supplied buffer.
*/
~MemoryPoolAllocator() {
Clear();
RAPIDJSON_DELETE(ownBaseAllocator_);
}
//! Deallocates all memory chunks, excluding the user-supplied buffer. void Clear() { while (chunkHead_ && chunkHead_ != userBuffer_) {
ChunkHeader* next = chunkHead_->next;
baseAllocator_->Free(chunkHead_);
chunkHead_ = next;
} if (chunkHead_ && chunkHead_ == userBuffer_)
chunkHead_->size = 0; // Clear user buffer
}
//! Computes the total capacity of allocated memory chunks. /*! \return total capacity in bytes.
*/
size_t Capacity() const {
size_t capacity = 0; for (ChunkHeader* c = chunkHead_; c != 0; c = c->next)
capacity += c->capacity; return capacity;
}
//! Computes the memory blocks allocated. /*! \return total used bytes.
*/
size_t Size() const {
size_t size = 0; for (ChunkHeader* c = chunkHead_; c != 0; c = c->next)
size += c->size; return size;
}
//! Allocates a memory block. (concept Allocator) void* Malloc(size_t size) { if (!size) return NULL;
// Do not shrink if new size is smaller than original if (originalSize >= newSize) return originalPtr;
// Simply expand it if it is the last allocation and there is sufficient space if (originalPtr == (char *)(chunkHead_) + RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + chunkHead_->size - originalSize) {
size_t increment = static_cast<size_t>(newSize - originalSize);
increment = RAPIDJSON_ALIGN(increment); if (chunkHead_->size + increment <= chunkHead_->capacity) {
chunkHead_->size += increment; return originalPtr;
}
}
// Realloc process: allocate and copy memory, do not free original buffer. void* newBuffer = Malloc(newSize);
RAPIDJSON_ASSERT(newBuffer != 0); // Do not handle out-of-memory explicitly. if (originalSize)
std::memcpy(newBuffer, originalPtr, originalSize); return newBuffer;
}
//! Frees a memory block (concept Allocator) staticvoid Free(void *ptr) { (void)ptr; } // Do nothing
private: //! Copy constructor is not permitted.
MemoryPoolAllocator(const MemoryPoolAllocator& rhs) /* = delete */; //! Copy assignment operator is not permitted.
MemoryPoolAllocator& operator=(const MemoryPoolAllocator& rhs) /* = delete */;
//! Creates a new chunk. /*! \param capacity Capacity of the chunk in bytes.
*/ void AddChunk(size_t capacity) { if (!baseAllocator_)
ownBaseAllocator_ = baseAllocator_ = RAPIDJSON_NEW(BaseAllocator());
ChunkHeader* chunk = reinterpret_cast<ChunkHeader*>(baseAllocator_->Malloc(RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + capacity));
chunk->capacity = capacity;
chunk->size = 0;
chunk->next = chunkHead_;
chunkHead_ = chunk;
}
//! Chunk header for perpending to each chunk. /*! Chunks are stored as a singly linked list.
*/ struct ChunkHeader {
size_t capacity; //!< Capacity of the chunk in bytes (excluding the header itself).
size_t size; //!< Current size of allocated memory in bytes.
ChunkHeader *next; //!< Next chunk in the linked list.
};
ChunkHeader *chunkHead_; //!< Head of the chunk linked-list. Only the head chunk serves allocation.
size_t chunk_capacity_; //!< The minimum capacity of chunk when they are allocated. void *userBuffer_; //!< User supplied buffer.
BaseAllocator* baseAllocator_; //!< base allocator for allocating memory chunks.
BaseAllocator* ownBaseAllocator_; //!< base allocator created by this object.
};
RAPIDJSON_NAMESPACE_END
#endif// RAPIDJSON_ENCODINGS_H_
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.1 Sekunden
(vorverarbeitet am 2026-06-17)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.