tars源码漫谈第40篇------tc_squeue.h(结构化队列)

      看了一下tars的整个源码, 没有发现用到tc_squeue中的TC_SQueue类, 我们也不重点关注。

      来简单看一下:

private:
    const static unsigned long ReserveLen = 8;
    const static unsigned long MarkLen = sizeof(unsigned long);
    struct Header
    {
        unsigned long iBufSize;
        unsigned long iReserveLen; // must be 8
        unsigned long iBegin;
        unsigned long iEnd;
        unsigned long iNum;        // 增加一个数量标记,不一定准确
    };

    Header *_header;
    char *_data;

      很典型的buffer结构。  随后便是对这个buffer的各种操作, 简单瞅一眼:

/**
 * 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.
 */

#ifndef __TC_SQueue_H__
#define __TC_SQueue_H__

#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <stdexcept>
#include <iostream>
#include <assert.h>
#include <iostream>

/**
 * 结构化的queue,在一边读一边写的情况下可以不用加锁,是线程(进程)安全的
 * 如果多个同时读写,需要加锁
 * 增加一个数量标记,在一边读一边写的情况下不一定准确完全准确 
*/

namespace tars
{

class TC_SQueue
{
public:
    TC_SQueue() {_header = NULL;_data = NULL;}
    ~TC_SQueue() {_header = NULL;_data = NULL;}

    void attach(char* pBuf, unsigned long iBufSize) throw (TC_Exception)
    {
        if(iBufSize <= sizeof(Header)+MarkLen+ReserveLen) 
        {
            throw TC_Exception("TC_SQueue::attach fail:iBufSize is too small");
        }

        _header = (Header *)pBuf;
        _data = pBuf+sizeof(Header);
        if(_header->iBufSize != iBufSize - sizeof(Header))
            throw TC_Exception("TC_SQueue::attach fail: iBufSize != iBufSize - sizeof(Header);");
        if(_header->iReserveLen != ReserveLen)
            throw TC_Exception("TC_SQueue::attach fail: iReserveLen != ReserveLen");
        if(_header->iBegin >= _header->iBufSize)
            throw TC_Exception("TC_SQueue::attach fail: iBegin > iBufSize - sizeof(Header);");
        if(_header->iEnd > iBufSize - sizeof(Header))
            throw TC_Exception("TC_SQueue::attach fail: iEnd > iBufSize - sizeof(Header);");
    }

    void create(char* pBuf, unsigned long iBufSize) throw (TC_Exception)
    {
        if(iBufSize <= sizeof(Header)+MarkLen+ReserveLen) 
        {
            throw TC_Exception("TC_SQueue::create fail:iBufSize is too small");
        }

        _header = (Header *)pBuf;
        _data = pBuf+sizeof(Header);
        _header->iBufSize = iBufSize - sizeof(Header);
        _header->iReserveLen = ReserveLen;
        _header->iBegin = 0;
        _header->iEnd = 0;
        _header->iNum = 0;
    }

    bool pop(string& buffer)
    {
        unsigned long iEnd=_header->iEnd;
        unsigned tmp_num;
        if(_header->iBegin == iEnd) 
        {
            _header->iNum = 0;
            return false;
        }
        else if(_header->iBegin<iEnd) 
        {
            assert(_header->iBegin+MarkLen < iEnd);
            unsigned long len = GetLen(_data+_header->iBegin);
            assert(_header->iBegin+MarkLen+len <= iEnd);
            
            buffer.assign(_data+_header->iBegin+MarkLen, len);
            _header->iBegin += len+MarkLen;
            tmp_num = _header->iNum;
            if(tmp_num > 0) 
                _header->iNum = tmp_num-1;
        }
        else 
        {
            // 被分段
            assert(iEnd+ReserveLen <= _header->iBegin);
            unsigned long len = 0;
            unsigned long new_begin = 0;
            char *data_from = NULL;
            char *data_to = NULL;
            assert(_header->iBegin < _header->iBufSize);
            // 长度字段也被分段
            if(_header->iBegin+MarkLen > _header->iBufSize) 
            { 
                char tmp[16];
                memcpy(tmp,_data+_header->iBegin,_header->iBufSize-_header->iBegin);
                memcpy(tmp+_header->iBufSize-_header->iBegin,_data,_header->iBegin+MarkLen-_header->iBufSize);
                len = GetLen(tmp);
                data_from = _data+(_header->iBegin+MarkLen-_header->iBufSize); //
                new_begin = _header->iBegin+MarkLen-_header->iBufSize+len;
                assert(new_begin <= iEnd);
            } 
            else 
            {
                len = GetLen(_data+_header->iBegin);
                data_from = _data+_header->iBegin+MarkLen;
                if(data_from == _data+_header->iBufSize) data_from = _data;
                if(_header->iBegin+MarkLen+len < _header->iBufSize) { 
                    new_begin = _header->iBegin+MarkLen+len;
                } else { // 数据被分段
                    new_begin = _header->iBegin+MarkLen+len-_header->iBufSize;
                    assert(new_begin <= iEnd);
                }
            }
            data_to = _data+new_begin;

            if(data_to > data_from) 
            {
                assert(data_to - data_from == (long)len);
                buffer.assign(data_from, len);
            } 
            else 
            {
                buffer.assign(data_from, _data+_header->iBufSize-data_from);
                buffer.append(_data, data_to-_data);
                assert(_header->iBufSize-(data_from-data_to)== len);
            }
            _header->iBegin = new_begin;
            tmp_num = _header->iNum;
            if(tmp_num > 0) 
                _header->iNum = tmp_num-1;
        }

        return true;
    }
    
