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

📄 memcache.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 "hxtypes.h"
#include "hxcom.h"      // IUnknown
#include "hxiids.h"     // GUIDs
#include "hxslist.h"    // CHXSimpleList
#include "hxthread.h"   // HXMutex
#include "hxstring.h"   // memcpy()
#include "hxcomm.h"     // IHXCommonClassFactory
#include "ihxpckts.h"   // IHXBuffer
#include "hxcache2.h"   // IHXCache2, IHXCacheObject, IHXCacheObjectResponse
#include "memcache.h"
#include "multilog.h"
#include "mlog_http.h"


/****************************************************************************
 *  CHXMemCacheObject::CHXMemCacheObject
 *
 *  Constructor
 */

CHXMemCacheObject::CHXMemCacheObject(IHXCommonClassFactory* /*IN*/  pClassFactory)
    : m_RefCount      (0),
      m_pMemResponse(NULL),
      m_pClassFactory(NULL),
      m_ulCapacity(0),
      m_lThreshold(50),
      m_ulUsedCapacity(0),
      m_pList(NULL),
      m_ulCurrentWriteOffset(0),
      m_pPendingAddBlock(NULL),
      m_bInAddBlockDone(FALSE),
      m_bInReadBlockDone(FALSE),
      m_pMutex(NULL),
      m_ulCurrentReadOffset(0)
{
    MLOG_HTTP("CHXMemCacheObject::CHXMemCacheObject()\n");

    if(pClassFactory != NULL)
    {
        m_pClassFactory = pClassFactory;
        m_pClassFactory->AddRef();
    }

    m_pPendingReadInfo.ulOffset = 0;
    m_pPendingReadInfo.ulLength = 0;
    m_pPendingReadInfo.pBlock = NULL;
    
    m_pList = new CHXSimpleList;

    #if defined(THREADS_SUPPORTED) || defined(_UNIX_THREADS_SUPPORTED)
        HXMutex::MakeMutex(m_pMutex);
    #else
        HXMutex::MakeStubMutex(m_pMutex);
    #endif

}

/****************************************************************************
 *  CHXMemCacheObject::~CHXMemCacheObject
 *
 *  Destructor
 */

CHXMemCacheObject::~CHXMemCacheObject()
{
    MLOG_HTTP("CHXMemCacheObject::~CHXMemCacheObject()\n");

    m_pMutex->Lock();

    // Destroy the list
    if(m_pList)
    {
        LISTPOSITION currPos = m_pList->GetHeadPosition();
        Info* currInfo;
        while(currPos != NULL)
        {
            currInfo = (Info *)m_pList->GetNext(currPos);
            currInfo->pBlock->Release();
            delete currInfo;
        }

        delete m_pList;
    }

    m_pMutex->Unlock();

    HX_DELETE(m_pMutex);

} // ~CHXMemCacheObject()


// IUnknown COM Interface Methods

/****************************************************************************
 *  IUnknown::AddRef
 *
 *  This routine increases the object reference count in a thread safe
 *  manner. The reference count is used to manage the lifetime of an object.
 *  This method must be explicitly called by the user whenever a new
 *  reference to an object is used.
 */

STDMETHODIMP_(UINT32) CHXMemCacheObject::AddRef(void)
{
    MLOG_HTTP("CHXMemCacheObject::AddRef()\n");

    return InterlockedIncrement(&m_RefCount);
}

/****************************************************************************
 *  IUnknown::Release
 *
 *  This routine decreases the object reference count in a thread safe
 *  manner, and deletes the object if no more references to it exist. It must
 *  be called explicitly by the user whenever an object is no longer needed.
 */

STDMETHODIMP_(UINT32) CHXMemCacheObject::Release(void)
{
    MLOG_HTTP("CHXMemCacheObject::Release()\n");

    if (InterlockedDecrement(&m_RefCount) > 0)
    {
	return m_RefCount;
    }

    delete this;
    return 0;
}


