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

📄 memcache.cpp

📁 著名的 helix realplayer 基于手机 symbian 系统的 播放器全套源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
            IHXBuffer* pTempBlock = m_pPendingAddBlock;
            m_pPendingAddBlock = NULL;

            UINT32 ulBlockSize = pTempBlock->GetSize();
            Info *pNewInfo = NULL;

            HX_RESULT res = HXR_OK;
            if(ulBlockSize != 0)
            {
                m_pMutex->Lock(); 
           
                // Can you accomodate this data?
                if(m_ulUsedCapacity + ulBlockSize > m_ulCapacity)
                {
                    res = HXR_OUTOFMEMORY;
                }
                else
                {
                    pNewInfo = new Info;
                    if(pNewInfo == NULL)
                        res = HXR_OUTOFMEMORY;
                }

                if(HXR_OK == res)
                {
                    // The new block should be contiguous
                    pNewInfo->ulOffset = m_ulCurrentWriteOffset;
                    pNewInfo->ulSize = ulBlockSize;
                    pNewInfo->pBlock = pTempBlock;

                    m_ulUsedCapacity += ulBlockSize;
                    m_ulCurrentWriteOffset += ulBlockSize;

                    m_pList->AddTail( (void *)pNewInfo );
                }
            

                m_pMutex->Unlock();
            }
            else
            {
                pTempBlock->Release();
            }

            m_bInAddBlockDone = TRUE;
            m_pMemResponse->AddBlockDone(res);
            m_bInAddBlockDone = FALSE;

        } // while
    }

    return HXR_OK;

} // AddBlock()

/************************************************************************
 *	Method:
 *
 *	    IHXCacheObject::VerifyBlock
 *
 *	Purpose:
 *
 *	    Verify that a block of data is in the cache.
 */

STDMETHODIMP
CHXMemCacheObject::VerifyBlock(UINT32	/*IN*/	ulBlockOffset,
			 UINT32	/*IN*/	ulBlockLength)
{
    MLOG_HTTP("CHXMemCacheObject::VeifyBlock()\n");

    if(m_pList == NULL)
        return HXR_UNEXPECTED;

    m_pMutex->Lock();
    
    // Critical Section starts

    BOOL bExists = TRUE;

    if(m_ulUsedCapacity == 0)
    {
        bExists = FALSE;
    }
    else
    {
        UINT32 ulLeastOffset = m_ulCurrentWriteOffset - m_ulUsedCapacity;
        UINT32 ulHighestOffset = m_ulCurrentWriteOffset - 1;

        
        BOOL bStartExists = (ulBlockOffset >= ulLeastOffset) && 
                            (ulBlockOffset <= ulHighestOffset);
        BOOL bEndExists = (ulBlockOffset + ulBlockLength - 1 >= ulLeastOffset) &&
                          (ulBlockOffset + ulBlockLength - 1 <= ulHighestOffset);

        bExists = bStartExists && bEndExists;
    }

    // Critical section ends

    m_pMutex->Unlock();

    m_pMemResponse->VerifyBlockDone(bExists);

    return HXR_OK;


} // VerifyBlock()

/************************************************************************
 *	Method:
 *
 *	    IHXCacheObject::ReadBlock
 *
 *	Purpose:
 *
 *	    Read a block out of the cache.
 */

