BVB Source Codes

CRYENGINE Show ParticleFixedSizeElementPool.cpp Source code

Return Download CRYENGINE: download ParticleFixedSizeElementPool.cpp Source code - Download CRYENGINE Source code - Type:.cpp
  1. // Copyright 2001-2016 Crytek GmbH / Crytek Group. All rights reserved.
  2.  
  3. // -------------------------------------------------------------------------
  4. //  File name:   ParticleFixedSizeElementPool.cpp
  5. //  Version:     v1.00
  6. //  Created:     15/03/2010 by Corey.
  7. //  Compilers:   Visual Studio.NET
  8. //  Description: A fragmentation-free allocator from a fixed-size pool and which
  9. //                                                       only allocates elements of the same size.
  10. // -------------------------------------------------------------------------
  11. //  History:
  12. //
  13. ////////////////////////////////////////////////////////////////////////////
  14.  
  15. #include "StdAfx.h"
  16. #include "ParticleFixedSizeElementPool.h"
  17. #include "ParticleUtils.h"
  18.  
  19. ///////////////////////////////////////////////////////////////////////////////
  20. ParticleObjectPool::ParticleObjectPool() :
  21.         m_pPoolMemory(NULL),
  22.         m_nPoolCapacity(0)
  23. {
  24.         CryInitializeSListHead(m_freeList4KB);
  25.         CryInitializeSListHead(m_freeList128Bytes);
  26.         CryInitializeSListHead(m_freeList256Bytes);
  27.         CryInitializeSListHead(m_freeList512Bytes);
  28.  
  29. #if defined(TRACK_PARTICLE_POOL_USAGE)
  30.         m_nUsedMemory = 0;
  31.         m_nMaxUsedMemory = 0;
  32.         m_nMemory128Bytes = 0;
  33.         m_nMemory256Bytes = 0;
  34.         m_nMemory512Bytes = 0;
  35.         m_nMemory128BytesUsed = 0;
  36.         m_nMemory256BytesUsed = 0;
  37.         m_nMemory512Bytesused = 0;
  38. #endif
  39. }
  40.  
  41. ///////////////////////////////////////////////////////////////////////////////
  42. ParticleObjectPool::~ParticleObjectPool()
  43. {
  44.         CryInterlockedFlushSList(m_freeList4KB);
  45.         CryInterlockedFlushSList(m_freeList128Bytes);
  46.         CryInterlockedFlushSList(m_freeList256Bytes);
  47.         CryInterlockedFlushSList(m_freeList512Bytes);
  48.  
  49.         CryModuleMemalignFree(m_pPoolMemory);
  50. }
  51.  
  52. ///////////////////////////////////////////////////////////////////////////////
  53. void ParticleObjectPool::Init(uint32 nBytesToAllocate)
  54. {
  55.         m_nPoolCapacity = Align(nBytesToAllocate, 4 * 1024);
  56.  
  57.         MEMSTAT_CONTEXT(EMemStatContextTypes::MSC_Other, 0, "Particles Pool");
  58.  
  59.         // allocate memory block to use as pool
  60.         if (m_pPoolMemory)
  61.         {
  62.                 CryModuleMemalignFree(m_pPoolMemory);
  63.                 m_pPoolMemory = NULL;
  64.         }
  65.         if (m_nPoolCapacity)
  66.         {
  67.                 m_pPoolMemory = CryModuleMemalign(m_nPoolCapacity, 128);
  68.         }
  69.  
  70.         // fill 4KB freelist
  71.         Init4KBFreeList();
  72. }
  73.  
  74. ///////////////////////////////////////////////////////////////////////////////
  75. void* ParticleObjectPool::Allocate(uint32 nSize)
  76. {
  77.         void* pRet = NULL;
  78.  
  79.         if (nSize <= 128)
  80.                 pRet = Allocate_128Byte();
  81.         else if (nSize <= 256)
  82.                 pRet = Allocate_256Byte();
  83.         else if (nSize <= 512)
  84.                 pRet = Allocate_512Byte();
  85.         else // fallback for the case that a a particle histy is bigger than 512 bytes
  86.                 pRet = malloc(nSize);
  87.  
  88.         return pRet;
  89. }
  90.  
  91. ///////////////////////////////////////////////////////////////////////////////
  92. void ParticleObjectPool::Deallocate(void* a_memoryToDeallocate, uint32 nSize)
  93. {
  94.         if (nSize <= 128)
  95.                 Deallocate_128Byte(a_memoryToDeallocate);
  96.         else if (nSize <= 256)
  97.                 Deallocate_256Byte(a_memoryToDeallocate);
  98.         else if (nSize <= 512)
  99.                 Deallocate_512Byte(a_memoryToDeallocate);
  100.         else
  101.                 free(a_memoryToDeallocate);
  102. }
  103.  
  104. ///////////////////////////////////////////////////////////////////////////////
  105. void ParticleObjectPool::Init4KBFreeList()
  106. {
  107.         CryInterlockedFlushSList(m_freeList4KB);
  108.         CryInterlockedFlushSList(m_freeList128Bytes);
  109.         CryInterlockedFlushSList(m_freeList256Bytes);
  110.         CryInterlockedFlushSList(m_freeList512Bytes);
  111.  
  112.         char* pElementMemory = (char*)m_pPoolMemory;
  113.         for (int i = (m_nPoolCapacity / (4 * 1024)) - 1; i >= 0; --i)
  114.         {
  115.                 // Build up the linked list of free nodes to begin with - do it in
  116.                 // reverse order so that consecutive allocations will be given chunks
  117.                 // in a cache-friendly order
  118.                 SLockFreeSingleLinkedListEntry* pNewNode = (SLockFreeSingleLinkedListEntry*)(pElementMemory + (i * (4 * 1024)));
  119.                 CryInterlockedPushEntrySList(m_freeList4KB, *pNewNode);
  120.         }
  121. }
  122.  
  123. ///////////////////////////////////////////////////////////////////////////////
  124. void* ParticleObjectPool::Allocate_128Byte()
  125. {
  126.         const uint32 nAllocationSize = 128;
  127.         do
  128.         {
  129.                 void* pListEntry = CryInterlockedPopEntrySList(m_freeList128Bytes);
  130.                 if (pListEntry)
  131.                 {
  132. #if defined(TRACK_PARTICLE_POOL_USAGE)
  133.                         CryInterlockedAdd(alias_cast<volatile int*>(&m_nMemory128BytesUsed), nAllocationSize);
  134.                         const int nUsedMemory = CryInterlockedAdd(alias_cast<volatile int*>(&m_nUsedMemory), nAllocationSize);
  135.                         int nMaxUsed = ~0;
  136.                         do
  137.                         {
  138.                                 nMaxUsed = *alias_cast<volatile int*>(&m_nMaxUsedMemory);
  139.                                 if (nUsedMemory <= nMaxUsed)
  140.                                         break;
  141.  
  142.                         }
  143.                         while (CryInterlockedCompareExchange(alias_cast<volatile LONG*>(&m_nMaxUsedMemory), nUsedMemory, nMaxUsed) == nMaxUsed);
  144. #endif
  145.                         return pListEntry;
  146.                 }
  147.  
  148.                 // allocation failed, refill list from a 4KB block if we have one
  149.                 void* pMemoryBlock = CryInterlockedPopEntrySList(m_freeList4KB);
  150.  
  151.                 // stop if we ran out of pool memory
  152.                 IF (pMemoryBlock == NULL, 0)
  153.                         return NULL;
  154.  
  155. #if defined(TRACK_PARTICLE_POOL_USAGE)
  156.                 CryInterlockedAdd(alias_cast<volatile int*>(&m_nMemory128Bytes), 4 * 1024);
  157. #endif
  158.  
  159.                 char* pElementMemory = (char*)pMemoryBlock;
  160.                 for (int i = ((4 * 1024) / (nAllocationSize)) - 1; i >= 0; --i)
  161.                 {
  162.                         // Build up the linked list of free nodes to begin with - do it in
  163.                         // reverse order so that consecutive allocations will be given chunks
  164.                         // in a cache-friendly order
  165.                         SLockFreeSingleLinkedListEntry* pNewNode = (SLockFreeSingleLinkedListEntry*)(pElementMemory + (i * (nAllocationSize)));
  166.                         CryInterlockedPushEntrySList(m_freeList128Bytes, *pNewNode);
  167.                 }
  168.  
  169.         }
  170.         while (true);
  171. }
  172.  
  173. ///////////////////////////////////////////////////////////////////////////////
  174. void* ParticleObjectPool::Allocate_256Byte()
  175. {
  176.         const uint32 nAllocationSize = 256;
  177.         do
  178.         {
  179.                 void* pListEntry = CryInterlockedPopEntrySList(m_freeList256Bytes);
  180.                 if (pListEntry)
  181.                 {
  182. #if defined(TRACK_PARTICLE_POOL_USAGE)                 
  183.                         CryInterlockedAdd(alias_cast<volatile int*>(&m_nMemory256BytesUsed), nAllocationSize);
  184.                         const int nUsedMemory = CryInterlockedAdd(alias_cast<volatile int*>(&m_nUsedMemory), nAllocationSize);
  185.                         int nMaxUsed = ~0;
  186.                         do
  187.                         {
  188.                                 nMaxUsed = *alias_cast<volatile int*>(&m_nMaxUsedMemory);
  189.                                 if (nUsedMemory <= nMaxUsed)
  190.                                         break;
  191.  
  192.                         }
  193.                         while (CryInterlockedCompareExchange(alias_cast<volatile LONG*>(&m_nMaxUsedMemory), nUsedMemory, nMaxUsed) == nMaxUsed);
  194. #endif
  195.                         return pListEntry;
  196.                 }
  197.  
  198.                 // allocation failed, refill list from a 4KB block if we have one
  199.                 void* pMemoryBlock = CryInterlockedPopEntrySList(m_freeList4KB);
  200.                 // stop if we ran out of pool memory
  201.                 IF (pMemoryBlock == NULL, 0)
  202.                         return NULL;
  203.  
  204. #if defined(TRACK_PARTICLE_POOL_USAGE)
  205.                 CryInterlockedAdd(alias_cast<volatile int*>(&m_nMemory256Bytes), 4 * 1024);
  206. #endif
  207.  
  208.                 char* pElementMemory = (char*)pMemoryBlock;
  209.                 for (int i = ((4 * 1024) / (nAllocationSize)) - 1; i >= 0; --i)
  210.                 {
  211.                         // Build up the linked list of free nodes to begin with - do it in
  212.                         // reverse order so that consecutive allocations will be given chunks
  213.                         // in a cache-friendly order
  214.                         SLockFreeSingleLinkedListEntry* pNewNode = (SLockFreeSingleLinkedListEntry*)(pElementMemory + (i * (nAllocationSize)));
  215.                         CryInterlockedPushEntrySList(m_freeList256Bytes, *pNewNode);
  216.                 }
  217.  
  218.         }
  219.         while (true);
  220. }
  221.  
  222. ///////////////////////////////////////////////////////////////////////////////
  223. void* ParticleObjectPool::Allocate_512Byte()
  224. {
  225.         const uint32 nAllocationSize = 512;
  226.         do
  227.         {
  228.                 void* pListEntry = CryInterlockedPopEntrySList(m_freeList512Bytes);
  229.                 if (pListEntry)
  230.                 {
  231. #if defined(TRACK_PARTICLE_POOL_USAGE)
  232.                         CryInterlockedAdd(alias_cast<volatile int*>(&m_nMemory512Bytesused), nAllocationSize);
  233.                         const int nUsedMemory = CryInterlockedAdd(alias_cast<volatile int*>(&m_nUsedMemory), nAllocationSize);
  234.                         int nMaxUsed = ~0;
  235.                         do
  236.                         {
  237.                                 nMaxUsed = *alias_cast<volatile int*>(&m_nMaxUsedMemory);
  238.                                 if (nUsedMemory <= nMaxUsed)
  239.                                         break;
  240.  
  241.                         }
  242.                         while (CryInterlockedCompareExchange(alias_cast<volatile LONG*>(&m_nMaxUsedMemory), nUsedMemory, nMaxUsed) == nMaxUsed);
  243. #endif
  244.                         return pListEntry;
  245.                 }
  246.  
  247.                 // allocation failed, refill list from a 4KB block if we have one
  248.                 void* pMemoryBlock = CryInterlockedPopEntrySList(m_freeList4KB);
  249.                 // stop if we ran out of pool memory
  250.                 IF (pMemoryBlock == NULL, 0)
  251.                         return NULL;
  252.  
  253. #if defined(TRACK_PARTICLE_POOL_USAGE)
  254.                 CryInterlockedAdd(alias_cast<volatile int*>(&m_nMemory512Bytes), 4 * 1024);
  255. #endif
  256.  
  257.                 char* pElementMemory = (char*)pMemoryBlock;
  258.                 for (int i = ((4 * 1024) / (nAllocationSize)) - 1; i >= 0; --i)
  259.                 {
  260.                         // Build up the linked list of free nodes to begin with - do it in
  261.                         // reverse order so that consecutive allocations will be given chunks
  262.                         // in a cache-friendly order
  263.                         SLockFreeSingleLinkedListEntry* pNewNode = (SLockFreeSingleLinkedListEntry*)(pElementMemory + (i * (nAllocationSize)));
  264.                         CryInterlockedPushEntrySList(m_freeList512Bytes, *pNewNode);
  265.                 }
  266.  
  267.         }
  268.         while (true);
  269. }
  270.  
  271. ///////////////////////////////////////////////////////////////////////////////
  272. void ParticleObjectPool::Deallocate_128Byte(void* pPtr)
  273. {
  274.         IF (!pPtr, 0)
  275.                 return;
  276.  
  277.         CryInterlockedPushEntrySList(m_freeList128Bytes, *alias_cast<SLockFreeSingleLinkedListEntry*>(pPtr));
  278. #if defined(TRACK_PARTICLE_POOL_USAGE)
  279.         CryInterlockedAdd(alias_cast<volatile int*>(&m_nUsedMemory), -128);
  280.         CryInterlockedAdd(alias_cast<volatile int*>(&m_nMemory128BytesUsed), -128);
  281. #endif
  282. }
  283.  
  284. ///////////////////////////////////////////////////////////////////////////////
  285. void ParticleObjectPool::Deallocate_256Byte(void* pPtr)
  286. {
  287.         IF (!pPtr, 0)
  288.                 return;
  289.  
  290.         CryInterlockedPushEntrySList(m_freeList256Bytes, *alias_cast<SLockFreeSingleLinkedListEntry*>(pPtr));
  291. #if defined(TRACK_PARTICLE_POOL_USAGE)
  292.         CryInterlockedAdd(alias_cast<volatile int*>(&m_nUsedMemory), -256);
  293.         CryInterlockedAdd(alias_cast<volatile int*>(&m_nMemory256BytesUsed), -256);
  294. #endif
  295. }
  296.  
  297. ///////////////////////////////////////////////////////////////////////////////
  298. void ParticleObjectPool::Deallocate_512Byte(void* pPtr)
  299. {
  300.         IF (!pPtr, 0)
  301.                 return;
  302.  
  303.         CryInterlockedPushEntrySList(m_freeList512Bytes, *alias_cast<SLockFreeSingleLinkedListEntry*>(pPtr));
  304. #if defined(TRACK_PARTICLE_POOL_USAGE)
  305.         CryInterlockedAdd(alias_cast<volatile int*>(&m_nUsedMemory), -512);
  306.         CryInterlockedAdd(alias_cast<volatile int*>(&m_nMemory512Bytesused), -512);
  307. #endif
  308. }
  309.  
downloadParticleFixedSizeElementPool.cpp Source code - Download CRYENGINE Source code
Related Source Codes/Software:
postal - 2017-06-11
reactide - Reactide is the first dedicated IDE for React web ... 2017-06-11
rkt - rkt is a pod-native container engine for Linux. It... 2017-06-11
uWebSockets - Tiny WebSockets https://for... 2017-06-11
realworld - TodoMVC for the RealWorld - Exemplary fullstack Me... 2017-06-11
CRYENGINE - CRYENGINE is a powerful real-time game development... 2017-06-11
goreplay - GoReplay is an open-source tool for capturing and ... 2017-06-10
pyenv - Simple Python version management 2017-06-10
redux-saga - An alternative side effect model for Redux apps ... 2017-06-10
angular-starter - 2017-06-10

 Back to top