/****************************************************************************
 *  IUnknown::QueryInterface
 *
 *  This routine indicates which interfaces this object supports. If a given
 *  interface is supported, the object's reference count is incremented, and
 *  a reference to that interface is returned. Otherwise a NULL object and
 *  error code are returned. This method is called by other objects to
 *  discover the functionality of this object.
 */

STDMETHODIMP CHXMemCacheObject::QueryInterface(REFIID interfaceID,
					       void** ppInterfaceObj)
{
    MLOG_HTTP("CHXMemCacheObject::QueryInterface()\n");

    // By definition all COM objects support the IUnknown interface
    if (IsEqualIID(interfaceID, IID_IUnknown))
    {
	AddRef();
	*ppInterfaceObj = (IUnknown*)(IHXCacheObject*)this;
	return HXR_OK;
    }
    // IHXCacheObject interface is supported
    else if (IsEqualIID(interfaceID, IID_IHXCacheObject))
    {
	AddRef();
	*ppInterfaceObj = (IHXCacheObject*)this;
	return HXR_OK;
    }

    // No other interfaces are supported
    *ppInterfaceObj = NULL;
    return HXR_NOINTERFACE;
}


//IHXCacheObject methods

/************************************************************************
 *	Method:
 *
 *	    IHXCacheObject::Init
 *
 *	Purpose:
 *
 *	    Associates a cache object with the response object
 *	    it should notify of operation completeness.
 */

STDMETHODIMP
CHXMemCacheObject::Init(IHXCacheObjectResponse*     /*IN*/  pMemResponse,
                        UINT32                      /*IN*/  ulCapacity,
                        UINT32                      /*IN*/  lThreshold)
{
    MLOG_HTTP("CHXMemCacheObject::Init(Capacity = %u, Threshold = %d)\n", ulCapacity, lThreshold);

    HX_RESULT res = HXR_OK;

    if(pMemResponse != NULL)
    {
        // Release any previous response objects
        if(m_pMemResponse != NULL)
        {
            m_pMemResponse->Release();
        }

        m_pMemResponse = pMemResponse;
        pMemResponse->AddRef();
    
    }
    else
    {
        res = HXR_INVALID_PARAMETER;
    }

    m_ulCapacity = ulCapacity;

    if( (lThreshold < 0) || (lThreshold >= 100) ) 
    {
        res = HXR_INVALID_PARAMETER;
    }
    else
    {
        m_lThreshold = lThreshold;
    }

    m_pMemResponse->InitDone(res);

    // HXR_OK from this function indicates InitDone() will be called.
    // Since this statement is executed only after the above InitDone()
    // we return HXR_OK instead of res. 
    return HXR_OK;

} // Init()


/************************************************************************
     *	Method:
     *
     *	    IHXCacheObject::GetThreshold
     *
     *	Purpose:
     *
     *	    Obtain the threshold of the cache object.
     */

STDMETHODIMP_(UINT32)
CHXMemCacheObject::GetThreshold(void)
{
    MLOG_HTTP("CHXFileCacheObject::GetThreshold()\n"); 

    return m_lThreshold;

} // GetThreshold()

/************************************************************************
 *	Method:
 *
 *	    IHXCacheObject::ChangeThreshold
 *
 *	Purpose:
 *
 *	    The object keeps caching data until it is full (exhausts its 
 *      capacity). Once it is full, it will overwite existing cached data
 *      with new data ONLY if the percentage of cached data which has been
 *      read from the cache using the ReadBlock() method is *greater* than a
 *      given percentage of Capacity.. This percentage is set using the SetThreshold()
 *      method. In case the threshold is exceeded, the oldest added data
 *      (the data with the the least offset) will be discarded and the 
 *      amount of data discarded is so that the remaining cached data just
 *      satisfies the threshold condidtion (approximately).
 *
 *      This cache object is used in the HTTP/1.0 file system plugin for
 *      mobile devices and in this case, the threshold is set to 70%
 *      i.e., fNewThreshold = 0.7
 *
 */