STDMETHODIMP
CHXMemCacheObject::ReadBlock(UINT32	/*IN*/	ulBlockOffset,
		            UINT32	/*IN*/	ulBlockLength)
{
    MLOG_HTTP("CHXMemCacheObject::ReadBlock(Offset = %u, Length = %u)\n", ulBlockOffset, ulBlockLength);

    if(m_pList == NULL)
        return HXR_UNEXPECTED;

    if(m_pPendingReadInfo.pBlock != NULL)
        return HXR_UNEXPECTED;

    m_pClassFactory->CreateInstance(CLSID_IHXBuffer,
                     (void **) &m_pPendingReadInfo.pBlock);

    if(m_pPendingReadInfo.pBlock == NULL)
        return HXR_OUTOFMEMORY;

    HX_RESULT res = m_pPendingReadInfo.pBlock->SetSize(ulBlockLength);

    if(res != HXR_OK)
    {
        m_pPendingReadInfo.pBlock->Release();
        m_pPendingReadInfo.pBlock = NULL;
        return res;
    }

    m_pPendingReadInfo.ulLength = ulBlockLength;
    m_pPendingReadInfo.ulOffset = ulBlockOffset;

    if(!m_bInReadBlockDone)
    {
        while(m_pPendingReadInfo.pBlock)
        {
            HX_RESULT res2 = HXR_OK;

            // To prepare for the possibilty of ReadBlock()
            // being called from ReadBlockDone()
            IHXBuffer* pTempBlock = m_pPendingReadInfo.pBlock;
            m_pPendingReadInfo.pBlock = NULL;
            UINT32 ulTempLength = m_pPendingReadInfo.ulLength;
            m_pPendingReadInfo.ulLength = 0;
            UINT32 ulTempOffset = m_pPendingReadInfo.ulOffset;
            m_pPendingReadInfo.ulOffset = 0;

            m_pMutex->Lock();

            UINT32 ulLeastOffset = m_ulCurrentWriteOffset - m_ulUsedCapacity; 
            UINT32 ulHighestOffset = m_ulCurrentWriteOffset - 1;

            if(m_ulUsedCapacity == 0)
            {
                if(ulTempOffset >= m_ulCurrentWriteOffset)
                    res2 = HXR_INCOMPLETE;
                else
                    res2 = HXR_FAIL;
                    
                HX_RELEASE(pTempBlock);
                pTempBlock = NULL;

            }
            else if(ulTempOffset < ulLeastOffset)
            {
                res2 = HXR_FAIL;
                HX_RELEASE(pTempBlock);
                pTempBlock = NULL;
            }
            else if(ulTempOffset > ulHighestOffset)
            {
                res2 = HXR_INCOMPLETE;
                HX_RELEASE(pTempBlock);
                pTempBlock = NULL;

                // If 'forward data' requested, mark all data as read so
                // that old data can be discarded to make space for new data.
                //m_ulCurrentReadOffset = ulHighestOffset + 1; 
                m_ulCurrentReadOffset = ulTempOffset;
                _CheckForThresholdCondition();
            }
            else
            {
                // Fill the pTempBlock with data from the list
            
                UCHAR* ucTempBlockData = pTempBlock->GetBuffer();
                UINT32 ulBytesReadFromList = 0;

                LISTPOSITION currPos = m_pList->GetHeadPosition();
                Info* currInfo;

                while(currPos != NULL)
                {   
                    currInfo = (Info *)m_pList->GetNext(currPos);
                    UINT32 ulCurrLowOffset = currInfo->ulOffset;
                    UINT32 ulCurrHighOffset = currInfo->ulOffset + currInfo->ulSize - 1;
                    UCHAR* ucCurrBlockData = currInfo->pBlock->GetBuffer();

                    if( (ulTempOffset >= ulCurrLowOffset) && (ulTempOffset <= ulCurrHighOffset) )
                    {
                        UINT32 ulMatchSize = ( (ulCurrHighOffset - ulTempOffset + 1) < ulTempLength ) ?
                                                ulCurrHighOffset - ulTempOffset + 1 : ulTempLength;

                        memcpy((void*)(ucTempBlockData + ulBytesReadFromList),
                                (void*)(ucCurrBlockData + ulTempOffset - ulCurrLowOffset), ulMatchSize);

                        ulBytesReadFromList += ulMatchSize;
                        ulTempOffset += ulMatchSize;

                        ulTempLength -= ulMatchSize;

                        if(0 == ulTempLength)
                            break;
                    }
                }

                if(ulTempLength > 0)
                {
                    res2 = HXR_INCOMPLETE;
                    pTempBlock->SetSize(ulBytesReadFromList);   
                }
                else
                {
                    res2 = HXR_OK;
                }

                m_ulCurrentReadOffset = ulTempOffset;
                _CheckForThresholdCondition();

            }

            m_pMutex->Unlock();

            m_bInReadBlockDone = TRUE;
            m_pMemResponse->ReadBlockDone(res2, pTempBlock);
            m_bInReadBlockDone = FALSE;
            
            HX_RELEASE(pTempBlock);
        }

    }

    return HXR_OK;

} // ReadBlock()

/************************************************************************
 *	Method:
 *	    IHXCacheObject::Flush
 *
 *	Purpose:
 *
 *	    Releases all data buffers cached in the object. The object now
 *      gets to a same state as when it was newly created. After flushine,
 *	    the object can be used for reading/writing as before.
 */

STDMETHODIMP
CHXMemCacheObject::Flush(void) 
{
    MLOG_HTTP("CHXMemCacheObject::Flush()\n");

    if(!m_pList)
        return HXR_UNEXPECTED;;
    
    m_pMutex->Lock();

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

    m_pList->RemoveAll();
    m_ulUsedCapacity = 0;
    m_ulCurrentWriteOffset = 0;
    m_ulCurrentReadOffset = 0;

    m_pMutex->Unlock();

    m_pMemResponse->FlushDone(HXR_OK);

    return HXR_OK;

} // Flush()

