json_batchallocator.h 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. #ifndef JSONCPP_BATCHALLOCATOR_H_INCLUDED
  2. # define JSONCPP_BATCHALLOCATOR_H_INCLUDED
  3. # include <stdlib.h>
  4. # include <assert.h>
  5. # ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
  6. namespace Json {
  7. /* Fast memory allocator.
  8. *
  9. * This memory allocator allocates memory for a batch of object (specified by
  10. * the page size, the number of object in each page).
  11. *
  12. * It does not allow the destruction of a single object. All the allocated objects
  13. * can be destroyed at once. The memory can be either released or reused for future
  14. * allocation.
  15. *
  16. * The in-place new operator must be used to construct the object using the pointer
  17. * returned by allocate.
  18. */
  19. template<typename AllocatedType
  20. ,const unsigned int objectPerAllocation>
  21. class BatchAllocator
  22. {
  23. public:
  24. typedef AllocatedType Type;
  25. BatchAllocator( unsigned int objectsPerPage = 255 )
  26. : freeHead_( 0 )
  27. , objectsPerPage_( objectsPerPage )
  28. {
  29. // printf( "Size: %d => %s\n", sizeof(AllocatedType), typeid(AllocatedType).name() );
  30. assert( sizeof(AllocatedType) * objectPerAllocation >= sizeof(AllocatedType *) ); // We must be able to store a slist in the object free space.
  31. assert( objectsPerPage >= 16 );
  32. batches_ = allocateBatch( 0 ); // allocated a dummy page
  33. currentBatch_ = batches_;
  34. }
  35. ~BatchAllocator()
  36. {
  37. for ( BatchInfo *batch = batches_; batch; )
  38. {
  39. BatchInfo *nextBatch = batch->next_;
  40. free( batch );
  41. batch = nextBatch;
  42. }
  43. }
  44. /// allocate space for an array of objectPerAllocation object.
  45. /// @warning it is the responsability of the caller to call objects constructors.
  46. AllocatedType *allocate()
  47. {
  48. if ( freeHead_ ) // returns node from free list.
  49. {
  50. AllocatedType *object = freeHead_;
  51. freeHead_ = *(AllocatedType **)object;
  52. return object;
  53. }
  54. if ( currentBatch_->used_ == currentBatch_->end_ )
  55. {
  56. currentBatch_ = currentBatch_->next_;
  57. while ( currentBatch_ && currentBatch_->used_ == currentBatch_->end_ )
  58. currentBatch_ = currentBatch_->next_;
  59. if ( !currentBatch_ ) // no free batch found, allocate a new one
  60. {
  61. currentBatch_ = allocateBatch( objectsPerPage_ );
  62. currentBatch_->next_ = batches_; // insert at the head of the list
  63. batches_ = currentBatch_;
  64. }
  65. }
  66. AllocatedType *allocated = currentBatch_->used_;
  67. currentBatch_->used_ += objectPerAllocation;
  68. return allocated;
  69. }
  70. /// Release the object.
  71. /// @warning it is the responsability of the caller to actually destruct the object.
  72. void release( AllocatedType *object )
  73. {
  74. assert( object != 0 );
  75. *(AllocatedType **)object = freeHead_;
  76. freeHead_ = object;
  77. }
  78. private:
  79. struct BatchInfo
  80. {
  81. BatchInfo *next_;
  82. AllocatedType *used_;
  83. AllocatedType *end_;
  84. AllocatedType buffer_[objectPerAllocation];
  85. };
  86. // disabled copy constructor and assignement operator.
  87. BatchAllocator( const BatchAllocator & );
  88. void operator =( const BatchAllocator &);
  89. static BatchInfo *allocateBatch( unsigned int objectsPerPage )
  90. {
  91. const unsigned int mallocSize = sizeof(BatchInfo) - sizeof(AllocatedType)* objectPerAllocation
  92. + sizeof(AllocatedType) * objectPerAllocation * objectsPerPage;
  93. BatchInfo *batch = static_cast<BatchInfo*>( malloc( mallocSize ) );
  94. batch->next_ = 0;
  95. batch->used_ = batch->buffer_;
  96. batch->end_ = batch->buffer_ + objectsPerPage;
  97. return batch;
  98. }
  99. BatchInfo *batches_;
  100. BatchInfo *currentBatch_;
  101. /// Head of a single linked list within the allocated space of freeed object
  102. AllocatedType *freeHead_;
  103. unsigned int objectsPerPage_;
  104. };
  105. } // namespace Json
  106. # endif // ifndef JSONCPP_DOC_INCLUDE_IMPLEMENTATION
  107. #endif // JSONCPP_BATCHALLOCATOR_H_INCLUDED