⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hxalloc.cpp

📁 著名的 helix realplayer 基于手机 symbian 系统的 播放器全套源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/* ***** BEGIN LICENSE BLOCK ***** 
 * Version: RCSL 1.0/RPSL 1.0 
 *  
 * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. 
 *      
 * The contents of this file, and the files included with this file, are 
 * subject to the current version of the RealNetworks Public Source License 
 * Version 1.0 (the "RPSL") available at 
 * http://www.helixcommunity.org/content/rpsl unless you have licensed 
 * the file under the RealNetworks Community Source License Version 1.0 
 * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, 
 * in which case the RCSL will apply. You may also obtain the license terms 
 * directly from RealNetworks.  You may not use this file except in 
 * compliance with the RPSL or, if you have a valid RCSL with RealNetworks 
 * applicable to this file, the RCSL.  Please see the applicable RPSL or 
 * RCSL for the rights, obligations and limitations governing use of the 
 * contents of the file.  
 *  
 * This file is part of the Helix DNA Technology. RealNetworks is the 
 * developer of the Original Code and owns the copyrights in the portions 
 * it created. 
 *  
 * This file, and the files included with this file, is distributed and made 
 * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
 * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS 
 * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
 * 
 * Technology Compatibility Kit Test Suite(s) Location: 
 *    http://www.helixcommunity.org/content/tck 
 * 
 * Contributor(s): 
 *  
 * ***** END LICENSE BLOCK ***** */ 

///////////////////
//	include files
#include "hxtypes.h"
#include "hxmap.h"
#include "hxalloc.h"
#include "hxassert.h"
#include "hxerrors.h"
#include "hxheap.h" 
#include "hxtick.h"
#include "chxpckts.h"
#include "hxstrutl.h"

#if defined(_WINDOWS)
#include "hlxclib/windows.h"
#include <windowsx.h>
#endif

///////////////////
//	private data
#ifdef _DEBUG
#undef HX_THIS_FILE		
static const char HX_THIS_FILE[] = __FILE__;
#endif

///////////////////
//	private functions

///////////////////////////////////////////////////////////////////////////////
//	CHXMemoryBlock Implementation
///////////////////////////////////////////////////////////////////////////////
CHXMemoryBlock::CHXMemoryBlock(CHXMemoryAllocator *pAllocator, BOOL bGlobalAlloc /* = FALSE */)
{
	HX_ASSERT_VALID_PTR(pAllocator);

	m_pMemBuffer = NULL;
	m_MemBufferSize = 0;
	m_RefCount = 0;
	m_pAllocator = pAllocator;    
	m_bUseGlobalAlloc = bGlobalAlloc;	// Determines whether we use GlobalAlloc or new
}

CHXMemoryBlock::~CHXMemoryBlock()
{
	HX_ASSERT(m_RefCount == 0);
	HX_ASSERT(m_pMemBuffer == NULL);

	// clean up just in case
	if (m_pMemBuffer != NULL)
	{
#if defined(_WINDOWS) && !defined(WIN32_PLATFORM_PSPC)
            if (m_bUseGlobalAlloc)
            {    
                GlobalFreePtr(m_pMemBuffer);
            }
            else
#endif // _WINDOWS
            {
		delete [] m_pMemBuffer;
            }

            m_pMemBuffer = NULL;
            m_MemBufferSize = 0;
	}
}

BOOL CHXMemoryBlock::Allocate(ULONG32 uSize)
{
	HX_ASSERT_VALID_PTR(m_pAllocator);
	
	if (uSize > 0)
	{   
		// On x86 systems we'd like the buffer to be aligned to "HXALLOC_BUFFER_ALIGNMENT" bytes.
		// So we'll allocate (uSize + HXALLOC_BUFFER_ALIGNMENT - 1) bytes, and move the returned
		// buffer pointer to the correct alignment
#if defined(_WINDOWS) && !defined(WIN32_PLATFORM_PSPC)
		if (m_bUseGlobalAlloc)
		{
#if defined(_M_IX86)
		    m_pMemBuffer = (UCHAR*) GlobalAllocPtr(GMEM_MOVEABLE | GMEM_SHARE, uSize + HXALLOC_BUFFER_ALIGNMENT - 1);
#else
		    m_pMemBuffer = (UCHAR*) GlobalAllocPtr(GMEM_MOVEABLE | GMEM_SHARE, uSize);
#endif
		}
		else
#endif
		{
#if defined(_M_IX86)
			m_pMemBuffer = new UCHAR[uSize + HXALLOC_BUFFER_ALIGNMENT - 1];
#else
			m_pMemBuffer = new UCHAR[uSize];
#endif
		}
		
                HX_ASSERT(m_pMemBuffer);
		if (m_pMemBuffer != NULL)
		{
			m_MemBufferSize = uSize;
                        return(TRUE);
		}
	}

	// we consider it a improper to allocate with 0 size.
	return(FALSE);
}

