共享内存队列的实现

共享内存队列类:(结构体Header,结构体Record,结构体Attr)

 共享内存队列
 
class ShmQueue {
public:
    /**
     * 队列头
     */
    struct Header {
        volatile unsigned int head;
        volatile unsigned int tail;
        unsigned int size;
	time_t createTime;

        long long in;
        long long out;
    };

    /**
     * 记录头
     */
    struct Record {
        enum {
            FRM_FIRST = 0x1, /**< 首个请求片断 */
            FRM_LAST = 0x2,  /**< 最后一个请求片断 */
            FRM_ALL = FRM_FIRST | FRM_LAST, /**< 完整数据包 */

            FRM_ERR = 0x4, /**< 错误包 */
	    FRM_NULL = 0x8, /**< 空包 */

            HAS_ATTR = 0x10, /**< 带有 attr */
            END_OF_QUEUE = 0x20, /**< 队列结束 */
			REQ_PENDING = 0x40, /**< 正在处理中 */
        	REQ_TRANSIT = 0x80, /**< 是否中转产生的请求 */
		};

		enum Mask {
			NEWSYNC_MASK = 0x1,
			VOIPSYNC_MASK = 0x2,
		};

		Record() {
			memset(this, 0, sizeof(Record));
		}
		enum {
		};
		
        unsigned int uid;
        unsigned int clientId;
        unsigned int cmd;
        unsigned int seq;
        unsigned int flags;
        unsigned int len;
        long long time;
	unsigned int mask;
    };

	/**
	 * LogicAttr, 只能增加字段,不能删除字段
	 */
	struct LogicAttr {
	unsigned int logicLen; // 整个LogicAttr的长度  
	long long reqTime;
 	unsigned char deviceId[16];
        unsigned short clientType;
	unsigned int state;
        unsigned int ver;
	//unsigned int notifyMask;
        unsigned int last_check_act_time;
        char sessionKey[32];
	//unsigned short keyLen;
	//char keyBuf[128];
        unsigned int terminal_type; //for Happy-City web client
        char reserved[16];
	};
	
    /**
     * 基本属性
     */
    struct BasicAttr {
	long long connTime;
        long long activeTime;
		
	unsigned int clientIp;
        unsigned int serverIp;
        unsigned short clientPort;
        unsigned short serverPort;
   
	unsigned int reqCount;
        unsigned int respCount;
	unsigned int oobCount;
  
	unsigned int reqBytes;
	unsigned int respBytes;
	unsigned int oobBytes;
  
	unsigned short pendingReqCount;
	unsigned short pendingRespCount;
	unsigned short pendingOobCount;
   };

    /**
     * 属性
     */
    struct Attr {
        BasicAttr basic;
	LogicAttr logic;
    };

    /**
     * 构造函数
     */
    ShmQueue() : _header(0), _base(0), _fifo(-1) {}

    /**
     * 析构函数
     */
    ~ShmQueue() {
        close();
    }

	/**
	 * 获取header
	 */
	Header* header() const {
		return _header;
	}

分配空间函数:

在共享内存内循环使用

unsigned int alloc(unsigned int n, unsigned int& begin) const {
        begin = _header->tail;//为了再次分配是从上次数据尾部开始
        if (_header->tail < _header->head) { // tail -> head,此时尾部在前
            if (_header->tail + n < _header->head) {//如果尾部到头部空间大于n,可以分配
                return _header->tail + n;
            }
            return _header->tail; // 没空间
        } else if (_header->tail + n <= _header->size) { // head -> tail,头部在前,_header->size是分配空间减去Header
            return _header->tail + n;
        } else {//头部在前,尾部不够空间分配
            // 舍弃最后一段, 从头开始分配,再判断开始位置到header距离
            if (n < _header->head) {
                // 设置队列结束标识
                if (_header->tail + sizeof(Record) <= _header->size) {
                    Record record;
                    record.flags = Record::END_OF_QUEUE;
                    memcpy(_base + _header->tail, &record, sizeof(Record));
                }

                begin = 0;
                return n;
            }
            return _header->tail; // 没空间
        }
    }
添加数据函数

