tc_mem_queue是用内存实现的队列, 源码很简单, 无非就是一个队列而已。 之所以要这么玩, 估计比stl queue的效率更高?
看看源码:
/**
* Tencent is pleased to support the open source community by making Tars available.
*
* Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
#include "util/tc_mem_queue.h"
#include
#include
#include
#include
#include
namespace tars
{
TC_MemQueue::TC_MemQueue()
:_pctrlBlock(NULL)
,_paddr(NULL)
,_size(0)
,_pstModifyHead(NULL)
{
}
void TC_MemQueue::create(void *pAddr, size_t iSize)
{
assert(pAddr);
assert(iSize != 0);
_size = iSize;
_pctrlBlock = (CONTROL_BLOCK*)pAddr;
_pstModifyHead = static_cast((void*)((char*)pAddr + sizeof(CONTROL_BLOCK)));
_paddr = (void *)((char *)_pctrlBlock + sizeof(CONTROL_BLOCK) + sizeof(tagModifyHead));
_pctrlBlock->iMemSize = iSize;
_pctrlBlock->iTopIndex = 0;
_pctrlBlock->iBotIndex = 0;
_pctrlBlock->iPopCount = 0;
_pctrlBlock->iPushCount = 0;
}
void TC_MemQueue::connect(void *pAddr, size_t iSize)
{
assert(pAddr);
_pctrlBlock = (CONTROL_BLOCK*)pAddr;
assert(iSize == _pctrlBlock->iMemSize);
_size = _pctrlBlock->iMemSize;
_pstModifyHead = static_cast((void*)((char*)pAddr + sizeof(CONTROL_BLOCK)));
_paddr = (void *)((char *)_pctrlBlock + sizeof(CONTROL_BLOCK) + sizeof(tagModifyHead));
}
bool TC_MemQueue::isFull(size_t iSize)
{
doUpdate();
size_t iTopIndex = _pctrlBlock->iTopIndex;
size_t iBotIndex = _pctrlBlock->iBotIndex;
if(iTopIndex < iBotIndex)
{
return (iTopIndex + sizeof(size_t) + iSize >= iBotIndex);
}
else if(iTopIndex > iBotIndex)
{
return iTopIndex + sizeof(size_t) + iSize >= iBotIndex + queueSize();
}
return false;
}
/**
* 获取空闲的空间大小
*/
size_t TC_MemQueue::getFreeSize()
{
doUpdate();
size_t iTopIndex = _pctrlBlock->iTopIndex;
size_t iBotIndex = _pctrlBlock->iBotIndex;
if(iTopIndex < iBotIndex)
{
return iBotIndex - iTopIndex;
}
else if(iTopIndex > iBotIndex)
{
return queueSize() - iTopIndex + iBotIndex;
}
else
{
return _size - sizeof(CONTROL_BLOCK) - sizeof(tagModifyHead);
}
}
bool TC_MemQueue::isEmpty()
{
doUpdate();
return (_pctrlBlock->iTopIndex == _pctrlBlock->iBotIndex);
}
size_t TC_MemQueue::queueSize()
{
doUpdate();
return _size - sizeof(CONTROL_BLOCK) - sizeof(tagModifyHead);
}
size_t TC_MemQueue::elementCount()
{
doUpdate();
size_t iPushCount = _pctrlBlock->iPushCount;
size_t iPopCount = _pctrlBlock->iPopCount;
if(iPushCount >= iPopCount)
{
return iPushCount - iPopCount;
}
return numeric_limits::max() - iPopCount + iPushCount;
}
bool TC_MemQueue::pop_front(string &sOut)
{
if(isEmpty())
{
return false;
}
doUpdate();
//大小没有分隔
if(_pctrlBlock->iBotIndex + sizeof(size_t) <= queueSize())
{
size_t iSize;
memcpy((char*)&iSize, (const char*)_paddr + _pctrlBlock->iBotIndex, sizeof(size_t));
sOut.reserve(iSize);
//文件没有分隔
if(_pctrlBlock->iBotIndex + sizeof(size_t) + iSize <= queueSize())
{
sOut.assign((char*)_paddr + _pctrlBlock->iBotIndex + sizeof(size_t), iSize);
update(&_pctrlBlock->iBotIndex, _pctrlBlock->iBotIndex + sizeof(size_t) + iSize);
}
else
{
//前面的数据长度
size_t iLeftSize = queueSize() - _pctrlBlock->iBotIndex - sizeof(size_t);
sOut.assign((char*)_paddr + _pctrlBlock->iBotIndex + sizeof(size_t), iLeftSize);
sOut.append((char*)_paddr, iSize - iLeftSize);
update(&_pctrlBlock->iBotIndex, iSize - iLeftSize);
}
}
else
{
size_t iSize;
size_t iLeftSize = queueSize() - _pctrlBlock->iBotIndex;
memcpy((char*)&iSize, (const char*)_paddr + _pctrlBlock->iBotIndex, iLeftSize);
memcpy((char*)&iSize + iLeftSize, (const char*)_paddr, sizeof(size_t) - iLeftSize);
sOut.assign((char*)_paddr + sizeof(size_t) - iLeftSize, iSize);
update(&_pctrlBlock->iBotIndex, iSize + sizeof(size_t) - iLeftSize);
}
update(&_pctrlBlock->iPopCount, _pctrlBlock->iPopCount + 1);
doUpdate(true);
return true;
}
bool TC_MemQueue::push_back(const string &sIn)
{
return push_back(sIn.c_str(),sIn.length());
}
bool TC_MemQueue::push_back(const char *pvIn, size_t iSize)
{
if(isFull(iSize))
{
return false;
}
doUpdate();
//没有跨越共享内存边界
if(_pctrlBlock->iTopIndex + sizeof(size_t) + iSize <= queueSize())
{
memcpy((char*)_paddr + _pctrlBlock->iTopIndex, (const char*)&iSize, sizeof(size_t));
memcpy((char*)_paddr + _pctrlBlock->iTopIndex + sizeof(size_t), (const char*)pvIn, iSize);
update(&_pctrlBlock->iTopIndex, _pctrlBlock->iTopIndex + sizeof(size_t) + iSize);
}
//跨越了共享内存边界
else
{
//共享内存剩下的大小
size_t iLeftSize = queueSize() - _pctrlBlock->iTopIndex;
//iSize跨越了共享内存边界
if(iLeftSize < sizeof(size_t))
{
if(iLeftSize > 0)
{
memcpy((char*)_paddr + _pctrlBlock->iTopIndex, (const char*)&iSize, iLeftSize);
}
memcpy((char*)_paddr, (const char*)&iSize + iLeftSize, sizeof(size_t) - iLeftSize);
memcpy((char*)_paddr + sizeof(size_t) - iLeftSize, (const char*)pvIn, iSize);
update(&_pctrlBlock->iTopIndex, iSize + sizeof(size_t) - iLeftSize);
}
else
{
//iSize没有跨越共享内存边界
memcpy((char*)_paddr + _pctrlBlock->iTopIndex, (const char*)&iSize, sizeof(size_t));
size_t iLeftSize1 = iLeftSize - sizeof(size_t);
if(iLeftSize1 > 0)
{
memcpy((char*)_paddr + _pctrlBlock->iTopIndex + sizeof(size_t), (const char*)pvIn, iLeftSize1);
}
memcpy((char*)_paddr, (const char*)pvIn + iLeftSize1, iSize - iLeftSize1);
update(&_pctrlBlock->iTopIndex, iSize - iLeftSize1);
}
}
update(&_pctrlBlock->iPushCount, _pctrlBlock->iPushCount + 1);
doUpdate(true);
return true;
}
void TC_MemQueue::doUpdate(bool bUpdate)
{
if(bUpdate)
{
_pstModifyHead->_cModifyStatus = 2;
}
//==1, copy过程中, 程序失败, 需要清除状态
if(_pstModifyHead->_cModifyStatus == 1)
{
_pstModifyHead->_iNowIndex = 0;
for(size_t i = 0; i < sizeof(_pstModifyHead->_stModifyData) / sizeof(tagModifyData); i++)
{
_pstModifyHead->_stModifyData[i]._iModifyAddr = 0;
_pstModifyHead->_stModifyData[i]._cBytes = 0;
_pstModifyHead->_stModifyData[i]._iModifyValue = 0;
}
_pstModifyHead->_cModifyStatus = 0;
}
//==2, 已经修改成功, 但是没有copy到内存中, 需要更新到内存中
else if(_pstModifyHead->_cModifyStatus == 2)
{
for(size_t i = 0; i < _pstModifyHead->_iNowIndex; i++)
{
if(_pstModifyHead->_stModifyData[i]._cBytes == sizeof(size_t))
{
*(size_t*)((char*)_pctrlBlock + _pstModifyHead->_stModifyData[i]._iModifyAddr) = _pstModifyHead->_stModifyData[i]._iModifyValue;
}
else if(_pstModifyHead->_stModifyData[i]._cBytes == sizeof(bool))
{
*(bool*)((char*)_pctrlBlock + _pstModifyHead->_stModifyData[i]._iModifyAddr) = (bool)_pstModifyHead->_stModifyData[i]._iModifyValue;
}
else
{
assert(true);
}
}
_pstModifyHead->_iNowIndex = 0;
_pstModifyHead->_cModifyStatus = 0;
}
//==0, 正常状态
else if(_pstModifyHead->_cModifyStatus == 0)
{
return;
}
}
void TC_MemQueue::update(void* iModifyAddr, size_t iModifyValue)
{
_pstModifyHead->_cModifyStatus = 1;
_pstModifyHead->_stModifyData[_pstModifyHead->_iNowIndex]._iModifyAddr = (char*)iModifyAddr - (char*)_pctrlBlock;
_pstModifyHead->_stModifyData[_pstModifyHead->_iNowIndex]._iModifyValue = iModifyValue;
_pstModifyHead->_stModifyData[_pstModifyHead->_iNowIndex]._cBytes = sizeof(iModifyValue);
_pstModifyHead->_iNowIndex++;
assert(_pstModifyHead->_iNowIndex < sizeof(_pstModifyHead->_stModifyData) / sizeof(tagModifyData));
}
void TC_MemQueue::update(void* iModifyAddr, bool bModifyValue)
{
_pstModifyHead->_cModifyStatus = 1;
_pstModifyHead->_stModifyData[_pstModifyHead->_iNowIndex]._iModifyAddr = (char*)iModifyAddr - (char*)_pctrlBlock;
_pstModifyHead->_stModifyData[_pstModifyHead->_iNowIndex]._iModifyValue = bModifyValue;
_pstModifyHead->_stModifyData[_pstModifyHead->_iNowIndex]._cBytes = sizeof(bModifyValue);
_pstModifyHead->_iNowIndex++;
assert(_pstModifyHead->_iNowIndex < sizeof(_pstModifyHead->_stModifyData) / sizeof(tagModifyData));
}
}
可以看到, 都是queue的基本操作实现