void CHXMemoryBlock::Free()
{
	HX_ASSERT_VALID_PTR(m_pMemBuffer);

	if (m_pMemBuffer != NULL)
	{
#if defined(_WINDOWS) && !defined(WIN32_PLATFORM_PSPC)
		if (m_bUseGlobalAlloc)
		{    
			GlobalFreePtr(m_pMemBuffer);
	        }
		else
#endif // _WINDOWS
		{
           		delete [] m_pMemBuffer;
		}
		
		m_pMemBuffer = NULL;
		m_MemBufferSize = 0;
	}
}

HX_RESULT
CHXMemoryBlock::QueryInterface(HX_IID iid, void** ppvObj)
{
	// Do dynamic Cast
	if (iid == IID_IHXUnknown)
	{
		*ppvObj = (IHXUnknown *)this;
	}
	else
	{
		*ppvObj = NULL;
	}

	// Do lifetime control
	if (*ppvObj != NULL)
	{
		((IHXUnknown *)*ppvObj)->AddRef();
	}

	return( (*ppvObj != NULL)?(HX_NO_ERROR):(HX_NO_INTERFACE));
}

ULONG32 CHXMemoryBlock::AddRef()
{
	// shouldn't add ref empty blocks.
	HX_ASSERT_VALID_PTR(m_pMemBuffer);

	return InterlockedIncrement(&m_RefCount);
}

ULONG32 CHXMemoryBlock::Release()
{
    HX_ASSERT(m_RefCount != 0);

    if(InterlockedDecrement(&m_RefCount) == 0)
    {
	//  This is used instead of delete
	//  The Allocator puts the memory into a free pool and 
	//  deletes it when it is destroyed
	m_pAllocator->NotifyFreeBlock(this);
	return 0;
    }

    return m_RefCount;
}

///////////////////////////////////////////////////////////////////////////////
//	CHXMemoryAllocator Implementation
///////////////////////////////////////////////////////////////////////////////
HX_RESULT
CHXMemoryAllocator::QueryInterface(HX_IID iid, void** ppvObj)
{
	// Do dynamic Cast
	if (iid == IID_IHX20MemoryAllocator)
	{
		*ppvObj = (IHX20MemoryAllocator *)this;
	}
	else if (iid == IID_IHXUnknown)
	{
		*ppvObj = (IHXUnknown *)this;
	}
	else
	{
		*ppvObj = NULL;
	}

	// Do lifetime control
	if (*ppvObj != NULL)
	{
		((IHXUnknown *)*ppvObj)->AddRef();
	}

	return( (*ppvObj != NULL)?(HX_NO_ERROR):(HX_NO_INTERFACE));

}

ULONG32 CHXMemoryAllocator::AddRef()
{
    return InterlockedIncrement(&m_ref);
}

ULONG32 CHXMemoryAllocator::Release()
{
    HX_ASSERT(m_ref != 0);
    if(InterlockedDecrement(&m_ref) == 0)
    {
	delete this;
	return 0;
    }

    return m_ref;
}

CHXMemoryAllocator::CHXMemoryAllocator(const char* szIdentifier, 
                                       BOOL bThreadSafe, 
                                       BOOL bUseGlobalAlloc, 
                                       BOOL bEstimateFreeListSize, 
                                       UINT32 uiPoolHistoryDepth)
    : m_AllocCount(0)
    , m_Count(0)
    , m_uSize(0)
    , m_ref(0)
    , m_bThreadSafe(bThreadSafe)
    , m_bUseGlobalAlloc(bUseGlobalAlloc)
    , m_bEstimateFreeListSize(bEstimateFreeListSize)
    , m_uiPoolHistoryDepth(uiPoolHistoryDepth)
    , m_uiCurrentHistoryIndex(0)
#ifndef WIN32
    , m_pMutex(NULL)