 /**
     * 写入数据到队列
     */
    size_t add(Record& record, Attr* attr, mm::ByteBuffer* data) {
		// 计算空间
        if (!data) {
			record.len = 0;
		}
		
        unsigned int len = record.len + sizeof(Record);//为什么需要在前面加上record.len,其代表的是什么,应该是在接收到
        if (attr) {
            /*if (attr->logic.logicLen  == 0) {
                attr->logic.logicLen  = 4;
            }*/
            len += sizeof( Attr );
			//len += sizeof( Attr ) - sizeof( LogicAttr ) + attr->logic.logicLen ;
            record.flags |= Record::HAS_ATTR;
        } else {
			record.flags &= ~Record::HAS_ATTR;
		}

        // 分配空间
        unsigned int begin = 0;
        unsigned int tail = alloc(len, begin);//??

        // 写入数据
        if (tail != _header->tail) {
            // record
            memcpy(_base + begin, &record, sizeof(Record));
            begin += sizeof(Record);

            // attr
            if (attr) {
                memcpy(_base + begin, attr, sizeof(Attr));
                //begin += sizeof(Attr) - sizeof(LogicAttr) + attr->logic.logicLen;
                begin += sizeof(Attr);          
            }

            // data
            if (data) {
				data->read(_base + begin, record.len);
			}

			Comm::LogDebug("client %u uin %u write %u bytes to queue %d [ %u %u %u ]",
                    record.clientId, record.uid, record.len, _shmId, _header->head,
				   	_header->tail, _header->size);

           /* if (attr)
            {
                Comm::LogDebug("DEBUG_G: logic:%d", attr->logic.logicLen);
            }
            if (data)
            {
                Comm::LogDebug("DEBUG_G: to queue pos:%d len:%d:%s ", begin, record.len, data->base());
            }*/

            _header->tail = tail;
			_header->in++;
            return len;
        } else {
            Comm::LogDebug("client %u uin %u ERR: failed to write %u bytes to queue %d [ %u %u %u ]",
                    record.clientId, record.uid, record.len, _shmId, _header->head,
				   	_header->tail, _header->size);
            return 0;
        }
    }
	

取数据

/**
     * 从队列获取数据
     */
    size_t get(Record& record, Attr& attr, mm::ByteBuffer& data) {
        if (_header->head != _header->tail) {
            // 判断是否移动到开头
            if (_header->head + sizeof(Record) > _header->size) {
                _header->head = 0;
            }//这里为什么要这样移动

            // record
            memcpy(&record, _base + _header->head, sizeof(Record));
            if (record.clientId == 0 && record.uid == 0 && record.cmd == 0
                    && record.flags == Record::END_OF_QUEUE) {
                // 切换到开头, 再读一次
                _header->head = 0;
                memcpy(&record, _base, sizeof(Record));
            }

            // attr
            unsigned int len = sizeof(Record);
            if (record.flags & Record::HAS_ATTR) {
                memcpy(&attr, _base + _header->head + len, sizeof(Attr));
                len += sizeof(Attr);
				// len += sizeof( Attr ) - sizeof( LogicAttr ) + attr.logic.logicLen;

                /*if (attr.logic.logicLen == 4) {
                    attr.logic.logicLen = 0;
                }*/
            }

            // data
            data.write(_base + _header->head + len, record.len);
            len += record.len;

            Comm::LogDebug("client %u uin %u read %u bytes from queue %d [ %u %u %u ]",
                    record.clientId, record.uid, record.len, _shmId,
					_header->head, _header->tail, _header->size);

            // Comm::LogDebug("DEBUG_G:getqueue pos:%d logic:%d %d %d", _header->head + len - record.len, attr.logic.logicLen, data.remaining(), data.base());
            
			_header->head += len;
			_header->out++;
            return len;
        } else {
            record.len = 0;
            record.flags &= ~Record::HAS_ATTR;
            return 0;
        }
    }



  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值