/************************************************************************
 *	Method:
 *
 *	    IHXCacheObject::IsFull
 *
 *	Purpose:
 *
 *	    Can the cache object accept any more data for storage?
 */

STDMETHODIMP_(BOOL)
CHXMemCacheObject::IsFull()
{
    MLOG_HTTP("CHXMemCacheObject::IsFull()\n");

    m_pMutex->Lock();

    BOOL bIsFull = TRUE;
    if(m_ulUsedCapacity < m_ulCapacity)
        bIsFull = FALSE;
    
    m_pMutex->Unlock();

    return bIsFull;

} // IsFull()

/************************************************************************
 *	Method:
 *
 *	    IHXCacheObject::IsEmpty
 *
 *	Purpose:
 *
 *	    Does the cache object have any data stored?
 */

STDMETHODIMP_(BOOL)
CHXMemCacheObject::IsEmpty()
{
    MLOG_HTTP("CHXMemCacheObject::IsEmpty()\n");

    if(m_ulUsedCapacity == 0)
        return TRUE;
    else
        return FALSE;

} // IsEmpty()


// Discards exactly 'byteCount' amount of oldest data.
// Note that this method is not thread safe. The caller has to take 
// care of locking common data structures before calling this method.
HX_RESULT CHXMemCacheObject::_DiscardData(UINT32 byteCount)
{
    MLOG_HTTP("CHXMemCacheObject::_DiscardData(%u)\n", byteCount);

    HX_RESULT res = HXR_UNEXPECTED;

    UINT32 ulDiscardedData = 0;

    LISTPOSITION currHeadPos = NULL;
    Info *headInfo = NULL;

    while( (currHeadPos = m_pList->GetHeadPosition())!= NULL )
    {
        headInfo = (Info*)(m_pList->RemoveHead());
        UINT32 ulHeadBlockSize = headInfo->ulSize;

        if(ulDiscardedData + ulHeadBlockSize <= byteCount)
        {
            headInfo->pBlock->Release();
            delete headInfo;
            
            ulDiscardedData += ulHeadBlockSize;
        }
        else
        {
            if(ulDiscardedData + ulHeadBlockSize > byteCount)
            {
                UINT32 ulValidDataSize = (ulDiscardedData + ulHeadBlockSize - byteCount);
                UINT32 ulInvalidDataSize = ulHeadBlockSize - ulValidDataSize;

                Info *pNewInfo = new Info;
                if(pNewInfo == NULL)
                {
                   res = HXR_OUTOFMEMORY;
                   break;
                }

                m_pClassFactory->CreateInstance(CLSID_IHXBuffer,
                                               (void **) &(pNewInfo->pBlock));

                if(pNewInfo->pBlock == NULL)
                    break;

                res = pNewInfo->pBlock->SetSize(ulValidDataSize);

                if(res != HXR_OK)
                    break;

                memcpy( (void*)(pNewInfo->pBlock->GetBuffer()),
                        (void*)(headInfo->pBlock->GetBuffer()+ ulInvalidDataSize),
                        ulValidDataSize );

                pNewInfo->ulOffset = headInfo->ulOffset + ulInvalidDataSize;
                pNewInfo->ulSize = ulValidDataSize;

                m_pList->AddHead( (void *)pNewInfo );

                headInfo->pBlock->Release();
                delete headInfo;
            }


            ulDiscardedData = byteCount;
            headInfo = NULL;
            res = HXR_OK;
            break;
        }
    }

    m_ulUsedCapacity -= ulDiscardedData;

    return res;
}

// Check if utilizedData has exceeded THRESHOLD. If yes, discard 
// appropriate amount of data. Note that this
// method is not thread safe. The caller has to take care of 
// locking common data structures before calling this method.
HX_RESULT CHXMemCacheObject::_CheckForThresholdCondition()
{
    MLOG_HTTP("CHXMemCacheObject::_CheckForThresholdCondition()\n");

    if(m_ulUsedCapacity == 0)
    {
        return HXR_OK;
    }

    UINT32 ulLeastOffset = m_ulCurrentWriteOffset - m_ulUsedCapacity;
    UINT32 ulHighestOffset = m_ulCurrentWriteOffset - 1;

    HX_RESULT res = HXR_OK;

    INT32 ulExcess = (m_ulCurrentReadOffset - ulLeastOffset) - 
                      (INT32)(m_lThreshold * m_ulCapacity * 0.01);

    if(ulExcess > 0)
    {
        if(ulExcess > m_ulUsedCapacity)
            ulExcess = m_ulUsedCapacity; 

        res = _DiscardData(ulExcess);
    }

    return res;

} // _CheckForThresholdCondition()

⌨️ 快捷键说明

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