#endif	// WIN32
{
    m_strIdentifier = szIdentifier;

#ifdef WIN32
    if (m_bThreadSafe) InitializeCriticalSection(&m_critsec);
    if (ERROR_SUCCESS != RegOpenKeyEx(HKEY_CLASSES_ROOT,
				      OS_STRING("RVEncoderStats"),0,
				      KEY_ALL_ACCESS,&m_hkey))
    {
        m_hkey = NULL;
    }
#else	// WIN32
    if (bThreadSafe)
    {
#ifdef THREADS_SUPPORTED
	HXMutex::MakeMutex(m_pMutex);
#else  // THREADS_SUPPORTED
	HXMutex::MakeStubMutex(m_pMutex);
#endif  // THREADS_SUPPORTED
    }
#endif	// WIN32

    if (m_bEstimateFreeListSize && uiPoolHistoryDepth)
    {
        m_puiBufferUseHistory = new UINT32[uiPoolHistoryDepth]; 
        memset(m_puiBufferUseHistory, 0, sizeof(m_puiBufferUseHistory));
    }
    else
    {
        m_puiBufferUseHistory = NULL;
        m_bEstimateFreeListSize = FALSE;
    }

    WriteRuntimeStats();
}


CHXMemoryAllocator::CHXMemoryAllocator(BOOL bThreadSafe/*=FALSE*/, 
                                       BOOL bUseGlobalAlloc/*=FALSE*/,
                                       BOOL bEstimateFreeListSize, 
                                       UINT32 uiPoolHistoryDepth)
    : m_AllocCount(0)
    , m_Count(0)
    , m_uSize(0)
    , m_ref(0)
    , m_bThreadSafe(bThreadSafe)
    , m_bUseGlobalAlloc(bUseGlobalAlloc)
    , m_bEstimateFreeListSize(bEstimateFreeListSize)
    , m_uiPoolHistoryDepth(uiPoolHistoryDepth)
    , m_uiCurrentHistoryIndex(0)
#ifndef WIN32
    , m_pMutex(NULL)
#endif	// WIN32
{
#ifdef WIN32
	if (m_bThreadSafe) InitializeCriticalSection(&m_critsec);
        m_hkey = NULL;
#else	// WIN32
	if (bThreadSafe)
	{
#ifdef THREADS_SUPPORTED
	    HXMutex::MakeMutex(m_pMutex);
#else  // THREADS_SUPPORTED
	    HXMutex::MakeStubMutex(m_pMutex);
#endif  // THREADS_SUPPORTED
	}
#endif	// WIN32

        if (m_bEstimateFreeListSize && uiPoolHistoryDepth)
        {
            m_puiBufferUseHistory = new UINT32[uiPoolHistoryDepth]; 
            memset(m_puiBufferUseHistory, 0, sizeof(m_puiBufferUseHistory));
        }
        else
        {
            m_puiBufferUseHistory = NULL;
            m_bEstimateFreeListSize = FALSE;
        }
}

CHXMemoryAllocator::~CHXMemoryAllocator()
{
    WriteRuntimeStats();

        // cleanup memory left by the user in the map
	POSITION currentMapNode = m_MemBlockMap.GetStartPosition();
	CHXMemoryBlock * pMemBlock;
	UCHAR * memPtr;

	// we should find the map empty.
	HX_ASSERT(m_MemBlockMap.IsEmpty());

	while(!m_MemBlockMap.IsEmpty())
	{
		m_MemBlockMap.GetNextAssoc(currentMapNode, (void *&)memPtr, (void *&)pMemBlock);

		if (pMemBlock != NULL)
		{
			// by releasing the memory the memblock and buffer
			// get cleaned up correctly.
			while ((UINT16)pMemBlock->Release())
			{
				;
			}
		}
	}

	// need to clean up all the allocated nodes
	while(!m_freeList.IsEmpty())
	{
		CHXMemoryBlock * pMemBlock = (CHXMemoryBlock *)
			m_freeList.RemoveHead();
		
		pMemBlock->Free();
		delete pMemBlock;
	}

#ifdef WIN32
	if (m_bThreadSafe) DeleteCriticalSection(&m_critsec);
        if (m_hkey)
            RegCloseKey(m_hkey);
#else	// WIN32
	HX_DELETE(m_pMutex);
#endif	// WIN32

        if (m_puiBufferUseHistory)
        {
            delete [] m_puiBufferUseHistory; 
        }
}