    bool push(const string& buffer)
    {
        return push(buffer.c_str(), buffer.length());
    }
    // 写端使用
    bool push(const char *buffer,unsigned long len)
    {
        if(len == 0) return true;
        unsigned long iBegin = _header->iBegin;
        if(_header->iEnd == iBegin) 
        {
            _header->iNum = 0;
            if(MarkLen+len+ReserveLen>_header->iBufSize) 
                return false;
        } 
        else if(_header->iEnd > iBegin) 
        {
            assert(iBegin+MarkLen < _header->iEnd);
            if(_header->iBufSize - _header->iEnd + iBegin < MarkLen+len+ReserveLen)
                return false;
        } 
        else 
        {
            assert(_header->iEnd+ReserveLen <= iBegin);
            if(iBegin - _header->iEnd < MarkLen+len+ReserveLen)
                return false;
        }

        // 长度字段被分段
        if(_header->iEnd+MarkLen > _header->iBufSize) 
        {
            char tmp[16]; SetLen(tmp,len);
            memcpy(_data+_header->iEnd,tmp,_header->iBufSize-_header->iEnd);
            memcpy(_data,tmp+_header->iBufSize-_header->iEnd,_header->iEnd+MarkLen-_header->iBufSize);
            memcpy(_data+_header->iEnd+MarkLen-_header->iBufSize,buffer,len);
            _header->iEnd = len+_header->iEnd+MarkLen-_header->iBufSize;
            assert(_header->iEnd+ReserveLen <= iBegin);
            _header->iNum++;
        } 
        // 数据被分段
        else if(_header->iEnd+MarkLen+len > _header->iBufSize)
        {
            SetLen(_data+_header->iEnd,len);
            memcpy(_data+_header->iEnd+MarkLen,buffer,_header->iBufSize-_header->iEnd-MarkLen);
            memcpy(_data,buffer+_header->iBufSize-_header->iEnd-MarkLen,len-(_header->iBufSize-_header->iEnd-MarkLen));
            _header->iEnd = len-(_header->iBufSize-_header->iEnd-MarkLen);
            assert(_header->iEnd+ReserveLen <= iBegin);
            _header->iNum++;
        }
        else 
        {
            SetLen(_data+_header->iEnd,len);
            memcpy(_data+_header->iEnd+MarkLen,buffer,len);
            _header->iEnd = (_header->iEnd+MarkLen+len)%_header->iBufSize;
            _header->iNum++;
        }
        return true;
    }

    // 读端使用
    //bool isEmpty() const {unsigned long iEnd=_header->iEnd;return _header->iBegin == iEnd;}
    bool empty() const {unsigned long iEnd=_header->iEnd;return _header->iBegin == iEnd;}
    // 写端使用
    bool full(unsigned long len) const
    {
        unsigned long iBegin = _header->iBegin;
        if(len==0) return false;

        if(_header->iEnd == iBegin) 
        {
            if(len+MarkLen+ReserveLen > _header->iBufSize) return true;
            return false;
        } 
        else if(_header->iEnd > iBegin) 
        {
            assert(iBegin+MarkLen < _header->iEnd);
            return _header->iBufSize - _header->iEnd + iBegin < MarkLen+len+ReserveLen;
        }
        assert(_header->iEnd+ReserveLen <= iBegin);
        return (iBegin - _header->iEnd < MarkLen+len+ReserveLen);
    }
    // 返回队列里的元素数量,不一定绝对准确,只能作为参考
    unsigned long size() const 
    {
        if (empty()) 
        {
            _header->iNum = 0;
        }
        return _header->iNum;
    } 

private:
    unsigned long GetLen(char *buf) {unsigned long u; memcpy((void *)&u,buf,MarkLen); return u;}
    void SetLen(char *buf,unsigned long u) {memcpy(buf,(void *)&u,MarkLen);}

private:
    const static unsigned long ReserveLen = 8;
    const static unsigned long MarkLen = sizeof(unsigned long);
    struct Header
    {
        unsigned long iBufSize;
        unsigned long iReserveLen; // must be 8
        unsigned long iBegin;
        unsigned long iEnd;
        unsigned long iNum;        // 增加一个数量标记,不一定准确
    };

    Header *_header;
    char *_data;
};

}
#endif

       可以大致看看, 鉴于tars中没用到, 所以不重点说。

 

 

 

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值