fbxcontainerallocators.h 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. /****************************************************************************************
  2. Copyright (C) 2015 Autodesk, Inc.
  3. All rights reserved.
  4. Use of this software is subject to the terms of the Autodesk license agreement
  5. provided at the time of installation or download, or which otherwise accompanies
  6. this software in either electronic or hard copy form.
  7. ****************************************************************************************/
  8. //! \file fbxcontainerallocators.h
  9. #ifndef _FBXSDK_CORE_BASE_CONTAINER_ALLOCATORS_H_
  10. #define _FBXSDK_CORE_BASE_CONTAINER_ALLOCATORS_H_
  11. #include <fbxsdk/fbxsdk_def.h>
  12. #include <fbxsdk/fbxsdk_nsbegin.h>
  13. /** An allocator class for use as a template parameter to one of the
  14. * container class (FbxMap, FbxSet, FbxDynamicArray...) must implement these.
  15. */
  16. class FBXSDK_DLL FbxBaseAllocator
  17. {
  18. public:
  19. /** The class constructor.
  20. * \param pRecordSize the size of one record held by the container.
  21. * \remarks The parameter pRecordSize is not necessarily the same
  22. * size as of the value type, since the
  23. * container may wrap the value into a private class.
  24. */
  25. FbxBaseAllocator(const size_t pRecordSize) :
  26. mRecordSize(pRecordSize)
  27. {
  28. }
  29. /** This tells the allocator that we are about to call AllocateRecords
  30. * one or many times to allocate pRecordCount records.
  31. * \param pRecordCount
  32. * \remarks This gives the allocator a chance to do whatever it deems necessary
  33. * to optimize subsequent allocations, for example, by preallocating a
  34. * sufficiently large pool of memory.
  35. */
  36. void Reserve(const size_t /*pRecordCount*/)
  37. {
  38. // By default, ignore all preallocating requests.
  39. }
  40. /** Returns a pointer to a uninitialized continuous block of memory
  41. * able to hold pRecordCount * pRecordSize bytes.
  42. * \param pRecordCount
  43. * \remarks pRecordSize was defined in the Constructor description, above.
  44. */
  45. void* AllocateRecords(const size_t pRecordCount=1)
  46. {
  47. return FbxMalloc(pRecordCount * mRecordSize);
  48. }
  49. /** Frees a block of memory returned by AllocateRecords.
  50. * \param pRecord
  51. */
  52. void FreeMemory(void* pRecord)
  53. {
  54. FbxFree(pRecord);
  55. }
  56. /** \return the size of each record allocated.
  57. */
  58. size_t GetRecordSize() const
  59. {
  60. return mRecordSize;
  61. }
  62. private:
  63. size_t mRecordSize;
  64. };
  65. /** This allocator only frees the allocated memory when it is deleted.
  66. * This is a good allocator for building dictionaries, where we only
  67. * add things to a container, but never remove them.
  68. */
  69. class FbxHungryAllocator
  70. {
  71. public:
  72. FbxHungryAllocator(size_t pRecordSize) :
  73. mRecordSize(pRecordSize),
  74. mRecordPoolSize(0),
  75. mData(NULL)
  76. {
  77. }
  78. FbxHungryAllocator(const FbxHungryAllocator& pOther) :
  79. mRecordSize(pOther.mRecordSize),
  80. mRecordPoolSize(pOther.mRecordPoolSize),
  81. mData(NULL)
  82. {
  83. }
  84. ~FbxHungryAllocator()
  85. {
  86. MemoryBlock* lCurrent = mData;
  87. MemoryBlock* lNext = lCurrent ? lCurrent->mNextBlock : 0;
  88. while (lCurrent)
  89. {
  90. FbxDelete(lCurrent);
  91. lCurrent = lNext;
  92. lNext = lCurrent ? lCurrent->mNextBlock : 0;
  93. }
  94. }
  95. void Reserve(const size_t pRecordCount)
  96. {
  97. MemoryBlock* lMem = FbxNew< MemoryBlock >(pRecordCount* mRecordSize);
  98. lMem->mNextBlock = mData;
  99. mData = lMem;
  100. mRecordPoolSize += pRecordCount;
  101. }
  102. void* AllocateRecords(const size_t pRecordCount = 1)
  103. {
  104. MemoryBlock* lBlock = mData;
  105. void* lRecord = NULL;
  106. while( (lBlock != NULL) && ((lRecord = lBlock->GetChunk(pRecordCount * mRecordSize)) == NULL) )
  107. {
  108. lBlock = lBlock->mNextBlock;
  109. }
  110. if( lRecord == NULL )
  111. {
  112. size_t lNumRecordToAllocate = mRecordPoolSize / 8 == 0 ? 2 : mRecordPoolSize / 8;
  113. if( lNumRecordToAllocate < pRecordCount )
  114. {
  115. lNumRecordToAllocate = pRecordCount;
  116. }
  117. Reserve(lNumRecordToAllocate);
  118. lRecord = AllocateRecords(pRecordCount);
  119. }
  120. return lRecord;
  121. }
  122. void FreeMemory(void* /*pRecord*/)
  123. {
  124. // "Hungry": release memory only when the allocator is destroyed.
  125. }
  126. size_t GetRecordSize() const
  127. {
  128. return mRecordSize;
  129. }
  130. FbxHungryAllocator& operator=(const FbxHungryAllocator& pOther)
  131. {
  132. if( this != &pOther )
  133. {
  134. // The next call to AllocateRecords() may skip over currently reserved
  135. // records if the size changes drastically, but otherwise GetChunk()
  136. // is size-oblivious.
  137. if( mRecordSize < pOther.mRecordSize )
  138. {
  139. mRecordPoolSize = 0;
  140. }
  141. mRecordSize = pOther.mRecordSize;
  142. }
  143. return(*this);
  144. }
  145. private:
  146. class MemoryBlock
  147. {
  148. public:
  149. MemoryBlock(size_t pSize) :
  150. mNextBlock(NULL),
  151. mData(NULL),
  152. mFreeData(NULL),
  153. mEnd(NULL)
  154. {
  155. mData = FbxMalloc(pSize);
  156. mFreeData = mData;
  157. mEnd = reinterpret_cast<char*>(mData) + pSize;
  158. }
  159. ~MemoryBlock()
  160. {
  161. FbxFree(mData);
  162. }
  163. void* GetChunk(const size_t pSize)
  164. {
  165. if( reinterpret_cast<char*>(mFreeData) + pSize < mEnd )
  166. {
  167. void* lChunk = mFreeData;
  168. mFreeData = reinterpret_cast<char*>(mFreeData) + pSize;
  169. return lChunk;
  170. }
  171. return NULL;
  172. }
  173. MemoryBlock* mNextBlock;
  174. void* mData;
  175. void* mFreeData;
  176. void* mEnd;
  177. };
  178. size_t mRecordSize;
  179. size_t mRecordPoolSize;
  180. MemoryBlock* mData;
  181. };
  182. #include <fbxsdk/fbxsdk_nsend.h>
  183. #endif /* _FBXSDK_CORE_BASE_CONTAINER_ALLOCATORS_H_ */