#ifdef RUNTIME_STATISTICS
void CHXMemoryAllocator::WriteRuntimeStats()
{
#ifdef WIN32
    if (m_hkey && m_strIdentifier.GetLength())
    {
        char szData[128]; /* Flawfinder: ignore */
        SafeSprintf(szData,128,"Size:%d AllocCount:%d FreeList:%d Map:%d",
            m_uSize,m_AllocCount,m_freeList.GetCount(),m_MemBlockMap.GetCount());
        RegSetValueEx(m_hkey,m_strIdentifier,0,REG_SZ,(BYTE*)szData,strlen(szData));
    }
#endif
}
#endif

HX_RESULT CHXMemoryAllocator::SetProperties(HX20ALLOCPROPS* pRequest, 
	HX20ALLOCPROPS* pActual)
{
#ifdef WIN32
	if (m_bThreadSafe) EnterCriticalSection(&m_critsec);
#else	// WIN32
	if (m_pMutex)
	{
	    m_pMutex->Lock();
	}
#endif	// WIN32

	// if there are buffers allocated, then empyt the free list 
	// so we don't give anyone a buffer of the wrong size
	if (m_AllocCount != 0 && pRequest->uBufferSize != m_uSize)
	{
            while (!m_freeList.IsEmpty())
            {
                CHXMemoryBlock * pMemBlock = (CHXMemoryBlock *)
                        m_freeList.RemoveHead();
                HX_ASSERT(pMemBlock);
                pMemBlock->Free();
                delete pMemBlock;
                m_AllocCount--;		
            }
	}
	
	pActual->uBufferSize = m_uSize = pRequest->uBufferSize;
	pActual->nNumBuffers = m_Count = pRequest->nNumBuffers;

        WriteRuntimeStats();

#ifdef WIN32
	if (m_bThreadSafe) LeaveCriticalSection(&m_critsec);
#else	// WIN32
	if (m_pMutex)
	{
	    m_pMutex->Unlock();
	}
#endif	// WIN32

	return(HXR_OK);
}

HX_RESULT CHXMemoryAllocator::GetProperties(HX20ALLOCPROPS* pProps)
{
	pProps->uBufferSize = m_uSize;
	pProps->nNumBuffers = m_Count;

	return(HXR_OK);
}

UCHAR * CHXMemoryAllocator::GetPacketBuffer(IHXUnknown ** pPacketBuffer)
{
	HX_ASSERT_VALID_PTR(this);
	HX_ASSERT_VALID_PTR(pPacketBuffer);
	UCHAR * pRetVal = NULL;
	*pPacketBuffer = NULL;
	
#ifdef WIN32
	if (m_bThreadSafe) EnterCriticalSection(&m_critsec);
#else	// WIN32
	if (m_pMutex)
	{
	    m_pMutex->Lock();
	}
#endif	// WIN32

	if (m_uSize > 0)
	{
		// Get the next free buffer from the buffer pool
		if (!m_freeList.IsEmpty())
		{
			CHXMemoryBlock * pMemBlock;
			BOOL bRemoveFromHead = (HX_GET_BETTERTICKCOUNT() & 0x01) ? TRUE : FALSE;
			if (bRemoveFromHead)
			{
			    // Get the first buffer
			    pMemBlock = (CHXMemoryBlock *) m_freeList.RemoveHead();
			}
			else
			{
			    // Get the last buffer
			    pMemBlock = (CHXMemoryBlock *) m_freeList.RemoveTail();
			}
			
			// Add ref the block so we know we are using it
			pMemBlock->AddRef();
			
			// setup the map so we don't loose the block
			pRetVal = pMemBlock->GetSampleBase();
			m_MemBlockMap.SetAt(pRetVal, pMemBlock);
			*pPacketBuffer = (IHXUnknown *)pMemBlock;
		}

		// if we didn't find any blocks in the list allocate a new one
		if (pRetVal == NULL)
		{
			CHXMemoryBlock * pMemBlock = new CHXMemoryBlock(this, m_bUseGlobalAlloc);
                        HX_ASSERT(pMemBlock);
                        
			if (pMemBlock != NULL)
			{
				if (pMemBlock->Allocate(m_uSize))
				{
					pMemBlock->AddRef();
					pRetVal = pMemBlock->GetSampleBase();
					m_MemBlockMap.SetAt(pRetVal, pMemBlock);
					m_AllocCount++;
					*pPacketBuffer = (IHXUnknown *)pMemBlock;
				}
                                else
                                {
                                    HX_ASSERT(FALSE);
                                    delete pMemBlock;
                                }
			}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -