Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-05-20 22:39:44

0001 #ifndef JSONCPP_BATCHALLOCATOR_H_INCLUDED
0002 #define JSONCPP_BATCHALLOCATOR_H_INCLUDED
0003 
0004 #include <cassert>
0005 #include <cstdlib>
0006 
0007 #ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
0008 
0009 namespace jsoncollector {
0010   namespace Json {
0011 
0012     /* Fast memory allocator.
0013  *
0014  * This memory allocator allocates memory for a batch of object (specified by
0015  * the page size, the number of object in each page).
0016  *
0017  * It does not allow the destruction of a single object. All the allocated objects
0018  * can be destroyed at once. The memory can be either released or reused for future
0019  * allocation.
0020  * 
0021  * The in-place new operator must be used to construct the object using the pointer
0022  * returned by allocate.
0023  */
0024     template <typename AllocatedType, const unsigned int objectPerAllocation>
0025     class BatchAllocator {
0026     public:
0027       typedef AllocatedType Type;
0028 
0029       BatchAllocator(unsigned int objectsPerPage = 255) : freeHead_(0), objectsPerPage_(objectsPerPage) {
0030         //      printf( "Size: %d => %s\n", sizeof(AllocatedType), typeid(AllocatedType).name() );
0031         assert(sizeof(AllocatedType) * objectPerAllocation >=
0032                sizeof(AllocatedType *));  // We must be able to store a slist in the object free space.
0033         assert(objectsPerPage >= 16);
0034         batches_ = allocateBatch(0);  // allocated a dummy page
0035         currentBatch_ = batches_;
0036       }
0037 
0038       ~BatchAllocator() {
0039         for (BatchInfo *batch = batches_; batch;) {
0040           BatchInfo *nextBatch = batch->next_;
0041           free(batch);
0042           batch = nextBatch;
0043         }
0044       }
0045 
0046       /// allocate space for an array of objectPerAllocation object.
0047       /// @warning it is the responsability of the caller to call objects constructors.
0048       AllocatedType *allocate() {
0049         if (freeHead_)  // returns node from free list.
0050         {
0051           AllocatedType *object = freeHead_;
0052           freeHead_ = *(AllocatedType **)object;
0053           return object;
0054         }
0055         if (currentBatch_->used_ == currentBatch_->end_) {
0056           currentBatch_ = currentBatch_->next_;
0057           while (currentBatch_ && currentBatch_->used_ == currentBatch_->end_)
0058             currentBatch_ = currentBatch_->next_;
0059 
0060           if (!currentBatch_)  // no free batch found, allocate a new one
0061           {
0062             currentBatch_ = allocateBatch(objectsPerPage_);
0063             currentBatch_->next_ = batches_;  // insert at the head of the list
0064             batches_ = currentBatch_;
0065           }
0066         }
0067         AllocatedType *allocated = currentBatch_->used_;
0068         currentBatch_->used_ += objectPerAllocation;
0069         return allocated;
0070       }
0071 
0072       /// Release the object.
0073       /// @warning it is the responsability of the caller to actually destruct the object.
0074       void release(AllocatedType *object) {
0075         assert(object != 0);
0076         *(AllocatedType **)object = freeHead_;
0077         freeHead_ = object;
0078       }
0079 
0080       // disabled copy constructor and assignement operator.
0081       BatchAllocator(const BatchAllocator &) = delete;
0082       void operator=(const BatchAllocator &) = delete;
0083 
0084     private:
0085       struct BatchInfo {
0086         BatchInfo *next_;
0087         AllocatedType *used_;
0088         AllocatedType *end_;
0089         AllocatedType buffer_[objectPerAllocation];
0090       };
0091 
0092       static BatchInfo *allocateBatch(unsigned int objectsPerPage) {
0093         const unsigned int mallocSize = sizeof(BatchInfo) - sizeof(AllocatedType) * objectPerAllocation +
0094                                         sizeof(AllocatedType) * objectPerAllocation * objectsPerPage;
0095         BatchInfo *batch = static_cast<BatchInfo *>(malloc(mallocSize));
0096         batch->next_ = 0;
0097         batch->used_ = batch->buffer_;
0098         batch->end_ = batch->buffer_ + objectsPerPage;
0099         return batch;
0100       }
0101 
0102       BatchInfo *batches_;
0103       BatchInfo *currentBatch_;
0104       /// Head of a single linked list within the allocated space of freeed object
0105       AllocatedType *freeHead_;
0106       unsigned int objectsPerPage_;
0107     };
0108 
0109   }  // namespace Json
0110 }  //namespace jsoncollector
0111 
0112 #endif  // ifndef JSONCPP_DOC_INCLUDE_IMPLEMENTATION
0113 
0114 #endif  // JSONCPP_BATCHALLOCATOR_H_INCLUDED