hxalloc.cpp
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:25k
源码类别:

Symbian

开发平台:

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