hxalloc.cpp
Upload User: dangjiwu
Upload Date: 2013-07-19
Package Size: 42019k
Code Size: 25k
Category:

Symbian

Development Platform:

Visual C++

  1. /* ***** BEGIN LICENSE BLOCK ***** 
  2.  * Version: RCSL 1.0/RPSL 1.0 
  3.  *  
  4.  * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. 
  5.  *      
  6.  * The contents of this file, and the files included with this file, are 
  7.  * subject to the current version of the RealNetworks Public Source License 
  8.  * Version 1.0 (the "RPSL") available at 
  9.  * http://www.helixcommunity.org/content/rpsl unless you have licensed 
  10.  * the file under the RealNetworks Community Source License Version 1.0 
  11.  * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, 
  12.  * in which case the RCSL will apply. You may also obtain the license terms 
  13.  * directly from RealNetworks.  You may not use this file except in 
  14.  * compliance with the RPSL or, if you have a valid RCSL with RealNetworks 
  15.  * applicable to this file, the RCSL.  Please see the applicable RPSL or 
  16.  * RCSL for the rights, obligations and limitations governing use of the 
  17.  * contents of the file.  
  18.  *  
  19.  * This file is part of the Helix DNA Technology. RealNetworks is the 
  20.  * developer of the Original Code and owns the copyrights in the portions 
  21.  * it created. 
  22.  *  
  23.  * This file, and the files included with this file, is distributed and made 
  24.  * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  25.  * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  26.  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS 
  27.  * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  28.  * 
  29.  * Technology Compatibility Kit Test Suite(s) Location: 
  30.  *    http://www.helixcommunity.org/content/tck 
  31.  * 
  32.  * Contributor(s): 
  33.  *  
  34.  * ***** END LICENSE BLOCK ***** */ 
  35. ///////////////////
  36. // include files
  37. #include "hxtypes.h"
  38. #include "hxmap.h"
  39. #include "hxalloc.h"
  40. #include "hxassert.h"
  41. #include "hxerrors.h"
  42. #include "hxheap.h" 
  43. #include "hxtick.h"
  44. #include "chxpckts.h"
  45. #include "hxstrutl.h"
  46. #if defined(_WINDOWS)
  47. #include "hlxclib/windows.h"
  48. #include <windowsx.h>
  49. #endif
  50. ///////////////////
  51. // private data
  52. #ifdef _DEBUG
  53. #undef HX_THIS_FILE
  54. static const char HX_THIS_FILE[] = __FILE__;
  55. #endif
  56. ///////////////////
  57. // private functions
  58. ///////////////////////////////////////////////////////////////////////////////
  59. // CHXMemoryBlock Implementation
  60. ///////////////////////////////////////////////////////////////////////////////
  61. CHXMemoryBlock::CHXMemoryBlock(CHXMemoryAllocator *pAllocator, BOOL bGlobalAlloc /* = FALSE */)
  62. {
  63. HX_ASSERT_VALID_PTR(pAllocator);
  64. m_pMemBuffer = NULL;
  65. m_MemBufferSize = 0;
  66. m_RefCount = 0;
  67. m_pAllocator = pAllocator;    
  68. m_bUseGlobalAlloc = bGlobalAlloc; // Determines whether we use GlobalAlloc or new
  69. }
  70. CHXMemoryBlock::~CHXMemoryBlock()
  71. {
  72. HX_ASSERT(m_RefCount == 0);
  73. HX_ASSERT(m_pMemBuffer == NULL);
  74. // clean up just in case
  75. if (m_pMemBuffer != NULL)
  76. {
  77. #if defined(_WINDOWS) && !defined(WIN32_PLATFORM_PSPC)
  78.             if (m_bUseGlobalAlloc)
  79.             {    
  80.                 GlobalFreePtr(m_pMemBuffer);
  81.             }
  82.             else
  83. #endif // _WINDOWS
  84.             {
  85. delete [] m_pMemBuffer;
  86.             }
  87.             m_pMemBuffer = NULL;
  88.             m_MemBufferSize = 0;
  89. }
  90. }
  91. BOOL CHXMemoryBlock::Allocate(ULONG32 uSize)
  92. {
  93. HX_ASSERT_VALID_PTR(m_pAllocator);
  94. if (uSize > 0)
  95. {   
  96. // On x86 systems we'd like the buffer to be aligned to "HXALLOC_BUFFER_ALIGNMENT" bytes.
  97. // So we'll allocate (uSize + HXALLOC_BUFFER_ALIGNMENT - 1) bytes, and move the returned
  98. // buffer pointer to the correct alignment
  99. // clean up just in case
  100. HX_ASSERT(NULL==m_pMemBuffer);
  101. if (m_pMemBuffer != NULL)
  102. {
  103. #if defined(_WINDOWS) && !defined(WIN32_PLATFORM_PSPC)
  104. if (m_bUseGlobalAlloc)
  105. {    
  106. GlobalFreePtr(m_pMemBuffer);
  107. }
  108. else
  109. #endif // _WINDOWS
  110. {
  111. delete [] m_pMemBuffer;
  112. }
  113.         m_pMemBuffer = NULL;
  114.     m_MemBufferSize = 0;
  115. }
  116. #if defined(_WINDOWS) && !defined(WIN32_PLATFORM_PSPC)
  117. if (m_bUseGlobalAlloc)
  118. {
  119. #if defined(_M_IX86)
  120.     m_pMemBuffer = (UCHAR*) GlobalAllocPtr(GMEM_MOVEABLE | GMEM_SHARE, uSize + HXALLOC_BUFFER_ALIGNMENT - 1);
  121. #else
  122.     m_pMemBuffer = (UCHAR*) GlobalAllocPtr(GMEM_MOVEABLE | GMEM_SHARE, uSize);
  123. #endif
  124. }
  125. else
  126. #endif
  127. {
  128. #if defined(_M_IX86)
  129. m_pMemBuffer = new UCHAR[uSize + HXALLOC_BUFFER_ALIGNMENT - 1];
  130. #else
  131. m_pMemBuffer = new UCHAR[uSize];
  132. #endif
  133. }
  134.                 HX_ASSERT(m_pMemBuffer);
  135. if (m_pMemBuffer != NULL)
  136. {
  137. m_MemBufferSize = uSize;
  138.                         return(TRUE);
  139. }
  140. }
  141. // we consider it a improper to allocate with 0 size.
  142. return(FALSE);
  143. }
  144. void CHXMemoryBlock::Free()
  145. {
  146. HX_ASSERT_VALID_PTR(m_pMemBuffer);
  147. if (m_pMemBuffer != NULL)
  148. {
  149. #if defined(_WINDOWS) && !defined(WIN32_PLATFORM_PSPC)
  150. if (m_bUseGlobalAlloc)
  151. {    
  152. GlobalFreePtr(m_pMemBuffer);
  153.         }
  154. else
  155. #endif // _WINDOWS
  156. {
  157.             delete [] m_pMemBuffer;
  158. }
  159. m_pMemBuffer = NULL;
  160. m_MemBufferSize = 0;
  161. }
  162. }
  163. HX_RESULT
  164. CHXMemoryBlock::QueryInterface(HX_IID iid, void** ppvObj)
  165. {
  166. // Do dynamic Cast
  167. if (iid == IID_IHXUnknown)
  168. {
  169. *ppvObj = (IHXUnknown *)this;
  170. }
  171. else
  172. {
  173. *ppvObj = NULL;
  174. }
  175. // Do lifetime control
  176. if (*ppvObj != NULL)
  177. {
  178. ((IHXUnknown *)*ppvObj)->AddRef();
  179. }
  180. return( (*ppvObj != NULL)?(HX_NO_ERROR):(HX_NO_INTERFACE));
  181. }
  182. ULONG32 CHXMemoryBlock::AddRef()
  183. {
  184. // shouldn't add ref empty blocks.
  185. HX_ASSERT_VALID_PTR(m_pMemBuffer);
  186. return InterlockedIncrement(&m_RefCount);
  187. }
  188. ULONG32 CHXMemoryBlock::Release()
  189. {
  190.     HX_ASSERT(m_RefCount != 0);
  191.     if(InterlockedDecrement(&m_RefCount) == 0)
  192.     {
  193. //  This is used instead of delete
  194. //  The Allocator puts the memory into a free pool and 
  195. //  deletes it when it is destroyed
  196. m_pAllocator->NotifyFreeBlock(this);
  197. return 0;
  198.     }
  199.     return m_RefCount;
  200. }
  201. ///////////////////////////////////////////////////////////////////////////////
  202. // CHXMemoryAllocator Implementation
  203. ///////////////////////////////////////////////////////////////////////////////
  204. HX_RESULT
  205. CHXMemoryAllocator::QueryInterface(HX_IID iid, void** ppvObj)
  206. {
  207. // Do dynamic Cast
  208. if (iid == IID_IHX20MemoryAllocator)
  209. {
  210. *ppvObj = (IHX20MemoryAllocator *)this;
  211. }
  212. else if (iid == IID_IHXUnknown)
  213. {
  214. *ppvObj = (IHXUnknown *)this;
  215. }
  216. else
  217. {
  218. *ppvObj = NULL;
  219. }
  220. // Do lifetime control
  221. if (*ppvObj != NULL)
  222. {
  223. ((IHXUnknown *)*ppvObj)->AddRef();
  224. }
  225. return( (*ppvObj != NULL)?(HX_NO_ERROR):(HX_NO_INTERFACE));
  226. }
  227. ULONG32 CHXMemoryAllocator::AddRef()
  228. {
  229.     return InterlockedIncrement(&m_ref);
  230. }
  231. ULONG32 CHXMemoryAllocator::Release()
  232. {
  233.     HX_ASSERT(m_ref != 0);
  234.     if(InterlockedDecrement(&m_ref) == 0)
  235.     {
  236. delete this;
  237. return 0;
  238.     }
  239.     return m_ref;
  240. }
  241. CHXMemoryAllocator::CHXMemoryAllocator(const char* szIdentifier, 
  242.                                        BOOL bThreadSafe, 
  243.                                        BOOL bUseGlobalAlloc, 
  244.                                        BOOL bEstimateFreeListSize, 
  245.                                        UINT32 uiPoolHistoryDepth)
  246.     : m_AllocCount(0)
  247.     , m_Count(0)
  248.     , m_uSize(0)
  249.     , m_ref(0)
  250.     , m_bThreadSafe(bThreadSafe)
  251.     , m_bUseGlobalAlloc(bUseGlobalAlloc)
  252.     , m_bEstimateFreeListSize(bEstimateFreeListSize)
  253.     , m_uiPoolHistoryDepth(uiPoolHistoryDepth)
  254.     , m_uiCurrentHistoryIndex(0)
  255. #ifndef WIN32
  256.     , m_pMutex(NULL)
  257. #endif // WIN32
  258. {
  259.     m_strIdentifier = szIdentifier;
  260. #ifdef WIN32
  261.     if (m_bThreadSafe) InitializeCriticalSection(&m_critsec);
  262.     if (ERROR_SUCCESS != RegOpenKeyEx(HKEY_CLASSES_ROOT,
  263.       OS_STRING("RVEncoderStats"),0,
  264.       KEY_ALL_ACCESS,&m_hkey))
  265.     {
  266.         m_hkey = NULL;
  267.     }
  268. #else // WIN32
  269.     if (bThreadSafe)
  270.     {
  271. #ifdef THREADS_SUPPORTED
  272. HXMutex::MakeMutex(m_pMutex);
  273. #else  // THREADS_SUPPORTED
  274. HXMutex::MakeStubMutex(m_pMutex);
  275. #endif  // THREADS_SUPPORTED
  276.     }
  277. #endif // WIN32
  278.     if (m_bEstimateFreeListSize && uiPoolHistoryDepth)
  279.     {
  280.         m_puiBufferUseHistory = new UINT32[uiPoolHistoryDepth]; 
  281.         memset(m_puiBufferUseHistory, 0, sizeof(m_puiBufferUseHistory));
  282.     }
  283.     else
  284.     {
  285.         m_puiBufferUseHistory = NULL;
  286.         m_bEstimateFreeListSize = FALSE;
  287.     }
  288.     WriteRuntimeStats();
  289. }
  290. CHXMemoryAllocator::CHXMemoryAllocator(BOOL bThreadSafe/*=FALSE*/, 
  291.                                        BOOL bUseGlobalAlloc/*=FALSE*/,
  292.                                        BOOL bEstimateFreeListSize, 
  293.                                        UINT32 uiPoolHistoryDepth)
  294.     : m_AllocCount(0)
  295.     , m_Count(0)
  296.     , m_uSize(0)
  297.     , m_ref(0)
  298.     , m_bThreadSafe(bThreadSafe)
  299.     , m_bUseGlobalAlloc(bUseGlobalAlloc)
  300.     , m_bEstimateFreeListSize(bEstimateFreeListSize)
  301.     , m_uiPoolHistoryDepth(uiPoolHistoryDepth)
  302.     , m_uiCurrentHistoryIndex(0)
  303. #ifndef WIN32
  304.     , m_pMutex(NULL)
  305. #endif // WIN32
  306. {
  307. #ifdef WIN32
  308. if (m_bThreadSafe) InitializeCriticalSection(&m_critsec);
  309.         m_hkey = NULL;
  310. #else // WIN32
  311. if (bThreadSafe)
  312. {
  313. #ifdef THREADS_SUPPORTED
  314.     HXMutex::MakeMutex(m_pMutex);
  315. #else  // THREADS_SUPPORTED
  316.     HXMutex::MakeStubMutex(m_pMutex);
  317. #endif  // THREADS_SUPPORTED
  318. }
  319. #endif // WIN32
  320.         if (m_bEstimateFreeListSize && uiPoolHistoryDepth)
  321.         {
  322.             m_puiBufferUseHistory = new UINT32[uiPoolHistoryDepth]; 
  323.             memset(m_puiBufferUseHistory, 0, sizeof(m_puiBufferUseHistory));
  324.         }
  325.         else
  326.         {
  327.             m_puiBufferUseHistory = NULL;
  328.             m_bEstimateFreeListSize = FALSE;
  329.         }
  330. }
  331. CHXMemoryAllocator::~CHXMemoryAllocator()
  332. {
  333.     WriteRuntimeStats();
  334.         // cleanup memory left by the user in the map
  335. POSITION currentMapNode = m_MemBlockMap.GetStartPosition();
  336. CHXMemoryBlock * pMemBlock;
  337. UCHAR * memPtr;
  338. // we should find the map empty.
  339. HX_ASSERT(m_MemBlockMap.IsEmpty());
  340. while(!m_MemBlockMap.IsEmpty())
  341. {
  342. m_MemBlockMap.GetNextAssoc(currentMapNode, (void *&)memPtr, (void *&)pMemBlock);
  343. if (pMemBlock != NULL)
  344. {
  345. // by releasing the memory the memblock and buffer
  346. // get cleaned up correctly.
  347. while ((UINT16)pMemBlock->Release())
  348. {
  349. ;
  350. }
  351. }
  352. }
  353. // need to clean up all the allocated nodes
  354. while(!m_freeList.IsEmpty())
  355. {
  356. CHXMemoryBlock * pMemBlock = (CHXMemoryBlock *)
  357. m_freeList.RemoveHead();
  358. pMemBlock->Free();
  359. delete pMemBlock;
  360. }
  361. #ifdef WIN32
  362. if (m_bThreadSafe) DeleteCriticalSection(&m_critsec);
  363.         if (m_hkey)
  364.             RegCloseKey(m_hkey);
  365. #else // WIN32
  366. HX_DELETE(m_pMutex);
  367. #endif // WIN32
  368.         if (m_puiBufferUseHistory)
  369.         {
  370.             delete [] m_puiBufferUseHistory; 
  371.         }
  372. }
  373. #ifdef RUNTIME_STATISTICS
  374. void CHXMemoryAllocator::WriteRuntimeStats()
  375. {
  376. #ifdef WIN32
  377.     if (m_hkey && m_strIdentifier.GetLength())
  378.     {
  379.         char szData[128]; /* Flawfinder: ignore */
  380.         SafeSprintf(szData,128,"Size:%d AllocCount:%d FreeList:%d Map:%d",
  381.             m_uSize,m_AllocCount,m_freeList.GetCount(),m_MemBlockMap.GetCount());
  382.         RegSetValueEx(m_hkey,m_strIdentifier,0,REG_SZ,(BYTE*)szData,strlen(szData)+1);
  383.     }
  384. #endif
  385. }
  386. #endif
  387. HX_RESULT CHXMemoryAllocator::SetProperties(HX20ALLOCPROPS* pRequest, 
  388. HX20ALLOCPROPS* pActual)
  389. {
  390. #ifdef WIN32
  391. if (m_bThreadSafe) EnterCriticalSection(&m_critsec);
  392. #else // WIN32
  393. if (m_pMutex)
  394. {
  395.     m_pMutex->Lock();
  396. }
  397. #endif // WIN32
  398. // if there are buffers allocated, then empyt the free list 
  399. // so we don't give anyone a buffer of the wrong size
  400. if (m_AllocCount != 0 && pRequest->uBufferSize != m_uSize)
  401. {
  402.             while (!m_freeList.IsEmpty())
  403.             {
  404.                 CHXMemoryBlock * pMemBlock = (CHXMemoryBlock *)
  405.                         m_freeList.RemoveHead();
  406.                 HX_ASSERT(pMemBlock);
  407.                 pMemBlock->Free();
  408.                 delete pMemBlock;
  409.                 m_AllocCount--;
  410.             }
  411. }
  412. pActual->uBufferSize = m_uSize = pRequest->uBufferSize;
  413. pActual->nNumBuffers = m_Count = pRequest->nNumBuffers;
  414.         WriteRuntimeStats();
  415. #ifdef WIN32
  416. if (m_bThreadSafe) LeaveCriticalSection(&m_critsec);
  417. #else // WIN32
  418. if (m_pMutex)
  419. {
  420.     m_pMutex->Unlock();
  421. }
  422. #endif // WIN32
  423. return(HXR_OK);
  424. }
  425. HX_RESULT CHXMemoryAllocator::GetProperties(HX20ALLOCPROPS* pProps)
  426. {
  427. pProps->uBufferSize = m_uSize;
  428. pProps->nNumBuffers = m_Count;
  429. return(HXR_OK);
  430. }
  431. UCHAR * CHXMemoryAllocator::GetPacketBuffer(IHXUnknown ** pPacketBuffer)
  432. {
  433. HX_ASSERT_VALID_PTR(this);
  434. HX_ASSERT_VALID_PTR(pPacketBuffer);
  435. UCHAR * pRetVal = NULL;
  436. *pPacketBuffer = NULL;
  437. #ifdef WIN32
  438. if (m_bThreadSafe) EnterCriticalSection(&m_critsec);
  439. #else // WIN32
  440. if (m_pMutex)
  441. {
  442.     m_pMutex->Lock();
  443. }
  444. #endif // WIN32
  445. if (m_uSize > 0)
  446. {
  447. // Get the next free buffer from the buffer pool
  448. if (!m_freeList.IsEmpty())
  449. {
  450. CHXMemoryBlock * pMemBlock;
  451. BOOL bRemoveFromHead = (HX_GET_BETTERTICKCOUNT() & 0x01) ? TRUE : FALSE;
  452. if (bRemoveFromHead)
  453. {
  454.     // Get the first buffer
  455.     pMemBlock = (CHXMemoryBlock *) m_freeList.RemoveHead();
  456. }
  457. else
  458. {
  459.     // Get the last buffer
  460.     pMemBlock = (CHXMemoryBlock *) m_freeList.RemoveTail();
  461. }
  462. // Add ref the block so we know we are using it
  463. pMemBlock->AddRef();
  464. // setup the map so we don't loose the block
  465. pRetVal = pMemBlock->GetSampleBase();
  466. m_MemBlockMap.SetAt(pRetVal, pMemBlock);
  467. *pPacketBuffer = (IHXUnknown *)pMemBlock;
  468. }
  469. // if we didn't find any blocks in the list allocate a new one
  470. if (pRetVal == NULL)
  471. {
  472. CHXMemoryBlock * pMemBlock = new CHXMemoryBlock(this, m_bUseGlobalAlloc);
  473.                         HX_ASSERT(pMemBlock);
  474.                         
  475. if (pMemBlock != NULL)
  476. {
  477. if (pMemBlock->Allocate(m_uSize))
  478. {
  479. pMemBlock->AddRef();
  480. pRetVal = pMemBlock->GetSampleBase();
  481. m_MemBlockMap.SetAt(pRetVal, pMemBlock);
  482. m_AllocCount++;
  483. *pPacketBuffer = (IHXUnknown *)pMemBlock;
  484. }
  485.                                 else
  486.                                 {
  487.                                     HX_ASSERT(FALSE);
  488.                                     delete pMemBlock;
  489.                                 }
  490. }
  491. }
  492. }
  493.         if (m_bEstimateFreeListSize)
  494.         {                
  495.             m_uiCurrentHistoryIndex = ++m_uiCurrentHistoryIndex % m_uiPoolHistoryDepth;
  496.             m_puiBufferUseHistory[m_uiCurrentHistoryIndex] = m_MemBlockMap.GetCount(); 
  497.         }
  498.         WriteRuntimeStats();
  499. #ifdef WIN32
  500. if (m_bThreadSafe) LeaveCriticalSection(&m_critsec);
  501. #else // WIN32
  502. if (m_pMutex)
  503. {
  504.     m_pMutex->Unlock();
  505. }
  506. #endif // WIN32
  507. return(pRetVal);
  508. }
  509. CHXMemoryBlock* CHXMemoryAllocator::PacketPtrToPacketObj(UCHAR * memPtr)
  510. {
  511.         HX_ASSERT(memPtr);
  512.         
  513. // find the instance pointer for the CHXMemoryBlock that 
  514. // ownes this memory buffer and AddRef the block
  515. CHXMemoryBlock * pMemBlock = NULL;
  516. #ifdef WIN32
  517. if (m_bThreadSafe) EnterCriticalSection(&m_critsec);
  518. #else // WIN32
  519. if (m_pMutex)
  520. {
  521.     m_pMutex->Lock();
  522. }
  523. #endif // WIN32
  524. m_MemBlockMap.Lookup(memPtr, (void *&)pMemBlock);
  525. #ifdef WIN32
  526. if (m_bThreadSafe) LeaveCriticalSection(&m_critsec);
  527. #else // WIN32
  528. if (m_pMutex)
  529. {
  530.     m_pMutex->Unlock();
  531. }
  532. #endif // WIN32
  533. return(pMemBlock);
  534. }
  535. UINT16 CHXMemoryAllocator::AddRefPacketPtr(UCHAR * memPtr)
  536. {
  537.         HX_ASSERT(memPtr);
  538.         
  539. // find the instance pointer for the CHXMemoryBlock that 
  540. // ownes this memory buffer and AddRef the block
  541. CHXMemoryBlock * pMemBlock;
  542. UINT16 uiRetVal = 0;
  543. #ifdef WIN32
  544. if (m_bThreadSafe) EnterCriticalSection(&m_critsec);
  545. #else // WIN32
  546. if (m_pMutex)
  547. {
  548.     m_pMutex->Lock();
  549. }
  550. #endif // WIN32
  551. if (m_MemBlockMap.Lookup(memPtr, (void *&)pMemBlock))
  552. {
  553. uiRetVal = (UINT16)pMemBlock->AddRef();
  554. }
  555. else
  556. {
  557. // shouldn't AddRef memory that doesn't exist...
  558. HX_ASSERT(FALSE);
  559. }
  560. #ifdef WIN32
  561. if (m_bThreadSafe) LeaveCriticalSection(&m_critsec);
  562. #else // WIN32
  563. if (m_pMutex)
  564. {
  565.     m_pMutex->Unlock();
  566. }
  567. #endif // WIN32
  568. return(uiRetVal);
  569. }
  570. UINT16 CHXMemoryAllocator::ReleasePacketPtr(UCHAR * memPtr)
  571. {
  572.         HX_ASSERT(memPtr);
  573. // find the instance pointer for the CHXMemoryBlock that 
  574. // ownes this memory buffer and AddRef the block
  575. UINT16 uiRetVal = 0;
  576. if (!memPtr)
  577. {
  578.     return(uiRetVal);
  579. }
  580. #ifdef WIN32
  581. if (m_bThreadSafe) EnterCriticalSection(&m_critsec);
  582. #else // WIN32
  583. if (m_pMutex)
  584. {
  585.     m_pMutex->Lock();
  586. }
  587. #endif // WIN32
  588. CHXMemoryBlock * pMemBlock;
  589. if (m_MemBlockMap.Lookup(memPtr, (void *&)pMemBlock))
  590. {
  591. uiRetVal = (UINT16)pMemBlock->Release();
  592. }
  593. else
  594. {
  595. // shouldn't AddRef memory that doesn't exist...
  596. HX_ASSERT(FALSE);
  597. }
  598.         WriteRuntimeStats();
  599. #ifdef WIN32
  600. if (m_bThreadSafe) LeaveCriticalSection(&m_critsec);
  601. #else // WIN32
  602. if (m_pMutex)
  603. {
  604.     m_pMutex->Unlock();
  605. }
  606. #endif // WIN32
  607. return(uiRetVal);
  608. }
  609. #ifdef XXXJEFFA_DEBUG
  610. UINT32 g_NextLogTime = 0;
  611. #endif
  612. void CHXMemoryAllocator::NotifyFreeBlock(CHXMemoryBlock * pMemBlock)
  613. {
  614.         HX_ASSERT(pMemBlock);
  615. #ifdef WIN32
  616. if (m_bThreadSafe) EnterCriticalSection(&m_critsec);
  617. #else // WIN32
  618. if (m_pMutex)
  619. {
  620.     m_pMutex->Lock();
  621. }
  622. #endif // WIN32
  623. // Remove the memory from the map since it's not going
  624. // to be considered valid anymore
  625. m_MemBlockMap.RemoveKey(pMemBlock->GetSampleBase());
  626.         UINT32 uiMaxRecentlyUsed = 0;
  627.         if (m_bEstimateFreeListSize)
  628.         {
  629.             for (UINT32 i = 0; i < m_uiPoolHistoryDepth; i++)
  630.             {
  631.                 if (m_puiBufferUseHistory[i] > uiMaxRecentlyUsed)
  632.                 {
  633.                     uiMaxRecentlyUsed = m_puiBufferUseHistory[i];   
  634.                 }
  635.             }
  636.         }
  637. // as long as this block is the right size we will
  638. // recycle it
  639. if (m_uSize == pMemBlock->GetLength() 
  640.     && ( (m_freeList.GetCount() < (int) m_Count) &&
  641.                  (m_bEstimateFreeListSize ? m_AllocCount <= uiMaxRecentlyUsed + 1 : TRUE)
  642.                )
  643.            )
  644. {
  645. BOOL bAddToTail = (HX_GET_BETTERTICKCOUNT() & 0x01) ? TRUE : FALSE;
  646. if (bAddToTail)
  647. {
  648.     m_freeList.AddTail(pMemBlock);
  649. }
  650. else
  651. {
  652.     m_freeList.AddHead(pMemBlock);
  653. }
  654. #ifdef XXXJEFFA_DEBUG
  655. if (!HXMM_ATINTERRUPT() && HX_GET_TICKCOUNT() > g_NextLogTime)
  656. {
  657. FILE* pFile = fopen("Boot Drive:Desktop Folder:log.txt", "a+t");
  658. if (pFile)
  659. {
  660. fprintf(pFile, "%pt%dt%dt%lun", this, m_freeList.GetCount(), m_uSize, (m_freeList.GetCount()*m_uSize));
  661. fclose(pFile);
  662. }
  663. g_NextLogTime = HX_GET_TICKCOUNT()  + 10000UL;
  664. }
  665. #endif
  666. }
  667. else
  668. {
  669. // if it doesn't go on the free block list 
  670. // then delete it
  671. pMemBlock->Free();
  672. delete pMemBlock;
  673. m_AllocCount--;
  674. }
  675. #ifdef WIN32
  676. if (m_bThreadSafe) LeaveCriticalSection(&m_critsec);
  677. #else // WIN32
  678. if (m_pMutex)
  679. {
  680.     m_pMutex->Unlock();
  681. }
  682. #endif // WIN32
  683. }
  684. ///////////////////////////////////////////////////////////////////////////////
  685. // CHXBufferMemoryAllocator Implementation
  686. ///////////////////////////////////////////////////////////////////////////////
  687. HX_RESULT
  688. CHXBufferMemoryAllocator::QueryInterface(HX_IID iid, void** ppvObj)
  689. {
  690.     HX_ASSERT(ppvObj);
  691.     // Do dynamic Cast
  692.     if (iid == IID_IHX20MemoryAllocator)
  693.     {
  694. *ppvObj = (IHX20MemoryAllocator *)this;
  695.     }
  696.     else if (iid == IID_IHXUnknown)
  697.     {
  698. *ppvObj = (IHXUnknown *)this;
  699.     }
  700.     else
  701.     {
  702. *ppvObj = NULL;
  703.     }
  704.     // Do lifetime control
  705.     if (*ppvObj != NULL)
  706.     {
  707. ((IHXUnknown *)*ppvObj)->AddRef();
  708.     }
  709.     return( (*ppvObj != NULL)?(HX_NO_ERROR):(HX_NO_INTERFACE));
  710. }
  711. ULONG32 CHXBufferMemoryAllocator::AddRef()
  712. {
  713.     HX_ASSERT(this);
  714.     return InterlockedIncrement(&m_ref);
  715. }
  716. ULONG32 CHXBufferMemoryAllocator::Release()
  717. {
  718.     HX_ASSERT(this);
  719.     HX_ASSERT(m_ref != 0);
  720.     if(InterlockedDecrement(&m_ref) == 0)
  721.     {
  722. delete this;
  723. return 0;
  724.     }
  725.     
  726.     return m_ref;
  727. }
  728. struct BufferBlock
  729. {
  730.     IHXBuffer* m_pBuf;
  731.     INT32 m_lRefCount;
  732. };
  733. CHXBufferMemoryAllocator::CHXBufferMemoryAllocator(BOOL bThreadSafe)
  734.     : m_Count(0)
  735.     , m_uSize(0)
  736.     , m_ref(0)
  737. #ifndef WIN32
  738.     , m_pMutex(NULL)
  739. #else // WIN32
  740.     , m_bThreadSafe(bThreadSafe)
  741. #endif // WIN32
  742. {
  743. #ifdef WIN32
  744.     if (m_bThreadSafe) InitializeCriticalSection(&m_critsec);
  745. #else // WIN32
  746.     if (bThreadSafe)
  747.     {
  748. #ifdef THREADS_SUPPORTED
  749. HXMutex::MakeMutex(m_pMutex);
  750. #else  // THREADS_SUPPORTED
  751. HXMutex::MakeStubMutex(m_pMutex);
  752. #endif  // THREADS_SUPPORTED
  753.     }
  754. #endif // WIN32
  755. }
  756. CHXBufferMemoryAllocator::~CHXBufferMemoryAllocator()
  757. {
  758.     // cleanup memory left by the user in the map
  759.     POSITION currentMapNode = m_BufMap.GetStartPosition();
  760.     BufferBlock* pBufBlock;
  761.     UCHAR* memPtr;
  762.     
  763.     // we should find the map empty.
  764.     HX_ASSERT(m_BufMap.IsEmpty());
  765.     while(!m_BufMap.IsEmpty())
  766.     {
  767. m_BufMap.GetNextAssoc(currentMapNode, (void *&)memPtr, (void *&)pBufBlock);
  768. if (pBufBlock != NULL)
  769. {
  770.     HX_ASSERT(FALSE);
  771.     HX_RELEASE(pBufBlock->m_pBuf);
  772.             HX_DELETE(pBufBlock);
  773. }
  774.     }
  775. #ifdef WIN32
  776.     if (m_bThreadSafe) DeleteCriticalSection(&m_critsec);
  777. #else // WIN32
  778.     HX_DELETE(m_pMutex);
  779. #endif // WIN32
  780. }
  781. HX_RESULT CHXBufferMemoryAllocator::SetProperties(HX20ALLOCPROPS* pRequest, 
  782. HX20ALLOCPROPS* pActual)
  783. {
  784.     pActual->uBufferSize = m_uSize = pRequest->uBufferSize;
  785.     pActual->nNumBuffers = m_Count = pRequest->nNumBuffers;
  786.     return HXR_OK;
  787. }
  788. HX_RESULT CHXBufferMemoryAllocator::GetProperties(HX20ALLOCPROPS* pProps)
  789. {
  790.     pProps->uBufferSize = m_uSize;
  791.     pProps->nNumBuffers = m_Count;
  792.     return HXR_OK;
  793. }
  794. UCHAR* CHXBufferMemoryAllocator::GetPacketBuffer(IHXUnknown ** pPacketBuffer)
  795. {
  796.     // XXXX JHUG we are not keeping a free list, should do that...
  797.     HX_ASSERT_VALID_PTR(this);
  798.     HX_ASSERT_VALID_PTR(pPacketBuffer);
  799.     UCHAR * pRetVal = NULL;
  800.     *pPacketBuffer = NULL;
  801.     if (m_uSize > 0)
  802.     {
  803.         BufferBlock* pBufBlock = new BufferBlock();
  804.         IHXBuffer* pBuffer = new CHXBuffer();
  805.         HX_ASSERT(pBufBlock && pBuffer);
  806.         if (pBuffer && pBufBlock)
  807.         {
  808.                 pBuffer->AddRef();
  809.                 pBufBlock->m_pBuf = pBuffer;
  810.                 pBufBlock->m_lRefCount = 1;
  811.                 if (SUCCEEDED(pBuffer->SetSize(m_uSize)))
  812.                 {
  813.                         pRetVal = pBuffer->GetBuffer();
  814. #ifdef WIN32
  815. if (m_bThreadSafe) EnterCriticalSection(&m_critsec);
  816. #else // WIN32
  817. if (m_pMutex)
  818. {
  819.     m_pMutex->Lock();
  820. }
  821. #endif // WIN32
  822.                         m_BufMap.SetAt(pRetVal, pBufBlock);
  823. #ifdef WIN32
  824. if (m_bThreadSafe) LeaveCriticalSection(&m_critsec);
  825. #else // WIN32
  826. if (m_pMutex)
  827. {
  828.     m_pMutex->Unlock();
  829. }
  830. #endif // WIN32
  831.                         *pPacketBuffer = (IHXUnknown *) pBuffer;
  832.                 }
  833.                 else
  834.                 {
  835.                     HX_RELEASE(pBuffer);
  836.                 }
  837.         }
  838.         else
  839.         {
  840.             HX_DELETE(pBufBlock);
  841.             HX_RELEASE(pBuffer);
  842.         }
  843.     }
  844.     return(pRetVal);
  845. }
  846. UCHAR* CHXBufferMemoryAllocator::AddBuffer(IHXBuffer* pBuf)
  847. {
  848.     HX_ASSERT(pBuf);
  849.     UCHAR* pMem = NULL;
  850.     if (pBuf)
  851.     {
  852.         BufferBlock* pBufBlock = new BufferBlock;
  853.         HX_ASSERT(pBufBlock);
  854.         if (pBufBlock)
  855.         {
  856.             pBuf->AddRef();
  857.             pBufBlock->m_pBuf = pBuf;
  858.             pBufBlock->m_lRefCount = 1;
  859.             pMem = pBuf->GetBuffer();
  860.     
  861. #ifdef WIN32
  862.     if (m_bThreadSafe) EnterCriticalSection(&m_critsec);
  863. #else // WIN32
  864.     if (m_pMutex)
  865.     {
  866. m_pMutex->Lock();
  867.     }
  868. #endif // WIN32
  869.             m_BufMap.SetAt(pMem, pBufBlock);
  870. #ifdef WIN32
  871.     if (m_bThreadSafe) LeaveCriticalSection(&m_critsec);
  872. #else // WIN32
  873.     if (m_pMutex)
  874.     {
  875. m_pMutex->Unlock();
  876.     }
  877. #endif // WIN32
  878.         }
  879.     }
  880.     return pMem;
  881. }
  882. UINT16 CHXBufferMemoryAllocator::AddRefPacketPtr(UCHAR * memPtr)
  883. {
  884.     HX_ASSERT(memPtr);
  885.     
  886.     BufferBlock* pBlock = NULL;
  887.     UINT16 uiRetVal = 0;
  888. #ifdef WIN32
  889.     if (m_bThreadSafe) EnterCriticalSection(&m_critsec);
  890. #else // WIN32
  891.     if (m_pMutex)
  892.     {
  893. m_pMutex->Lock();
  894.     }
  895. #endif // WIN32
  896.     if (m_BufMap.Lookup(memPtr, (void *&)pBlock))
  897.     {
  898. uiRetVal = (UINT16)++(pBlock->m_lRefCount);
  899.     }
  900.     else
  901.     {
  902.  // shouldn't AddRef memory that doesn't exist...
  903.  HX_ASSERT(FALSE);
  904.     }
  905. #ifdef WIN32
  906.     if (m_bThreadSafe) LeaveCriticalSection(&m_critsec);
  907. #else // WIN32
  908.     if (m_pMutex)
  909.     {
  910. m_pMutex->Unlock();
  911.     }
  912. #endif // WIN32
  913.     return uiRetVal;
  914. }
  915. UINT16 CHXBufferMemoryAllocator::ReleasePacketPtr(UCHAR * memPtr)
  916. {
  917.     UINT16 uiRetVal = 0;
  918.     HX_ASSERT(memPtr);
  919.     if (!memPtr)
  920.     {
  921. return uiRetVal;
  922.     }
  923. #ifdef WIN32
  924.     if (m_bThreadSafe) EnterCriticalSection(&m_critsec);
  925. #else // WIN32
  926.     if (m_pMutex)
  927.     {
  928. m_pMutex->Lock();
  929.     }
  930. #endif // WIN32
  931.     BufferBlock* pBlock = NULL;
  932.     if (m_BufMap.Lookup(memPtr, (void *&)pBlock))
  933.     {
  934. uiRetVal = (UINT16)--(pBlock->m_lRefCount);
  935. if (pBlock->m_lRefCount == 0)
  936.         {
  937.             HX_RELEASE(pBlock->m_pBuf);
  938.             HX_DELETE(pBlock);
  939.             m_BufMap.RemoveKey(memPtr);
  940.         }
  941.     }
  942.     else
  943.     {
  944. // shouldn't Release memory that doesn't exist...
  945. HX_ASSERT(FALSE);
  946.     }
  947. #ifdef WIN32
  948.     if (m_bThreadSafe) LeaveCriticalSection(&m_critsec);
  949. #else // WIN32
  950.     if (m_pMutex)
  951.     {
  952. m_pMutex->Unlock();
  953.     }
  954. #endif // WIN32
  955.     return uiRetVal;
  956. }