/** * Tencent is pleased to support the open source community by making MSEC available. * * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. * * Licensed under the GNU General Public License, Version 2.0 (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/GPL-2.0 * * 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. */ /** * @file mt_mbuf_pool.h **/ #ifndef __MT_MBUF_POOL_H__ #define __MT_MBUF_POOL_H__ #include #include #include "hash_list.h" namespace NS_MICRO_THREAD { using std::queue; enum BUFF_TYPE { BUFF_UNDEF = 0, BUFF_RECV = 1, BUFF_SEND = 2, }; typedef TAILQ_ENTRY(MtMsgBuf) MsgBufLink; typedef TAILQ_HEAD(__MtbuffTailq, MtMsgBuf) MsgBufQueue; class MtMsgBuf { private: int _max_len; int _msg_len; int _buf_type; int _recv_len; int _send_len; void* _msg_buff; public: MsgBufLink _entry; MtMsgBuf(int max_len) { _max_len = max_len; _msg_len = 0; _buf_type = BUFF_UNDEF; _recv_len = 0; _send_len = 0; _msg_buff = malloc(max_len); }; ~MtMsgBuf() { if (_msg_buff) { free(_msg_buff); _msg_buff = NULL; } }; void SetBuffType(BUFF_TYPE type) { _buf_type = (int)type; }; BUFF_TYPE GetBuffType() { return (BUFF_TYPE)_buf_type; }; void Reset() { _msg_len = 0; _recv_len = 0; _send_len = 0; _buf_type = BUFF_UNDEF; }; void SetMsgLen(int msg_len) { _msg_len = msg_len; }; int GetMsgLen() { return _msg_len; }; int GetMaxLen() { return _max_len; }; void* GetMsgBuff() { return _msg_buff; }; int GetHaveSndLen() { return _send_len; }; void SetHaveSndLen(int snd_len) { _send_len = snd_len; }; int GetHaveRcvLen() { return _recv_len; }; void SetHaveRcvLen(int rcv_len) { _recv_len = rcv_len; }; }; class MsgBufMap : public HashKey { public: MsgBufMap(int buff_size, int max_free) { _max_buf_size = buff_size; _max_free = max_free; this->SetDataPtr(this); _queue_num = 0; TAILQ_INIT(&_msg_queue); }; explicit MsgBufMap(int buff_size) { _max_buf_size = buff_size; TAILQ_INIT(&_msg_queue); }; ~MsgBufMap() { MtMsgBuf* ptr = NULL; MtMsgBuf* tmp = NULL; TAILQ_FOREACH_SAFE(ptr, &_msg_queue, _entry, tmp) { TAILQ_REMOVE(&_msg_queue, ptr, _entry); delete ptr; _queue_num--; } TAILQ_INIT(&_msg_queue); }; MtMsgBuf* GetMsgBuf(){ MtMsgBuf* ptr = NULL; if (!TAILQ_EMPTY(&_msg_queue)) { ptr = TAILQ_FIRST(&_msg_queue); TAILQ_REMOVE(&_msg_queue, ptr, _entry); _queue_num--; } else { ptr = new MtMsgBuf(_max_buf_size); } return ptr; }; void FreeMsgBuf(MtMsgBuf* ptr){ if (_queue_num >= _max_free) { delete ptr; } else { ptr->Reset(); TAILQ_INSERT_TAIL(&_msg_queue, ptr, _entry); _queue_num++; } }; virtual uint32_t HashValue(){ return _max_buf_size; }; virtual int HashCmp(HashKey* rhs){ return this->_max_buf_size - (int)rhs->HashValue(); }; private: int _max_free; int _max_buf_size; int _queue_num; MsgBufQueue _msg_queue; }; class MsgBuffPool { public: static MsgBuffPool* Instance (void); static void Destroy(void); void SetMaxFreeNum(int max_free) { _max_free = max_free; }; MtMsgBuf* GetMsgBuf(int max_size); void FreeMsgBuf(MtMsgBuf* msg_buf); ~MsgBuffPool(); private: explicit MsgBuffPool(int max_free = 300); static MsgBuffPool * _instance; int _max_free; HashList* _hash_map; }; } #endif