STDMETHODIMP
CHXMemCacheObject::ChangeThreshold(UINT32  /*IN*/	lNewThreshold)
{
    MLOG_HTTP("CHXMemCacheObject::ChangeThreshold(%d)\n", lNewThreshold); 

    if( (lNewThreshold < 0) || (lNewThreshold >= 100) )
    {
        return HXR_INVALID_PARAMETER;
    }

    m_pMutex->Lock();

    UINT32 lOldThreshold = m_lThreshold;
    m_lThreshold = lNewThreshold;

    HX_RESULT res = _CheckForThresholdCondition();

    if(HXR_OK != res)
    {
        // Revert back as something got messed up.
        m_lThreshold = lOldThreshold;
    }

    m_pMutex->Unlock();

    return res;


} // ChangeThreshold()

/************************************************************************
 *	Method:
 *
 *	    IHXCacheObject::GetCapacity
 *
 *	Purpose:
 *
 *	    Obtain the capacity in bytes of the cache object.
 */

STDMETHODIMP_(UINT32)
CHXMemCacheObject::GetCapacity(void)
{
    MLOG_HTTP("CHXMemCacheObject::GetCapacity()\n"); 
    
    return m_ulCapacity;

} // GetCapacity()

/************************************************************************
 *	Method:
 *
 *	    IHXCacheObject::ChangeCapacity
 *
 *	Purpose:
 *
 *	    Change the capacity of the cache object.
 */
STDMETHODIMP
CHXMemCacheObject::ChangeCapacity(UINT32  /*IN*/	newByteCount) 
{
   MLOG_HTTP("CHXMemCacheObject::ChangeCapacity(%u)\n", newByteCount); 

   HX_RESULT res = HXR_OK;
    
   m_pMutex->Lock();

   UINT32 ulOldCapacity = m_ulCapacity;

   m_ulCapacity = newByteCount;

   int ulExcessData = m_ulUsedCapacity - newByteCount;
   
   if(ulExcessData > 0)
   {
       // Discard the excess data.
       res = _DiscardData((UINT32)ulExcessData);

       if(HXR_OK != res)
       {
           // Revert back to old capacity if you couldn't
           // discard data.
           m_ulCapacity = ulOldCapacity;    
       }
       else
       {
           // Capacity has changed, so threshold might have been exceeded.
           res = _CheckForThresholdCondition();
       }
   }

   m_pMutex->Unlock();

   m_pMemResponse->ChangeCapacityDone(res);
   
   // HXR_OK from this function indicates ChangeCapacityDone() will be called.
   // Since this statement is executed only after the above ChangeCapacityDone()
   // we return HXR_OK instead of res. 
   return HXR_OK;

} // ChangeCapacity()

/************************************************************************
 *	Method:
 *
 *	    IHXCacheObject::GetUnusedCapacity
 *
 *	Purpose:
 *
 *	    Obtain the unused capacity in bytes of the cache object.
 */

STDMETHODIMP_(UINT32)
CHXMemCacheObject::GetUnusedCapacity()
{
    MLOG_HTTP("CHXMemCacheObject::GetUnusedCapacity()\n");

    m_pMutex->Lock();

    UINT32 ulUnusedCapacity = m_ulCapacity - m_ulUsedCapacity;

    m_pMutex->Unlock();

    return ulUnusedCapacity;

} // GetUnusedCapacity()

/************************************************************************
 *	Method:
 *
 *	    IHXCacheObject::AddBlock
 *
 *	Purpose:
 *
 *	    Adds a block of data to the cache.
 */

STDMETHODIMP
CHXMemCacheObject::AddBlock(IHXBuffer*	/*IN*/	pBlock) 
{
    MLOG_HTTP("CHXMemCacheObject::AddBlock()\n");

    if(pBlock == NULL)
    {
        return HXR_INVALID_PARAMETER;
    }

    if(m_pList == NULL)
        return HXR_UNEXPECTED;
            
    if(m_pPendingAddBlock != NULL)
    {
        return HXR_UNEXPECTED;
    }
    else
    {
        m_pPendingAddBlock = pBlock;
        m_pPendingAddBlock->AddRef();
    }

    if(!m_bInAddBlockDone)
    {
        while(m_pPendingAddBlock)
        {

⌨️ 快捷键说明

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