mirror of https://github.com/F-Stack/f-stack.git
Micro_thread: convert encoding of source files and remove chinese comments.
This commit is contained in:
parent
ef39c58b67
commit
35a813994b
|
@ -20,17 +20,20 @@
|
|||
########MAKEFILE##########
|
||||
|
||||
ifeq ($(FF_PATH),)
|
||||
$(error variable FF_PATH is not set)
|
||||
$(error variable FF_PATH is not set)
|
||||
endif
|
||||
|
||||
ifeq ($(FF_DPDK),)
|
||||
FF_DPDK= $(FF_PATH)/dpdk/x86_64-native-linuxapp-gcc
|
||||
endif
|
||||
|
||||
DEBUG= -g
|
||||
BINARY = libmt.a
|
||||
FF_LIB=$(FF_PATH)/libfstack.a
|
||||
DPDK_LIBS+= -L${FF_PATH}/lib -L${FF_DPDK}/lib -Wl,--whole-archive,-lfstack,--no-whole-archive
|
||||
DPDK_LIBS+= -Wl,--whole-archive -lrte_pmd_vmxnet3_uio -lrte_pmd_i40e -lrte_pmd_ixgbe -lrte_pmd_e1000 -lrte_pmd_ring
|
||||
DPDK_LIBS+= -Wl,--whole-archive -lrte_hash -lrte_kvargs -Wl,-lrte_mbuf -lethdev -lrte_eal -Wl,-lrte_mempool
|
||||
DPDK_LIBS+= -lrte_ring -lrte_cmdline -lrte_cfgfile -lrte_kni -lrte_timer -Wl,-lrte_pmd_virtio
|
||||
DPDK_LIBS+= -Wl,--no-whole-archive -lrt -lm -ldl -lcrypto -pthread
|
||||
FF_LIBS+= -L${FF_PATH}/lib -L${FF_DPDK}/lib -Wl,--whole-archive,-lfstack,--no-whole-archive
|
||||
FF_LIBS+= -Wl,--whole-archive -lrte_pmd_vmxnet3_uio -lrte_pmd_i40e -lrte_pmd_ixgbe -lrte_pmd_e1000 -lrte_pmd_ring
|
||||
FF_LIBS+= -Wl,--whole-archive -lrte_hash -lrte_kvargs -Wl,-lrte_mbuf -lethdev -lrte_eal -Wl,-lrte_mempool
|
||||
FF_LIBS+= -lrte_ring -lrte_cmdline -lrte_cfgfile -lrte_kni -lrte_timer -Wl,-lrte_pmd_virtio
|
||||
FF_LIBS+= -Wl,--no-whole-archive -lrt -lm -ldl -lcrypto -pthread
|
||||
|
||||
# Comment the following line if you are not using the gnu c compiler
|
||||
#C_ARGS = -Wall -g -fPIC -D_DEBUG
|
||||
|
@ -91,9 +94,9 @@ LIB_OBJ = micro_thread.o kqueue_proxy.o arch_ctx.o mt_session.o mt_notify.o mt_a
|
|||
libmt.a: $(LIB_OBJ)
|
||||
@echo -e Linking $(CYAN)$@$(RESET) ...$(RED)
|
||||
@-rm -f $@
|
||||
@ar crs $@ $^ $(FST_LIB) $(CRESET)
|
||||
@ar crs $@ $^ $(CRESET)
|
||||
@chmod +x $@
|
||||
|
||||
echo: echo.o libmt.a
|
||||
@echo -e Compile $(CYAN)$@$(RESET) ...$(RED)
|
||||
@$(CC) -O -gdwarf-2 -o $@ $^ -lstdc++ -ldl -lm $(DPDK_LIBS) $(CRESET)
|
||||
@$(CC) -O -gdwarf-2 -o $@ $^ -lstdc++ -ldl -lm $(FF_LIBS) $(CRESET)
|
||||
|
|
|
@ -1,561 +0,0 @@
|
|||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @filename epoll_proxy.cpp
|
||||
* @info epoll for micro thread manage
|
||||
*/
|
||||
|
||||
#include "epoll_proxy.h"
|
||||
#include "micro_thread.h"
|
||||
|
||||
using namespace NS_MICRO_THREAD;
|
||||
|
||||
/**
|
||||
* @brief 构造函数
|
||||
*/
|
||||
EpollProxy::EpollProxy()
|
||||
{
|
||||
_maxfd = EpollProxy::DEFAULT_MAX_FD_NUM;
|
||||
_epfd = -1;
|
||||
_evtlist = NULL;
|
||||
_eprefs = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief epoll初始化, 申请动态内存等
|
||||
*/
|
||||
int EpollProxy::InitEpoll(int max_num)
|
||||
{
|
||||
int rc = 0;
|
||||
if (max_num > _maxfd) // 如果设置的数目较大, 则调整最大fd数目
|
||||
{
|
||||
_maxfd = max_num;
|
||||
}
|
||||
|
||||
_epfd = epoll_create(_maxfd);
|
||||
if (_epfd < 0)
|
||||
{
|
||||
rc = -1;
|
||||
goto EXIT_LABEL;
|
||||
}
|
||||
fcntl(_epfd, F_SETFD, FD_CLOEXEC);
|
||||
|
||||
_eprefs = new FdRef[_maxfd];
|
||||
if (NULL == _eprefs)
|
||||
{
|
||||
rc = -2;
|
||||
goto EXIT_LABEL;
|
||||
}
|
||||
|
||||
_evtlist = (EpEvent*)calloc(_maxfd, sizeof(EpEvent));
|
||||
if (NULL == _evtlist)
|
||||
{
|
||||
rc = -3;
|
||||
goto EXIT_LABEL;
|
||||
}
|
||||
|
||||
struct rlimit rlim;
|
||||
memset(&rlim, 0, sizeof(rlim));
|
||||
if (getrlimit(RLIMIT_NOFILE, &rlim) == 0)
|
||||
{
|
||||
if ((int)rlim.rlim_max < _maxfd)
|
||||
{
|
||||
rlim.rlim_cur = rlim.rlim_max;
|
||||
setrlimit(RLIMIT_NOFILE, &rlim);
|
||||
rlim.rlim_cur = _maxfd;
|
||||
rlim.rlim_max = _maxfd;
|
||||
setrlimit(RLIMIT_NOFILE, &rlim);
|
||||
}
|
||||
}
|
||||
|
||||
EXIT_LABEL:
|
||||
|
||||
if (rc < 0)
|
||||
{
|
||||
TermEpoll();
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief epoll反初始化
|
||||
*/
|
||||
void EpollProxy::TermEpoll()
|
||||
{
|
||||
if (_epfd > 0)
|
||||
{
|
||||
close(_epfd);
|
||||
_epfd = -1;
|
||||
}
|
||||
|
||||
if (_evtlist != NULL)
|
||||
{
|
||||
free(_evtlist);
|
||||
_evtlist = NULL;
|
||||
}
|
||||
|
||||
if (_eprefs != NULL)
|
||||
{
|
||||
delete []_eprefs;
|
||||
_eprefs = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 将一个微线程侦听的所有socket送入epoll管理
|
||||
* @param fdset 微线程侦听的socket集合
|
||||
* @return true 成功, false 失败, 失败会尽力回滚, 减少影响
|
||||
*/
|
||||
bool EpollProxy::EpollAdd(EpObjList& obj_list)
|
||||
{
|
||||
bool ret = true;
|
||||
EpollerObj *epobj = NULL;
|
||||
EpollerObj *epobj_error = NULL;
|
||||
TAILQ_FOREACH(epobj, &obj_list, _entry)
|
||||
{
|
||||
if (!EpollAddObj(epobj))
|
||||
{
|
||||
MTLOG_ERROR("epobj add failed, fd: %d", epobj->GetOsfd());
|
||||
epoll_assert(0);
|
||||
epobj_error = epobj;
|
||||
ret = false;
|
||||
goto EXIT_LABEL;
|
||||
}
|
||||
}
|
||||
|
||||
EXIT_LABEL:
|
||||
|
||||
if (!ret)
|
||||
{
|
||||
TAILQ_FOREACH(epobj, &obj_list, _entry)
|
||||
{
|
||||
if (epobj == epobj_error)
|
||||
{
|
||||
break;
|
||||
}
|
||||
EpollDelObj(epobj);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 将一个微线程侦听的所有socket移除epoll管理
|
||||
* @param fdset 微线程侦听的socket集合
|
||||
* @return true 成功, false 失败
|
||||
*/
|
||||
bool EpollProxy::EpollDel(EpObjList& obj_list)
|
||||
{
|
||||
bool ret = true;
|
||||
|
||||
EpollerObj *epobj = NULL;
|
||||
TAILQ_FOREACH(epobj, &obj_list, _entry)
|
||||
{
|
||||
if (!EpollDelObj(epobj)) // failed also need continue, be sure ref count ok
|
||||
{
|
||||
MTLOG_ERROR("epobj del failed, fd: %d", epobj->GetOsfd());
|
||||
epoll_assert(0);
|
||||
ret = false;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 单个epfd更新epctrl, 成功需要更新当前监听事件值
|
||||
*/
|
||||
bool EpollProxy::EpollCtrlAdd(int fd, int events)
|
||||
{
|
||||
FdRef* item = FdRefGet(fd);
|
||||
if (NULL == item)
|
||||
{
|
||||
MT_ATTR_API(320851, 1); // fd error
|
||||
MTLOG_ERROR("epfd ref not find, failed, fd: %d", fd);
|
||||
epoll_assert(0);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 更新引用计数, 部分流程会依赖该计数, 失败要回滚
|
||||
item->AttachEvents(events);
|
||||
|
||||
int old_events = item->GetListenEvents();
|
||||
int new_events = old_events | events;
|
||||
if (old_events == new_events) {
|
||||
return true;
|
||||
}
|
||||
|
||||
int op = old_events ? EPOLL_CTL_MOD : EPOLL_CTL_ADD;
|
||||
EpEvent ev;
|
||||
ev.events = new_events;
|
||||
ev.data.fd = fd;
|
||||
if ((epoll_ctl(_epfd, op, fd, &ev) < 0) && !(op == EPOLL_CTL_ADD && errno == EEXIST))
|
||||
{
|
||||
MT_ATTR_API(320850, 1); // epoll error
|
||||
MTLOG_ERROR("epoll ctrl failed, fd: %d, op: %d, errno: %d", fd, op, errno);
|
||||
item->DetachEvents(events);
|
||||
epoll_assert(0);
|
||||
return false;
|
||||
}
|
||||
item->SetListenEvents(new_events);
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 单个epfd更新epctrl, 成功需要更新当前监听事件值
|
||||
*/
|
||||
bool EpollProxy::EpollCtrlDel(int fd, int events)
|
||||
{
|
||||
return EpollCtrlDelRef(fd, events, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 单个epfd更新epctrl, 检查引用计数, 可以预设长连接, 不会每次都epollctl
|
||||
*/
|
||||
bool EpollProxy::EpollCtrlDelRef(int fd, int events, bool use_ref)
|
||||
{
|
||||
FdRef* item = FdRefGet(fd);
|
||||
if (NULL == item)
|
||||
{
|
||||
MT_ATTR_API(320851, 1); // fd error
|
||||
MTLOG_ERROR("epfd ref not find, failed, fd: %d", fd);
|
||||
epoll_assert(0);
|
||||
return false;
|
||||
}
|
||||
|
||||
item->DetachEvents(events); // delete 失败不回滚处理
|
||||
int old_events = item->GetListenEvents();
|
||||
int new_events = old_events &~ events; // 默认情况
|
||||
|
||||
// 如果要按引用删除, 需要核查是否满足删除条件
|
||||
if (use_ref)
|
||||
{
|
||||
new_events = old_events;
|
||||
if (0 == item->ReadRefCnt()) {
|
||||
new_events = new_events & ~EPOLLIN;
|
||||
}
|
||||
if (0 == item->WriteRefCnt()) {
|
||||
new_events = new_events & ~EPOLLOUT;
|
||||
}
|
||||
}
|
||||
|
||||
if (old_events == new_events)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
int op = new_events ? EPOLL_CTL_MOD : EPOLL_CTL_DEL;
|
||||
EpEvent ev;
|
||||
ev.events = new_events;
|
||||
ev.data.fd = fd;
|
||||
if ((epoll_ctl(_epfd, op, fd, &ev) < 0) && !(op == EPOLL_CTL_DEL && errno == ENOENT))
|
||||
{
|
||||
MT_ATTR_API(320850, 1); // epoll error
|
||||
MTLOG_ERROR("epoll ctrl failed, fd: %d, op: %d, errno: %d", fd, op, errno);
|
||||
epoll_assert(0);
|
||||
return false;
|
||||
}
|
||||
item->SetListenEvents(new_events);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief 单个epfd更新epctrl, 如果失败, 完整回退
|
||||
*/
|
||||
bool EpollProxy::EpollAddObj(EpollerObj* obj)
|
||||
{
|
||||
if (NULL == obj)
|
||||
{
|
||||
MTLOG_ERROR("epobj input invalid, %p", obj);
|
||||
return false;
|
||||
}
|
||||
|
||||
FdRef* item = FdRefGet(obj->GetOsfd());
|
||||
if (NULL == item)
|
||||
{
|
||||
MT_ATTR_API(320851, 1); // fd error
|
||||
MTLOG_ERROR("epfd ref not find, failed, fd: %d", obj->GetOsfd());
|
||||
epoll_assert(0);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 不同的回调状态, 不同的方式处理 del 事件, 屏蔽连接复用方式的处理复杂性
|
||||
int ret = obj->EpollCtlAdd(item);
|
||||
if (ret < 0)
|
||||
{
|
||||
MTLOG_ERROR("epoll ctrl callback failed, fd: %d, obj: %p", obj->GetOsfd(), obj);
|
||||
epoll_assert(0);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 将一个微线程侦听的所有socket移除epoll管理
|
||||
* @param fdset 微线程侦听的socket集合
|
||||
* @return true 成功, false 失败
|
||||
*/
|
||||
bool EpollProxy::EpollDelObj(EpollerObj* obj)
|
||||
{
|
||||
if (NULL == obj)
|
||||
{
|
||||
MTLOG_ERROR("fdobj input invalid, %p", obj);
|
||||
return false;
|
||||
}
|
||||
|
||||
FdRef* item = FdRefGet(obj->GetOsfd());
|
||||
if (NULL == item)
|
||||
{
|
||||
MT_ATTR_API(320851, 1); // fd error
|
||||
MTLOG_ERROR("epfd ref not find, failed, fd: %d", obj->GetOsfd());
|
||||
epoll_assert(0);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 不同的回调状态, 不同的方式处理 del 事件, 屏蔽连接复用方式的处理复杂性
|
||||
int ret = obj->EpollCtlDel(item);
|
||||
if (ret < 0)
|
||||
{
|
||||
MTLOG_ERROR("epoll ctrl callback failed, fd: %d, obj: %p", obj->GetOsfd(), obj);
|
||||
epoll_assert(0);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 更新每个socket的最新接收事件信息
|
||||
* @param evtfdnum 收到事件的fd集合数目
|
||||
*/
|
||||
void EpollProxy::EpollRcvEventList(int evtfdnum)
|
||||
{
|
||||
int ret = 0;
|
||||
int osfd = 0;
|
||||
int revents = 0;
|
||||
FdRef* item = NULL;
|
||||
EpollerObj* obj = NULL;
|
||||
|
||||
for (int i = 0; i < evtfdnum; i++)
|
||||
{
|
||||
osfd = _evtlist[i].data.fd;
|
||||
item = FdRefGet(osfd);
|
||||
if (NULL == item)
|
||||
{
|
||||
MT_ATTR_API(320851, 1); // fd error
|
||||
MTLOG_ERROR("epfd ref not find, failed, fd: %d", osfd);
|
||||
epoll_assert(0);
|
||||
continue;
|
||||
}
|
||||
|
||||
revents = _evtlist[i].events;
|
||||
obj = item->GetNotifyObj();
|
||||
if (NULL == obj)
|
||||
{
|
||||
MTLOG_ERROR("fd notify obj null, failed, fd: %d", osfd);
|
||||
EpollCtrlDel(osfd, (revents & (EPOLLIN | EPOLLOUT)));
|
||||
continue;
|
||||
}
|
||||
obj->SetRcvEvents(revents);
|
||||
|
||||
// 1. 错误处理, 完毕后直接跳出
|
||||
if (revents & (EPOLLERR | EPOLLHUP))
|
||||
{
|
||||
obj->HangupNotify();
|
||||
continue;
|
||||
}
|
||||
|
||||
// 2. 可读事件, 非0返回值会跳出
|
||||
if (revents & EPOLLIN) {
|
||||
ret = obj->InputNotify();
|
||||
if (ret != 0) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 可写事件, 非0返回值会跳出
|
||||
if (revents & EPOLLOUT) {
|
||||
ret = obj->OutputNotify();
|
||||
if (ret != 0) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief epoll_wait 以及分发处理过程
|
||||
*/
|
||||
void EpollProxy::EpollDispath()
|
||||
{
|
||||
int wait_time = EpollGetTimeout();
|
||||
int nfd = epoll_wait(_epfd, _evtlist, _maxfd, wait_time);
|
||||
if (nfd <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
EpollRcvEventList(nfd);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 可读事件通知接口, 考虑通知处理可能会破坏环境, 可用返回值区分
|
||||
* @return 0 该fd可继续处理其它事件; !=0 该fd需跳出回调处理
|
||||
*/
|
||||
int EpollerObj::InputNotify()
|
||||
{
|
||||
MicroThread* thread = this->GetOwnerThread();
|
||||
if (NULL == thread)
|
||||
{
|
||||
epoll_assert(0);
|
||||
MTLOG_ERROR("Epoll fd obj, no thread ptr, wrong");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 多个事件同时到达, 防重复操作
|
||||
if (thread->HasFlag(MicroThread::IO_LIST))
|
||||
{
|
||||
MtFrame* frame = MtFrame::Instance();
|
||||
frame->RemoveIoWait(thread);
|
||||
frame->InsertRunable(thread);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 可写事件通知接口, 考虑通知处理可能会破坏环境, 可用返回值区分
|
||||
* @return 0 该fd可继续处理其它事件; !=0 该fd需跳出回调处理
|
||||
*/
|
||||
int EpollerObj::OutputNotify()
|
||||
{
|
||||
MicroThread* thread = this->GetOwnerThread();
|
||||
if (NULL == thread)
|
||||
{
|
||||
epoll_assert(0);
|
||||
MTLOG_ERROR("Epoll fd obj, no thread ptr, wrong");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 多个事件同时到达, 防重复操作
|
||||
if (thread->HasFlag(MicroThread::IO_LIST))
|
||||
{
|
||||
MtFrame* frame = MtFrame::Instance();
|
||||
frame->RemoveIoWait(thread);
|
||||
frame->InsertRunable(thread);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 异常通知接口, 关闭fd侦听, thread等待处理超时
|
||||
* @return 忽略返回值, 跳过其它事件处理
|
||||
*/
|
||||
int EpollerObj::HangupNotify()
|
||||
{
|
||||
MtFrame* frame = MtFrame::Instance();
|
||||
frame->EpollCtrlDel(this->GetOsfd(), this->GetEvents());
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 调整epoll侦听事件的回调接口, 长连接始终EPOLLIN, 偶尔EPOLLOUT
|
||||
* @param args fd引用对象的指针
|
||||
* @return 0 成功, < 0 失败, 要求事务回滚到操作前状态
|
||||
*/
|
||||
int EpollerObj::EpollCtlAdd(void* args)
|
||||
{
|
||||
MtFrame* frame = MtFrame::Instance();
|
||||
FdRef* fd_ref = (FdRef*)args;
|
||||
epoll_assert(fd_ref != NULL);
|
||||
|
||||
int osfd = this->GetOsfd();
|
||||
int new_events = this->GetEvents();
|
||||
|
||||
// 通知对象需要更新, FD通知对象理论上不会复用, 这里做冲突检查, 异常log记录
|
||||
EpollerObj* old_obj = fd_ref->GetNotifyObj();
|
||||
if ((old_obj != NULL) && (old_obj != this))
|
||||
{
|
||||
MTLOG_ERROR("epfd ref conflict, fd: %d, old: %p, now: %p", osfd, old_obj, this);
|
||||
return -1;
|
||||
}
|
||||
fd_ref->SetNotifyObj(this);
|
||||
|
||||
// 调用框架的epoll ctl接口, 屏蔽epoll ctrl细节
|
||||
if (!frame->EpollCtrlAdd(osfd, new_events))
|
||||
{
|
||||
MTLOG_ERROR("epfd ref add failed, log");
|
||||
fd_ref->SetNotifyObj(old_obj);
|
||||
return -2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 调整epoll侦听事件的回调接口, 长连接始终EPOLLIN, 偶尔EPOLLOUT
|
||||
* @param args fd引用对象的指针
|
||||
* @return 0 成功, < 0 失败, 要求事务回滚到操作前状态
|
||||
*/
|
||||
int EpollerObj::EpollCtlDel(void* args)
|
||||
{
|
||||
MtFrame* frame = MtFrame::Instance();
|
||||
FdRef* fd_ref = (FdRef*)args;
|
||||
epoll_assert(fd_ref != NULL);
|
||||
|
||||
int osfd = this->GetOsfd();
|
||||
int events = this->GetEvents();
|
||||
|
||||
// 通知对象需要更新, FD通知对象理论上不会复用, 这里做冲突检查, 异常log记录
|
||||
EpollerObj* old_obj = fd_ref->GetNotifyObj();
|
||||
if (old_obj != this)
|
||||
{
|
||||
MTLOG_ERROR("epfd ref conflict, fd: %d, old: %p, now: %p", osfd, old_obj, this);
|
||||
return -1;
|
||||
}
|
||||
fd_ref->SetNotifyObj(NULL);
|
||||
|
||||
// 调用框架的epoll ctl接口, 屏蔽epoll ctrl细节
|
||||
if (!frame->EpollCtrlDelRef(osfd, events, false)) // 引用有风险, 弊大于利, 关闭掉
|
||||
{
|
||||
MTLOG_ERROR("epfd ref del failed, log");
|
||||
fd_ref->SetNotifyObj(old_obj);
|
||||
return -2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -1,434 +0,0 @@
|
|||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @filename epoll_proxy.h
|
||||
* @info epoll for micro thread manage
|
||||
*/
|
||||
|
||||
#ifndef _EPOLL_PROXY___
|
||||
#define _EPOLL_PROXY___
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/resource.h>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
#include <sys/epoll.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <set>
|
||||
#include <vector>
|
||||
using std::set;
|
||||
using std::vector;
|
||||
|
||||
#define epoll_assert(statement)
|
||||
//#define epoll_assert(statement) assert(statement)
|
||||
|
||||
|
||||
namespace NS_MICRO_THREAD {
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
/* 操作系统头文件适配定义 */
|
||||
/******************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief add more detail for linux <sys/queue.h>, freebsd and University of California
|
||||
* @info queue.h version 8.3 (suse) diff version 8.5 (tlinux)
|
||||
*/
|
||||
#ifndef TAILQ_CONCAT
|
||||
|
||||
#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL)
|
||||
#define TAILQ_FIRST(head) ((head)->tqh_first)
|
||||
#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
|
||||
|
||||
#define TAILQ_LAST(head, headname) \
|
||||
(*(((struct headname *)((head)->tqh_last))->tqh_last))
|
||||
|
||||
#define TAILQ_FOREACH(var, head, field) \
|
||||
for ((var) = TAILQ_FIRST((head)); \
|
||||
(var); \
|
||||
(var) = TAILQ_NEXT((var), field))
|
||||
|
||||
#define TAILQ_CONCAT(head1, head2, field) \
|
||||
do { \
|
||||
if (!TAILQ_EMPTY(head2)) { \
|
||||
*(head1)->tqh_last = (head2)->tqh_first; \
|
||||
(head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \
|
||||
(head1)->tqh_last = (head2)->tqh_last; \
|
||||
TAILQ_INIT((head2)); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef TAILQ_FOREACH_SAFE // tlinux no this define
|
||||
#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \
|
||||
for ((var) = TAILQ_FIRST((head)); \
|
||||
(var) && ((tvar) = TAILQ_NEXT((var), field), 1); \
|
||||
(var) = (tvar))
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
/* Epoll proxy 定义与实现部分 */
|
||||
/******************************************************************************/
|
||||
|
||||
class EpollProxy;
|
||||
class MicroThread;
|
||||
|
||||
/**
|
||||
* @brief epoll通知对象基类定义
|
||||
*/
|
||||
class EpollerObj
|
||||
{
|
||||
protected:
|
||||
int _fd; ///< 系统FD 或 socket
|
||||
int _events; ///< 监听的事件类型
|
||||
int _revents; ///< 收到的事件类型
|
||||
int _type; ///< 工厂类别定义
|
||||
MicroThread* _thread; ///< 关联线程指针对象
|
||||
|
||||
public:
|
||||
|
||||
TAILQ_ENTRY(EpollerObj) _entry; ///< 关联微线程的管理入口
|
||||
|
||||
/**
|
||||
* @brief 构造与析构函数
|
||||
*/
|
||||
explicit EpollerObj(int fd = -1) {
|
||||
_fd = fd;
|
||||
_events = 0;
|
||||
_revents = 0;
|
||||
_type = 0;
|
||||
_thread = NULL;
|
||||
};
|
||||
virtual ~EpollerObj(){};
|
||||
|
||||
/**
|
||||
* @brief 可读事件通知接口, 考虑通知处理可能会破坏环境, 可用返回值区分
|
||||
* @return 0 该fd可继续处理其它事件; !=0 该fd需跳出回调处理
|
||||
*/
|
||||
virtual int InputNotify();
|
||||
|
||||
/**
|
||||
* @brief 可写事件通知接口, 考虑通知处理可能会破坏环境, 可用返回值区分
|
||||
* @return 0 该fd可继续处理其它事件; !=0 该fd需跳出回调处理
|
||||
*/
|
||||
virtual int OutputNotify();
|
||||
|
||||
/**
|
||||
* @brief 异常通知接口
|
||||
* @return 忽略返回值, 跳过其它事件处理
|
||||
*/
|
||||
virtual int HangupNotify();
|
||||
|
||||
/**
|
||||
* @brief 调整epoll侦听事件的回调接口, 长连接始终EPOLLIN, 偶尔EPOLLOUT
|
||||
* @param args fd引用对象的指针
|
||||
* @return 0 成功, < 0 失败, 要求事务回滚到操作前状态
|
||||
*/
|
||||
virtual int EpollCtlAdd(void* args);
|
||||
|
||||
/**
|
||||
* @brief 调整epoll侦听事件的回调接口, 长连接始终EPOLLIN, 偶尔EPOLLOUT
|
||||
* @param args fd引用对象的指针
|
||||
* @return 0 成功, < 0 失败, 要求事务回滚到操作前状态
|
||||
*/
|
||||
virtual int EpollCtlDel(void* args);
|
||||
|
||||
/**
|
||||
* @brief fd打开可读事件侦听
|
||||
*/
|
||||
void EnableInput() { _events |= EPOLLIN; };
|
||||
|
||||
/**
|
||||
* @brief fd打开可写事件侦听
|
||||
*/
|
||||
void EnableOutput() { _events |= EPOLLOUT; };
|
||||
|
||||
/**
|
||||
* @brief fd关闭可读事件侦听
|
||||
*/
|
||||
void DisableInput() { _events &= ~EPOLLIN; };
|
||||
|
||||
/**
|
||||
* @brief fd关闭可写事件侦听
|
||||
*/
|
||||
void DisableOutput() { _events &= ~EPOLLOUT; };
|
||||
|
||||
/**
|
||||
* @brief 系统socket设置读取封装
|
||||
*/
|
||||
int GetOsfd() { return _fd; };
|
||||
void SetOsfd(int fd) { _fd = fd; };
|
||||
|
||||
/**
|
||||
* @brief 监听事件与收到事件的访问方法
|
||||
*/
|
||||
int GetEvents() { return _events; };
|
||||
void SetRcvEvents(int revents) { _revents = revents; };
|
||||
int GetRcvEvents() { return _revents; };
|
||||
|
||||
/**
|
||||
* @brief 工厂管理方法, 获取真实类型
|
||||
*/
|
||||
int GetNtfyType() { return _type; };
|
||||
virtual void Reset() {
|
||||
_fd = -1;
|
||||
_events = 0;
|
||||
_revents = 0;
|
||||
_type = 0;
|
||||
_thread = NULL;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 设置与获取所属的微线程句柄接口
|
||||
* @param thread 关联的线程指针
|
||||
*/
|
||||
void SetOwnerThread(MicroThread* thread) { _thread = thread; };
|
||||
MicroThread* GetOwnerThread() { return _thread; };
|
||||
|
||||
};
|
||||
|
||||
typedef TAILQ_HEAD(__EpFdList, EpollerObj) EpObjList; ///< 高效的双链管理
|
||||
typedef struct epoll_event EpEvent; ///< 重定义一下epoll event
|
||||
|
||||
|
||||
/**
|
||||
* @brief EPOLL支持同一FD多个线程侦听, 建立一个引用计数数组, 元素定义
|
||||
* @info 引用计数弊大于利, 没有实际意义, 字段保留, 功能移除掉 20150623
|
||||
*/
|
||||
class FdRef
|
||||
{
|
||||
private:
|
||||
int _wr_ref; ///< 监听写的引用计数
|
||||
int _rd_ref; ///< 监听读的引用计数
|
||||
int _events; ///< 当前正在侦听的事件列表
|
||||
int _revents; ///< 当前该fd收到的事件信息, 仅在epoll_wait后处理中有效
|
||||
EpollerObj* _epobj; ///< 单独注册调度器对象,一个fd关联一个对象
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief 构造与析构函数
|
||||
*/
|
||||
FdRef() {
|
||||
_wr_ref = 0;
|
||||
_rd_ref = 0;
|
||||
_events = 0;
|
||||
_revents = 0;
|
||||
_epobj = NULL;
|
||||
};
|
||||
~FdRef(){};
|
||||
|
||||
/**
|
||||
* @brief 监听事件获取与设置接口
|
||||
*/
|
||||
void SetListenEvents(int events) {
|
||||
_events = events;
|
||||
};
|
||||
int GetListenEvents() {
|
||||
return _events;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 监听对象获取与设置接口
|
||||
*/
|
||||
void SetNotifyObj(EpollerObj* ntfy) {
|
||||
_epobj = ntfy;
|
||||
};
|
||||
EpollerObj* GetNotifyObj() {
|
||||
return _epobj;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 监听引用计数的更新
|
||||
*/
|
||||
void AttachEvents(int event) {
|
||||
if (event & EPOLLIN) {
|
||||
_rd_ref++;
|
||||
}
|
||||
if (event & EPOLLOUT){
|
||||
_wr_ref++;
|
||||
}
|
||||
};
|
||||
void DetachEvents(int event) {
|
||||
if (event & EPOLLIN) {
|
||||
if (_rd_ref > 0) {
|
||||
_rd_ref--;
|
||||
} else {
|
||||
_rd_ref = 0;
|
||||
}
|
||||
}
|
||||
if (event & EPOLLOUT){
|
||||
if (_wr_ref > 0) {
|
||||
_wr_ref--;
|
||||
} else {
|
||||
_wr_ref = 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 获取引用计数
|
||||
*/
|
||||
int ReadRefCnt() { return _rd_ref; };
|
||||
int WriteRefCnt() { return _wr_ref; };
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief EPOLL代理, 封装epoll操作与epoll全局数据
|
||||
*/
|
||||
class EpollProxy
|
||||
{
|
||||
public:
|
||||
static const int DEFAULT_MAX_FD_NUM = 100000; ///< 默认最大监控的fd
|
||||
|
||||
private:
|
||||
int _epfd; ///< epoll 主句柄
|
||||
int _maxfd; ///< 最大的文件句柄数
|
||||
EpEvent* _evtlist; ///< epoll返回给用户的事件列表指针
|
||||
FdRef* _eprefs; ///< 用户监听的事件本地管理数组
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief 构造与析构函数
|
||||
*/
|
||||
EpollProxy();
|
||||
virtual ~EpollProxy(){};
|
||||
|
||||
/**
|
||||
* @brief epoll初始化与终止处理, 申请动态内存等
|
||||
* @param max_num 最大可管理的fd数目
|
||||
*/
|
||||
int InitEpoll(int max_num);
|
||||
void TermEpoll(void);
|
||||
|
||||
/**
|
||||
* @brief epoll_wait 获取最大等待时间接口
|
||||
* @return 目前需要等待的时间, 单位MS
|
||||
*/
|
||||
virtual int EpollGetTimeout(void) { return 0;};
|
||||
|
||||
/**
|
||||
* @brief epoll 触发调度接口
|
||||
* @param fdlist 多路并发请求, 所有发送的socket集合
|
||||
* @param fd 单个socket, 触发等待
|
||||
* @param timeout 超时时间设置, 毫秒
|
||||
* @return true 成功, false 失败
|
||||
*/
|
||||
virtual bool EpollSchedule(EpObjList* fdlist, EpollerObj* fd, int timeout) { return false;};
|
||||
|
||||
/**
|
||||
* @brief 将一个微线程侦听的所有socket送入epoll管理
|
||||
* @param fdset 微线程侦听的socket集合
|
||||
* @return true 成功, false 失败
|
||||
*/
|
||||
bool EpollAdd(EpObjList& fdset);
|
||||
|
||||
/**
|
||||
* @brief 将一个微线程侦听的所有socket移除epoll管理
|
||||
* @param fdset 微线程侦听的socket集合
|
||||
* @return true 成功, false 失败
|
||||
*/
|
||||
bool EpollDel(EpObjList& fdset);
|
||||
|
||||
/**
|
||||
* @brief epoll_wait 以及分发处理过程
|
||||
*/
|
||||
void EpollDispath(void);
|
||||
|
||||
/**
|
||||
* @brief 单独一个fd注册, 关联侦听事件
|
||||
* @param fd 文件句柄与事件信息
|
||||
* @param obj epoll回调对象
|
||||
*/
|
||||
bool EpollAddObj(EpollerObj* obj);
|
||||
|
||||
/**
|
||||
* @brief 取消一个fd注册, 关联侦听事件
|
||||
* @param fd 文件句柄与事件信息
|
||||
* @param obj epoll回调对象
|
||||
*/
|
||||
bool EpollDelObj(EpollerObj* obj);
|
||||
|
||||
/**
|
||||
* @brief 封装epoll ctl的处理与当前监听事件的记录, 内部接口
|
||||
* @param fd 操作的文件句柄
|
||||
* @param new_events 需要新增的监听事件
|
||||
*/
|
||||
bool EpollCtrlAdd(int fd, int new_events);
|
||||
|
||||
/**
|
||||
* @brief 封装epoll ctl的处理与当前监听事件的记录, 内部接口
|
||||
* @param fd 操作的文件句柄
|
||||
* @param new_events 需要新删除的监听事件
|
||||
*/
|
||||
bool EpollCtrlDel(int fd, int new_events);
|
||||
bool EpollCtrlDelRef(int fd, int new_events, bool use_ref);
|
||||
|
||||
/**
|
||||
* @brief 根据fd获取本地引用的结构, 按fd生成策略, 目前简单管理
|
||||
* @param fd 文件描述符
|
||||
* @return 本地文件引用结构, NULL 表示失败
|
||||
*/
|
||||
FdRef* FdRefGet(int fd) {
|
||||
return ((fd >= _maxfd) || (fd < 0)) ? (FdRef*)NULL : &_eprefs[fd];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief 单独的注册接口, 用于注册或取消注册通知对象
|
||||
* @param fd 操作的文件句柄
|
||||
* @param obj 待注册或取消注册的对象
|
||||
*/
|
||||
void EpollNtfyReg(int fd, EpollerObj* obj) {
|
||||
FdRef* ref = FdRefGet(fd);
|
||||
if (ref) {
|
||||
ref->SetNotifyObj(obj);
|
||||
}
|
||||
};
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* @brief 更新每个socket的最新接收事件信息
|
||||
* @param evtfdnum 收到事件的fd集合数目
|
||||
*/
|
||||
void EpollRcvEventList(int evtfdnum);
|
||||
|
||||
};
|
||||
}//NAMESPCE
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -19,8 +19,6 @@
|
|||
|
||||
/**
|
||||
* @filename hash_list.h
|
||||
* @info 开链hash类, 简单hash存储实现; 继承来实现hash映射, 注意插入元素的
|
||||
* 生命周期, 如栈变量等会自动析构的元素, 不要存放于此, 否则会坏链
|
||||
* @time 2013-06-11
|
||||
*/
|
||||
|
||||
|
@ -35,94 +33,59 @@
|
|||
|
||||
namespace NS_MICRO_THREAD {
|
||||
|
||||
/**
|
||||
* @brief Hash存放元素的基类, 继承该元素即可实现扩展
|
||||
*/
|
||||
class HashKey
|
||||
{
|
||||
private:
|
||||
HashKey* _next_entry; ///< 开链hash的链接元素
|
||||
uint32_t _hash_value; ///< hash value信息, 节约比较的时间
|
||||
void* _data_ptr; ///< hash data数据指针, 可key - value 聚合存储
|
||||
HashKey* _next_entry;
|
||||
uint32_t _hash_value;
|
||||
void* _data_ptr;
|
||||
|
||||
public:
|
||||
|
||||
friend class HashList; ///< hash表可以直接访问next指针
|
||||
friend class HashList;
|
||||
|
||||
/**
|
||||
* @brief 构造与虚析构函数
|
||||
*/
|
||||
HashKey():_next_entry(NULL), _hash_value(0), _data_ptr(NULL) {};
|
||||
virtual ~HashKey(){};
|
||||
|
||||
/**
|
||||
* @brief 节点元素的hash算法, 获取key的hash值
|
||||
* @return 节点元素的hash值
|
||||
*/
|
||||
virtual uint32_t HashValue() = 0;
|
||||
|
||||
/**
|
||||
* @brief 节点元素的cmp方法, 同一桶ID下, 按key比较
|
||||
* @return 节点元素的hash值
|
||||
*/
|
||||
virtual int HashCmp(HashKey* rhs) = 0;
|
||||
|
||||
/**
|
||||
* @brief 堆遍历接口, 用于调试, 在遍历每个元素时被调用, 可选实现
|
||||
*/
|
||||
|
||||
virtual void HashIterate() {
|
||||
return;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 节点元素的实际数据指针设置与获取
|
||||
*/
|
||||
void* GetDataPtr() {
|
||||
return _data_ptr;
|
||||
};
|
||||
void SetDataPtr(void* data) {
|
||||
_data_ptr = data;
|
||||
};
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief Hash管理类, 开链式hash, 注意选择合适的hash函数, 避免冲突过长
|
||||
*/
|
||||
class HashList
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief 构造函数与析构函数
|
||||
*/
|
||||
explicit HashList(int max = 100000) {
|
||||
explicit HashList(int max = 100000) {
|
||||
_max = GetMaxPrimeNum((max > 2) ? max : 100000);
|
||||
_buckets = (HashKey**)calloc(_max, sizeof(HashKey*));
|
||||
_count = 0;
|
||||
};
|
||||
virtual ~HashList() {
|
||||
if (_buckets) {
|
||||
free(_buckets);
|
||||
_buckets = NULL;
|
||||
}
|
||||
_buckets = (HashKey**)calloc(_max, sizeof(HashKey*));
|
||||
_count = 0;
|
||||
};
|
||||
};
|
||||
virtual ~HashList() {
|
||||
if (_buckets) {
|
||||
free(_buckets);
|
||||
_buckets = NULL;
|
||||
}
|
||||
_count = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 获取hash的元素个数
|
||||
* @return 堆元素实际数目
|
||||
*/
|
||||
int HashSize() {
|
||||
return _count;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief hash插入元素, 要在该元素析构前, 调用remove
|
||||
* @param key 待插入的元素指针, 注意元素的生命周期, 不要插入栈变量
|
||||
* @return 0 成功, -1 参数无效或未初始化, -2 重复插入或脏数据
|
||||
* @brief hash insert key.
|
||||
*/
|
||||
int HashInsert(HashKey* key) {
|
||||
if (!key || !_buckets) {
|
||||
|
@ -144,9 +107,7 @@ public:
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief hash查找元素
|
||||
* @param key 待查询的key指针
|
||||
* @return 查询结果对象指针, NULL表明无数据
|
||||
* @brief hash lookup key.
|
||||
*/
|
||||
HashKey* HashFind(HashKey* key) {
|
||||
if (!key || !_buckets) {
|
||||
|
@ -171,9 +132,7 @@ public:
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief hash查找元素
|
||||
* @param key 待查询的key指针
|
||||
* @return 查询结果对象指针, NULL表明无数据
|
||||
* @brief hash lookup key.
|
||||
*/
|
||||
void* HashFindData(HashKey* key) {
|
||||
HashKey* item = HashFind(key);
|
||||
|
@ -186,8 +145,7 @@ public:
|
|||
|
||||
|
||||
/**
|
||||
* @brief hash删除元素
|
||||
* @param key 待删除的key指针
|
||||
* @brief hash remove key.
|
||||
*/
|
||||
void HashRemove(HashKey* key) {
|
||||
if (!key || !_buckets) {
|
||||
|
@ -215,7 +173,7 @@ public:
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief hash遍历元素, 调用迭代函数
|
||||
* @brief hash loop.
|
||||
*/
|
||||
void HashForeach() {
|
||||
if (!_buckets) {
|
||||
|
@ -231,7 +189,7 @@ public:
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief hash清理遍历, 性能低下, 只用于最终遍历清理
|
||||
* @brief traverse hash list, low performance, only for remove.
|
||||
*/
|
||||
HashKey* HashGetFirst() {
|
||||
if (!_buckets) {
|
||||
|
@ -249,38 +207,35 @@ public:
|
|||
|
||||
private:
|
||||
|
||||
/**
|
||||
* @brief 获取桶长度的最大质数
|
||||
*/
|
||||
int GetMaxPrimeNum(int num)
|
||||
{
|
||||
int sqrt_value = (int)sqrt(num);
|
||||
for (int i = num; i > 0; i--)
|
||||
{
|
||||
int flag = 1;
|
||||
for (int k = 2; k <= sqrt_value; k++)
|
||||
{
|
||||
if (i % k == 0)
|
||||
{
|
||||
flag = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
int sqrt_value = (int)sqrt(num);
|
||||
for (int i = num; i > 0; i--)
|
||||
{
|
||||
int flag = 1;
|
||||
for (int k = 2; k <= sqrt_value; k++)
|
||||
{
|
||||
if (i % k == 0)
|
||||
{
|
||||
flag = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (flag == 1)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
if (flag == 1)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
};
|
||||
|
||||
|
||||
private:
|
||||
HashKey** _buckets; ///< 桶指针
|
||||
int _count; ///< 有效元素个数
|
||||
int _max; ///< 最大节点个数
|
||||
HashKey** _buckets;
|
||||
int _count;
|
||||
int _max;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
/**
|
||||
* @filename heap.h
|
||||
* @info 灵活插入删除的堆, 如果是没有随机删除需求, 可以用std::make_heap
|
||||
* @info flexible insert and delete heap, if no random deletion, use std::make_heap
|
||||
* @time 2013-06-11
|
||||
*/
|
||||
|
||||
|
@ -36,62 +36,36 @@
|
|||
|
||||
namespace NS_MICRO_THREAD {
|
||||
|
||||
class HeapEntry; // 堆元素类, 继承实现扩展
|
||||
class HeapList; // 堆管理类, 通用
|
||||
class HeapEntry;
|
||||
class HeapList;
|
||||
|
||||
/**
|
||||
* @brief 最小堆的堆元素定义, 用于构建通用的堆, 继承该元素即可扩展
|
||||
* @brief definition of heap elements for minimum heap
|
||||
*/
|
||||
class HeapEntry
|
||||
{
|
||||
private:
|
||||
int _index; ///< 堆元素下标, 利于快速索引删除操作
|
||||
int _index;
|
||||
|
||||
public:
|
||||
friend class HeapList;
|
||||
friend class HeapList;
|
||||
|
||||
/**
|
||||
* @brief 构造与虚析构函数
|
||||
*/
|
||||
HeapEntry():_index(0){};
|
||||
virtual ~HeapEntry(){};
|
||||
HeapEntry():_index(0){};
|
||||
virtual ~HeapEntry(){};
|
||||
|
||||
/**
|
||||
* @brief 堆元素取值函数, 用于返回值比较, 需子函数实现, 否则默认无序
|
||||
* @return 堆元素映射的值
|
||||
*/
|
||||
virtual unsigned long long HeapValue() = 0;
|
||||
|
||||
|
||||
/**
|
||||
* @brief 堆遍历接口, 用于调试, 在遍历每个元素时被调用, 可选实现
|
||||
*/
|
||||
virtual void HeapIterate() {
|
||||
return;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 堆元素插入堆中
|
||||
* @param list 堆指针
|
||||
* @return 0 成功; 其它失败 -1 堆满; -2 重复插入
|
||||
*/
|
||||
inline int InsertIntoHeap(HeapList* list);
|
||||
|
||||
/**
|
||||
* @brief 堆元素从堆中删除
|
||||
* @param list 堆指针
|
||||
* @return 0 成功; 其它失败 -1 堆空; -2 重复删除或脏数据
|
||||
*/
|
||||
inline int DeleteFromHeap(HeapList* list);
|
||||
|
||||
|
||||
/**
|
||||
* @brief 堆元素下标信息获取, 内部管理使用
|
||||
* @return 堆元素在堆中下标信息
|
||||
*/
|
||||
inline int GetIndex() {
|
||||
return _index;
|
||||
};
|
||||
inline int GetIndex() {
|
||||
return _index;
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
|
@ -105,50 +79,42 @@ private:
|
|||
}
|
||||
};
|
||||
|
||||
inline void SetIndex(int index) {
|
||||
_index = index;
|
||||
};
|
||||
inline void SetIndex(int index) {
|
||||
_index = index;
|
||||
};
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief 最小堆队列类, 通用类
|
||||
* @brief minimum heap queue.
|
||||
*/
|
||||
class HeapList
|
||||
{
|
||||
private:
|
||||
HeapEntry** _list; // 堆元素的指针数组, 目前定长
|
||||
int _max; // 堆可管理最大元素个数
|
||||
int _count; // 堆已经管理的元素个数
|
||||
HeapEntry** _list;
|
||||
int _max;
|
||||
int _count;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief 构造函数与析构函数
|
||||
*/
|
||||
explicit HeapList(int max = 100000) {
|
||||
|
||||
explicit HeapList(int max = 100000) {
|
||||
_max = (max > 0) ? max : 100000;
|
||||
_list = (HeapEntry**)malloc (sizeof(HeapEntry*) * (_max+1));
|
||||
heap_assert(_list);
|
||||
memset(_list, 0, sizeof(HeapEntry*) * (_max+1));
|
||||
_count = 0;
|
||||
};
|
||||
virtual ~HeapList() {
|
||||
if (_list) {
|
||||
free(_list);
|
||||
_list = NULL;
|
||||
}
|
||||
_list = (HeapEntry**)malloc (sizeof(HeapEntry*) * (_max+1));
|
||||
heap_assert(_list);
|
||||
memset(_list, 0, sizeof(HeapEntry*) * (_max+1));
|
||||
_count = 0;
|
||||
};
|
||||
virtual ~HeapList() {
|
||||
if (_list) {
|
||||
free(_list);
|
||||
_list = NULL;
|
||||
}
|
||||
_max = 0;
|
||||
_count = 0;
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 扩展heap的大小, 缩小则忽略
|
||||
* @param size 新的堆元素个数
|
||||
* @return 0 成功; -1 失败
|
||||
*/
|
||||
int HeapResize(int size) {
|
||||
if (_max >= size) {
|
||||
return 0;
|
||||
|
@ -166,270 +132,199 @@ public:
|
|||
|
||||
return 0;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief 插入堆元素
|
||||
* @param entry 堆元素指针
|
||||
* @return 0 成功; 其它失败 -1 堆满; -2 重复插入
|
||||
*/
|
||||
int HeapPush(HeapEntry* entry);
|
||||
int HeapPush(HeapEntry* entry);
|
||||
|
||||
/**
|
||||
* @brief 取堆顶元素, 并移除该元素
|
||||
* @return 堆顶元素指针, NULL 表示堆为空
|
||||
*/
|
||||
HeapEntry* HeapPop();
|
||||
HeapEntry* HeapPop();
|
||||
|
||||
/**
|
||||
* @brief 移除任意堆元素
|
||||
* @param entry 堆元素指针
|
||||
* @return 0 成功; 其它失败 -1 堆空; -2 重复删除或脏数据
|
||||
*/
|
||||
int HeapDelete(HeapEntry* entry);
|
||||
int HeapDelete(HeapEntry* entry);
|
||||
|
||||
/**
|
||||
* @brief 调试接口, 按2叉堆方式打印元素, 同时调用每元素的迭代接口
|
||||
*/
|
||||
void HeapForeach();
|
||||
void HeapForeach();
|
||||
|
||||
/**
|
||||
* @brief 获取堆的元素个数
|
||||
* @return 堆元素实际数目
|
||||
*/
|
||||
int HeapSize() {
|
||||
return _count;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 取堆顶元素, 不移除该元素
|
||||
* @return 堆顶元素指针, NULL 表示堆为空
|
||||
*/
|
||||
HeapEntry* HeapTop() {
|
||||
return (_count > 0) ? _list[1] : NULL;
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* @brief 判定堆是否满
|
||||
* @return true 满
|
||||
*/
|
||||
bool HeapFull() {
|
||||
return (_count >= _max);
|
||||
};
|
||||
bool HeapFull() {
|
||||
return (_count >= _max);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 判定堆是否空
|
||||
* @return true 空
|
||||
*/
|
||||
bool HeapEmpty() {
|
||||
return (_count == 0);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 按比较函数, 向上重排堆元素
|
||||
*/
|
||||
void HeapUp();
|
||||
bool HeapEmpty() {
|
||||
return (_count == 0);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 按比较函数, 向下重排堆元素
|
||||
*/
|
||||
void HeapDown(int index);
|
||||
void HeapUp();
|
||||
|
||||
void HeapDown(int index);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 按比较函数, 向上重排堆元素
|
||||
*/
|
||||
|
||||
inline void HeapList::HeapUp()
|
||||
{
|
||||
for (int pos = _count; pos > 0; pos = pos/2)
|
||||
{
|
||||
if (pos/2 < 1) // pos == 1 已经到顶, 0 属于保留
|
||||
{
|
||||
break;
|
||||
}
|
||||
for (int pos = _count; pos > 0; pos = pos/2)
|
||||
{
|
||||
if (pos/2 < 1) // pos == 1 peaked, 0 reserved.
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (_list[pos]->HeapValueCmp(_list[pos/2]) < 0)
|
||||
{
|
||||
HeapEntry* tmp = _list[pos/2];
|
||||
_list[pos/2] = _list[pos];
|
||||
_list[pos] = tmp;
|
||||
{
|
||||
HeapEntry* tmp = _list[pos/2];
|
||||
_list[pos/2] = _list[pos];
|
||||
_list[pos] = tmp;
|
||||
|
||||
_list[pos]->SetIndex(pos);
|
||||
_list[pos/2]->SetIndex(pos/2);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
_list[pos]->SetIndex(pos);
|
||||
_list[pos/2]->SetIndex(pos/2);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 按比较函数, 向下重排堆元素
|
||||
* @param index 从该位置开始重排
|
||||
*/
|
||||
inline void HeapList::HeapDown(int index)
|
||||
{
|
||||
int min_son;
|
||||
for (int pos = index; pos <= _count; pos = min_son)
|
||||
{
|
||||
if (pos*2 > _count) // pos是叶子节点了
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if (pos*2 == _count)
|
||||
{
|
||||
min_son = pos*2;
|
||||
}
|
||||
else
|
||||
{
|
||||
int min_son;
|
||||
for (int pos = index; pos <= _count; pos = min_son)
|
||||
{
|
||||
if (pos*2 > _count) // pos is a leaf node.
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if (pos*2 == _count)
|
||||
{
|
||||
min_son = pos*2;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_list[pos*2+1]->HeapValueCmp(_list[pos*2]) < 0)
|
||||
{
|
||||
min_son = pos*2+1;
|
||||
}
|
||||
else
|
||||
{
|
||||
min_son = pos*2;
|
||||
}
|
||||
}
|
||||
{
|
||||
min_son = pos*2+1;
|
||||
}
|
||||
else
|
||||
{
|
||||
min_son = pos*2;
|
||||
}
|
||||
}
|
||||
|
||||
if (_list[pos]->HeapValueCmp(_list[min_son]) > 0)
|
||||
{
|
||||
HeapEntry* tmp = _list[min_son];
|
||||
_list[min_son] = _list[pos];
|
||||
_list[pos] = tmp;
|
||||
if (_list[pos]->HeapValueCmp(_list[min_son]) > 0)
|
||||
{
|
||||
HeapEntry* tmp = _list[min_son];
|
||||
_list[min_son] = _list[pos];
|
||||
_list[pos] = tmp;
|
||||
|
||||
_list[pos]->SetIndex(pos);
|
||||
_list[min_son]->SetIndex(min_son);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
_list[pos]->SetIndex(pos);
|
||||
_list[min_son]->SetIndex(min_son);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 插入堆元素
|
||||
* @param entry 堆元素指针
|
||||
* @return 0 成功; 其它失败 -1 堆满; -2 重复插入
|
||||
*/
|
||||
inline int HeapList::HeapPush(HeapEntry* item)
|
||||
{
|
||||
if (HeapFull()) {
|
||||
heap_assert(0); // 满, 理论上是可能的, 实际运行不太可能过10W
|
||||
return -1;
|
||||
}
|
||||
if (HeapFull()) {
|
||||
heap_assert(0); // it's possible in theory but not in fact.
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (item->GetIndex() != 0) {
|
||||
heap_assert(0); // 重复插入
|
||||
heap_assert(0); // duplicated insertion.
|
||||
return -2;
|
||||
}
|
||||
|
||||
_count++;
|
||||
_list[_count] = item;
|
||||
_count++;
|
||||
_list[_count] = item;
|
||||
item->SetIndex(_count);
|
||||
|
||||
HeapUp();
|
||||
HeapUp();
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 取堆顶元素, 并移除该元素
|
||||
* @return 堆顶元素指针, NULL 表示堆为空
|
||||
*/
|
||||
inline HeapEntry* HeapList::HeapPop()
|
||||
{
|
||||
if (HeapEmpty()) {
|
||||
return NULL;
|
||||
}
|
||||
if (HeapEmpty()) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
HeapEntry* top = _list[1]; // 0 保留
|
||||
HeapEntry* top = _list[1]; // 0 reserved.
|
||||
|
||||
_list[1] = _list[_count];
|
||||
_list[1] = _list[_count];
|
||||
_list[1]->SetIndex(1);
|
||||
_list[_count] = 0;
|
||||
|
||||
_count--;
|
||||
HeapDown(1);
|
||||
|
||||
_count--;
|
||||
HeapDown(1);
|
||||
|
||||
heap_assert(top->GetIndex() == 1);
|
||||
top->SetIndex(0);
|
||||
return top;
|
||||
top->SetIndex(0);
|
||||
return top;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 移除任意堆元素
|
||||
* @param entry 堆元素指针
|
||||
* @return 0 成功; 其它失败 -1 堆空; -2 重复删除或脏数据
|
||||
*/
|
||||
inline int HeapList::HeapDelete(HeapEntry* item)
|
||||
{
|
||||
if (HeapEmpty()) {
|
||||
return -1;
|
||||
}
|
||||
if (HeapEmpty()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int pos = item->GetIndex() ;
|
||||
if ((pos > _count) ||(pos <= 0))
|
||||
{
|
||||
heap_assert(0); // 非法数据或重复删除
|
||||
return -2;
|
||||
}
|
||||
int pos = item->GetIndex() ;
|
||||
if ((pos > _count) ||(pos <= 0))
|
||||
{
|
||||
heap_assert(0); // duplicated deletion or illegal data.
|
||||
return -2;
|
||||
}
|
||||
|
||||
HeapEntry* del = _list[pos];
|
||||
_list[pos] = _list[_count];
|
||||
HeapEntry* del = _list[pos];
|
||||
_list[pos] = _list[_count];
|
||||
_list[pos]->SetIndex(pos);
|
||||
|
||||
_list[_count] = 0;
|
||||
_count--;
|
||||
_count--;
|
||||
|
||||
HeapDown(pos);
|
||||
HeapDown(pos);
|
||||
heap_assert(pos == del->GetIndex());
|
||||
del->SetIndex(0);
|
||||
return 0;
|
||||
del->SetIndex(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 调试接口, 按2叉堆方式打印元素, 同时调用每元素的迭代接口
|
||||
*/
|
||||
inline void HeapList::HeapForeach()
|
||||
{
|
||||
int per = 1;
|
||||
for (int i = 1; i <= _count; i++)
|
||||
{
|
||||
if (i >= per*2)
|
||||
{
|
||||
printf("\n");
|
||||
per *=2;
|
||||
}
|
||||
printf("%llu ", _list[i]->HeapValue());
|
||||
for (int i = 1; i <= _count; i++)
|
||||
{
|
||||
if (i >= per*2)
|
||||
{
|
||||
printf("\n");
|
||||
per *=2;
|
||||
}
|
||||
printf("%llu ", _list[i]->HeapValue());
|
||||
|
||||
_list[i]->HeapIterate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 堆元素插入堆中
|
||||
* @param list 堆指针
|
||||
* @return 0 成功; 其它失败 -1 堆满; -2 重复插入
|
||||
*/
|
||||
inline int HeapEntry::InsertIntoHeap(HeapList* list) {
|
||||
return list->HeapPush(this);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 堆元素从堆中删除
|
||||
* @param list 堆指针
|
||||
* @return 0 成功; 其它失败 -1 堆空; -2 重复删除或脏数据
|
||||
*/
|
||||
inline int HeapEntry::DeleteFromHeap(HeapList* list) {
|
||||
return list->HeapDelete(this);
|
||||
};
|
||||
|
|
|
@ -26,10 +26,6 @@
|
|||
|
||||
using namespace NS_MICRO_THREAD;
|
||||
|
||||
|
||||
/**
|
||||
* @brief 构造函数
|
||||
*/
|
||||
CTimerMng::CTimerMng(uint32_t max_item)
|
||||
{
|
||||
#define TIMER_MIN 100000
|
||||
|
@ -42,10 +38,6 @@ CTimerMng::CTimerMng(uint32_t max_item)
|
|||
_heap = new HeapList(max_item);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 析构函数
|
||||
*/
|
||||
CTimerMng::~CTimerMng()
|
||||
{
|
||||
if (_heap) {
|
||||
|
@ -54,13 +46,6 @@ CTimerMng::~CTimerMng()
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 定时器设置函数
|
||||
* @param timerable 定时器对象
|
||||
* @param interval 超时的间隔 ms单位
|
||||
* @return 成功返回true, 否则失败
|
||||
*/
|
||||
bool CTimerMng::start_timer(CTimerNotify* timerable, uint32_t interval)
|
||||
{
|
||||
if (!_heap || !timerable) {
|
||||
|
@ -78,10 +63,6 @@ bool CTimerMng::start_timer(CTimerNotify* timerable, uint32_t interval)
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 定时器停止接口函数
|
||||
* @param timerable 定时器对象
|
||||
*/
|
||||
void CTimerMng::stop_timer(CTimerNotify* timerable)
|
||||
{
|
||||
if (!_heap || !timerable) {
|
||||
|
@ -92,9 +73,6 @@ void CTimerMng::stop_timer(CTimerNotify* timerable)
|
|||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 定时器超时检测函数
|
||||
*/
|
||||
void CTimerMng::check_expired()
|
||||
{
|
||||
if (!_heap) {
|
||||
|
@ -110,6 +88,3 @@ void CTimerMng::check_expired()
|
|||
timer = dynamic_cast<CTimerNotify*>(_heap->HeapTop());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -30,99 +30,52 @@
|
|||
namespace NS_MICRO_THREAD
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief 定时器对象基类
|
||||
*/
|
||||
class CTimerNotify : public HeapEntry
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief 超时通知函数, 子类实现逻辑
|
||||
*/
|
||||
virtual void timer_notify() { return;};
|
||||
|
||||
/**
|
||||
* @brief 堆元素取值函数, 用于返回值比较, 需子函数实现, 否则默认无序
|
||||
* @return 堆元素映射的值
|
||||
*/
|
||||
|
||||
virtual unsigned long long HeapValue() {
|
||||
return (unsigned long long)_time_expired;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 构造函数
|
||||
*/
|
||||
CTimerNotify() : _time_expired(0) {};
|
||||
|
||||
/**
|
||||
* @brief 虚析构函数
|
||||
*/
|
||||
virtual ~CTimerNotify(){};
|
||||
|
||||
/**
|
||||
* @brief 设置绝对超时时间, 单位ms
|
||||
* @param expired 绝对超时时间 ms单位
|
||||
*/
|
||||
void set_expired_time(uint64_t expired) {
|
||||
_time_expired = expired;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 获取绝对超时时间, 单位ms
|
||||
* @return 绝对超时时间 ms单位
|
||||
*/
|
||||
uint64_t get_expired_time() {
|
||||
return _time_expired;
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
uint64_t _time_expired; // 绝对的超时时间ms单位
|
||||
uint64_t _time_expired;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief 定时器管理单例类
|
||||
*/
|
||||
class CTimerMng
|
||||
{
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
* @brief 构造函数
|
||||
* @param max_item 最大可管理的定时器对象数目(指针数目)
|
||||
*/
|
||||
explicit CTimerMng(uint32_t max_item = 100000);
|
||||
|
||||
/**
|
||||
* @brief 析构函数
|
||||
*/
|
||||
~CTimerMng();
|
||||
|
||||
/**
|
||||
* @brief 定时器设置函数
|
||||
* @param timerable 定时器对象
|
||||
* @param interval 超时的间隔 ms单位
|
||||
* @return 成功返回true, 否则失败
|
||||
*/
|
||||
bool start_timer(CTimerNotify* timerable, uint32_t interval);
|
||||
|
||||
/**
|
||||
* @brief 定时器停止接口函数
|
||||
* @param timerable 定时器对象
|
||||
*/
|
||||
void stop_timer(CTimerNotify* timerable);
|
||||
|
||||
/**
|
||||
* @brief 定时器超时检测函数
|
||||
*/
|
||||
void check_expired();
|
||||
|
||||
private:
|
||||
|
||||
HeapList* _heap; // 最小堆指针
|
||||
HeapList* _heap;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -39,34 +39,34 @@ KqueueProxy::KqueueProxy()
|
|||
|
||||
int KqueueProxy::InitKqueue(int max_num)
|
||||
{
|
||||
int rc = 0;
|
||||
if (max_num > _maxfd)
|
||||
{
|
||||
_maxfd = max_num;
|
||||
}
|
||||
int rc = 0;
|
||||
if (max_num > _maxfd)
|
||||
{
|
||||
_maxfd = max_num;
|
||||
}
|
||||
|
||||
_kqfd = ff_kqueue();
|
||||
if (_kqfd < 0)
|
||||
{
|
||||
rc = -1;
|
||||
goto EXIT_LABEL;
|
||||
}
|
||||
_kqfd = ff_kqueue();
|
||||
if (_kqfd < 0)
|
||||
{
|
||||
rc = -1;
|
||||
goto EXIT_LABEL;
|
||||
}
|
||||
|
||||
ff_fcntl(_kqfd, F_SETFD, FD_CLOEXEC);
|
||||
ff_fcntl(_kqfd, F_SETFD, FD_CLOEXEC);
|
||||
|
||||
_kqrefs = new KqFdRef[_maxfd];
|
||||
if (_kqrefs == NULL)
|
||||
{
|
||||
rc = -2;
|
||||
goto EXIT_LABEL;
|
||||
}
|
||||
_kqrefs = new KqFdRef[_maxfd];
|
||||
if (_kqrefs == NULL)
|
||||
{
|
||||
rc = -2;
|
||||
goto EXIT_LABEL;
|
||||
}
|
||||
|
||||
_evtlist = (KqEvent*)calloc(_maxfd, sizeof(KqEvent));
|
||||
if (_evtlist == NULL)
|
||||
{
|
||||
rc = -3;
|
||||
goto EXIT_LABEL;
|
||||
}
|
||||
_evtlist = (KqEvent*)calloc(_maxfd, sizeof(KqEvent));
|
||||
if (_evtlist == NULL)
|
||||
{
|
||||
rc = -3;
|
||||
goto EXIT_LABEL;
|
||||
}
|
||||
|
||||
struct rlimit rlim;
|
||||
memset(&rlim, 0, sizeof(rlim));
|
||||
|
@ -115,20 +115,20 @@ void KqueueProxy::TermKqueue()
|
|||
|
||||
bool KqueueProxy::KqueueAdd(KqObjList& obj_list)
|
||||
{
|
||||
bool ret = true;
|
||||
KqueuerObj *kqobj = NULL;
|
||||
KqueuerObj *kqobj_error = NULL;
|
||||
TAILQ_FOREACH(kqobj, &obj_list, _entry)
|
||||
{
|
||||
if (!KqueueAddObj(kqobj))
|
||||
{
|
||||
bool ret = true;
|
||||
KqueuerObj *kqobj = NULL;
|
||||
KqueuerObj *kqobj_error = NULL;
|
||||
TAILQ_FOREACH(kqobj, &obj_list, _entry)
|
||||
{
|
||||
if (!KqueueAddObj(kqobj))
|
||||
{
|
||||
MTLOG_ERROR("kqobj add failed, fd: %d", kqobj->GetOsfd());
|
||||
kqueue_assert(0);
|
||||
kqobj_error = kqobj;
|
||||
ret = false;
|
||||
goto EXIT_LABEL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EXIT_LABEL:
|
||||
|
||||
|
@ -167,303 +167,303 @@ bool KqueueProxy::KqueueDel(KqObjList& obj_list)
|
|||
|
||||
bool KqueueProxy::KqueueCtrlAdd(int fd, int events)
|
||||
{
|
||||
KqFdRef* item = KqFdRefGet(fd);
|
||||
if (item == NULL)
|
||||
{
|
||||
KqFdRef* item = KqFdRefGet(fd);
|
||||
if (item == NULL)
|
||||
{
|
||||
MT_ATTR_API(320851, 1); // fd error, wtf?
|
||||
MTLOG_ERROR("kqfd ref not find, failed, fd: %d", fd);
|
||||
kqueue_assert(0);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
item->AttachEvents(events);
|
||||
item->AttachEvents(events);
|
||||
|
||||
int old_events = item->GetListenEvents();
|
||||
int new_events = old_events | events;
|
||||
if (old_events == new_events)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
KqEvent ke;
|
||||
int ret;
|
||||
if (old_events & KQ_EVENT_WRITE) {
|
||||
EV_SET(&ke, fd, EVFILT_WRITE, EV_DELETE, 0, 0, NULL);
|
||||
ret = ff_kevent(_kqfd, &ke, 1, NULL, 0, NULL);
|
||||
if (ret == -1) {
|
||||
// TODO, error check
|
||||
item->DetachEvents(events);
|
||||
kqueue_assert(0);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (old_events & KQ_EVENT_READ) {
|
||||
EV_SET(&ke, fd, EVFILT_READ, EV_DELETE, 0, 0, NULL);
|
||||
ret = ff_kevent(_kqfd, &ke, 1, NULL, 0, NULL);
|
||||
if (ret == -1) {
|
||||
// TODO, error check
|
||||
item->DetachEvents(events);
|
||||
kqueue_assert(0);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (events & KQ_EVENT_WRITE) {
|
||||
EV_SET(&ke, fd, EVFILT_WRITE, EV_ADD, 0, 0, NULL);
|
||||
ret = ff_kevent(_kqfd, &ke, 1, NULL, 0, NULL);
|
||||
if (ret == -1) {
|
||||
// TODO, error check
|
||||
item->DetachEvents(events);
|
||||
kqueue_assert(0);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (events & KQ_EVENT_READ) {
|
||||
EV_SET(&ke, fd, EVFILT_READ, EV_ADD, 0, 0, NULL);
|
||||
ret = ff_kevent(_kqfd, &ke, 1, NULL, 0, NULL);
|
||||
if (ret == -1) {
|
||||
// TODO, error check
|
||||
item->DetachEvents(events);
|
||||
kqueue_assert(0);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
int old_events = item->GetListenEvents();
|
||||
int new_events = old_events | events;
|
||||
if (old_events == new_events)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
KqEvent ke;
|
||||
int ret;
|
||||
if (old_events & KQ_EVENT_WRITE) {
|
||||
EV_SET(&ke, fd, EVFILT_WRITE, EV_DELETE, 0, 0, NULL);
|
||||
ret = ff_kevent(_kqfd, &ke, 1, NULL, 0, NULL);
|
||||
if (ret == -1) {
|
||||
// TODO, error check
|
||||
item->DetachEvents(events);
|
||||
kqueue_assert(0);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (old_events & KQ_EVENT_READ) {
|
||||
EV_SET(&ke, fd, EVFILT_READ, EV_DELETE, 0, 0, NULL);
|
||||
ret = ff_kevent(_kqfd, &ke, 1, NULL, 0, NULL);
|
||||
if (ret == -1) {
|
||||
// TODO, error check
|
||||
item->DetachEvents(events);
|
||||
kqueue_assert(0);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (events & KQ_EVENT_WRITE) {
|
||||
EV_SET(&ke, fd, EVFILT_WRITE, EV_ADD, 0, 0, NULL);
|
||||
ret = ff_kevent(_kqfd, &ke, 1, NULL, 0, NULL);
|
||||
if (ret == -1) {
|
||||
// TODO, error check
|
||||
item->DetachEvents(events);
|
||||
kqueue_assert(0);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (events & KQ_EVENT_READ) {
|
||||
EV_SET(&ke, fd, EVFILT_READ, EV_ADD, 0, 0, NULL);
|
||||
ret = ff_kevent(_kqfd, &ke, 1, NULL, 0, NULL);
|
||||
if (ret == -1) {
|
||||
// TODO, error check
|
||||
item->DetachEvents(events);
|
||||
kqueue_assert(0);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
item->SetListenEvents(new_events);
|
||||
item->SetListenEvents(new_events);
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool KqueueProxy::KqueueCtrlDel(int fd, int events)
|
||||
{
|
||||
return KqueueCtrlDelRef(fd, events, false);
|
||||
return KqueueCtrlDelRef(fd, events, false);
|
||||
}
|
||||
|
||||
bool KqueueProxy::KqueueCtrlDelRef(int fd, int events, bool use_ref)
|
||||
{
|
||||
KqFdRef* item = KqFdRefGet(fd);
|
||||
if (item == NULL)
|
||||
{
|
||||
KqFdRef* item = KqFdRefGet(fd);
|
||||
if (item == NULL)
|
||||
{
|
||||
MT_ATTR_API(320851, 1); // fd error
|
||||
MTLOG_ERROR("kqfd ref not find, failed, fd: %d", fd);
|
||||
kqueue_assert(0);
|
||||
return false;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
item->DetachEvents(events);
|
||||
int old_events = item->GetListenEvents();
|
||||
int new_events = old_events &~ events;
|
||||
item->DetachEvents(events);
|
||||
int old_events = item->GetListenEvents();
|
||||
int new_events = old_events &~ events;
|
||||
|
||||
if (use_ref) {
|
||||
new_events = old_events;
|
||||
if (item->ReadRefCnt() == 0) {
|
||||
new_events = new_events & ~KQ_EVENT_READ;
|
||||
}
|
||||
if (item->WriteRefCnt() == 0) {
|
||||
new_events = new_events & ~KQ_EVENT_WRITE;
|
||||
}
|
||||
}
|
||||
if (use_ref) {
|
||||
new_events = old_events;
|
||||
if (item->ReadRefCnt() == 0) {
|
||||
new_events = new_events & ~KQ_EVENT_READ;
|
||||
}
|
||||
if (item->WriteRefCnt() == 0) {
|
||||
new_events = new_events & ~KQ_EVENT_WRITE;
|
||||
}
|
||||
}
|
||||
|
||||
if (old_events == new_events)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
KqEvent ke;
|
||||
int ret;
|
||||
if (old_events & KQ_EVENT_WRITE) {
|
||||
EV_SET(&ke, fd, EVFILT_WRITE, EV_DELETE, 0, 0, NULL);
|
||||
ret = ff_kevent(_kqfd, &ke, 1, NULL, 0, NULL);
|
||||
if (ret == -1) {
|
||||
kqueue_assert(0);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (old_events & KQ_EVENT_READ) {
|
||||
EV_SET(&ke, fd, EVFILT_READ, EV_DELETE, 0, 0, NULL);
|
||||
ret = ff_kevent(_kqfd, &ke, 1, NULL, 0, NULL);
|
||||
if (ret == -1) {
|
||||
kqueue_assert(0);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (old_events == new_events)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
KqEvent ke;
|
||||
int ret;
|
||||
if (old_events & KQ_EVENT_WRITE) {
|
||||
EV_SET(&ke, fd, EVFILT_WRITE, EV_DELETE, 0, 0, NULL);
|
||||
ret = ff_kevent(_kqfd, &ke, 1, NULL, 0, NULL);
|
||||
if (ret == -1) {
|
||||
kqueue_assert(0);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (old_events & KQ_EVENT_READ) {
|
||||
EV_SET(&ke, fd, EVFILT_READ, EV_DELETE, 0, 0, NULL);
|
||||
ret = ff_kevent(_kqfd, &ke, 1, NULL, 0, NULL);
|
||||
if (ret == -1) {
|
||||
kqueue_assert(0);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (new_events & KQ_EVENT_WRITE) {
|
||||
EV_SET(&ke, fd, EVFILT_WRITE, EV_ADD, 0, 0, NULL);
|
||||
ret = ff_kevent(_kqfd, &ke, 1, NULL, 0, NULL);
|
||||
if (ret == -1) {
|
||||
kqueue_assert(0);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (new_events & KQ_EVENT_READ) {
|
||||
EV_SET(&ke, fd, EVFILT_READ, EV_ADD, 0, 0, NULL);
|
||||
ret = ff_kevent(_kqfd, &ke, 1, NULL, 0, NULL);
|
||||
if (ret == -1) {
|
||||
kqueue_assert(0);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (new_events & KQ_EVENT_WRITE) {
|
||||
EV_SET(&ke, fd, EVFILT_WRITE, EV_ADD, 0, 0, NULL);
|
||||
ret = ff_kevent(_kqfd, &ke, 1, NULL, 0, NULL);
|
||||
if (ret == -1) {
|
||||
kqueue_assert(0);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (new_events & KQ_EVENT_READ) {
|
||||
EV_SET(&ke, fd, EVFILT_READ, EV_ADD, 0, 0, NULL);
|
||||
ret = ff_kevent(_kqfd, &ke, 1, NULL, 0, NULL);
|
||||
if (ret == -1) {
|
||||
kqueue_assert(0);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
item->SetListenEvents(new_events);
|
||||
item->SetListenEvents(new_events);
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool KqueueProxy::KqueueAddObj(KqueuerObj* obj)
|
||||
{
|
||||
if (obj == NULL)
|
||||
{
|
||||
if (obj == NULL)
|
||||
{
|
||||
MTLOG_ERROR("kqobj input invalid, %p", obj);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
KqFdRef* item = KqFdRefGet(obj->GetOsfd());
|
||||
if (item == NULL)
|
||||
{
|
||||
KqFdRef* item = KqFdRefGet(obj->GetOsfd());
|
||||
if (item == NULL)
|
||||
{
|
||||
MT_ATTR_API(320851, 1); // fd error
|
||||
MTLOG_ERROR("kqfd ref not find, failed, fd: %d", obj->GetOsfd());
|
||||
kqueue_assert(0);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int ret = obj->KqueueCtlAdd(item);
|
||||
if (ret < 0) {
|
||||
int ret = obj->KqueueCtlAdd(item);
|
||||
if (ret < 0) {
|
||||
MTLOG_ERROR("kqueue ctrl callback failed, fd: %d, obj: %p", obj->GetOsfd(), obj);
|
||||
kqueue_assert(0);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool KqueueProxy::KqueueDelObj(KqueuerObj* obj)
|
||||
{
|
||||
if (obj == NULL)
|
||||
{
|
||||
if (obj == NULL)
|
||||
{
|
||||
MTLOG_ERROR("kqobj input invalid, %p", obj);
|
||||
return false;
|
||||
}
|
||||
KqFdRef* item = KqFdRefGet(obj->GetOsfd());
|
||||
if (item == NULL)
|
||||
{
|
||||
}
|
||||
KqFdRef* item = KqFdRefGet(obj->GetOsfd());
|
||||
if (item == NULL)
|
||||
{
|
||||
MT_ATTR_API(320851, 1); // fd error
|
||||
MTLOG_ERROR("kqfd ref not find, failed, fd: %d", obj->GetOsfd());
|
||||
kqueue_assert(0);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int ret = obj->KqueueCtlDel(item);
|
||||
if (ret < 0) {
|
||||
int ret = obj->KqueueCtlDel(item);
|
||||
if (ret < 0) {
|
||||
MTLOG_ERROR("kqueue ctrl callback failed, fd: %d, obj: %p", obj->GetOsfd(), obj);
|
||||
kqueue_assert(0);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void KqueueProxy::KqueueRcvEventList(int evtfdnum)
|
||||
{
|
||||
int ret = 0;
|
||||
int osfd = 0;
|
||||
int revents = 0;
|
||||
int tmp_evts = 0;
|
||||
KqFdRef* item = NULL;
|
||||
KqueuerObj* obj = NULL;
|
||||
int ret = 0;
|
||||
int osfd = 0;
|
||||
int revents = 0;
|
||||
int tmp_evts = 0;
|
||||
KqFdRef* item = NULL;
|
||||
KqueuerObj* obj = NULL;
|
||||
|
||||
for (int i = 0; i < evtfdnum; i++)
|
||||
{
|
||||
osfd = _evtlist[i].ident;
|
||||
for (int i = 0; i < evtfdnum; i++)
|
||||
{
|
||||
osfd = _evtlist[i].ident;
|
||||
|
||||
item = KqFdRefGet(osfd);
|
||||
if (item == NULL)
|
||||
{
|
||||
item = KqFdRefGet(osfd);
|
||||
if (item == NULL)
|
||||
{
|
||||
MT_ATTR_API(320851, 1); // fd error
|
||||
MTLOG_ERROR("kqfd ref not find, failed, fd: %d", osfd);
|
||||
kqueue_assert(0);
|
||||
continue;
|
||||
}
|
||||
tmp_evts = _evtlist[i].filter;
|
||||
if (tmp_evts == EVFILT_READ) {
|
||||
revents |= KQ_EVENT_READ;
|
||||
}
|
||||
if (tmp_evts == EVFILT_WRITE) {
|
||||
revents |= KQ_EVENT_WRITE;
|
||||
}
|
||||
obj = item->GetNotifyObj();
|
||||
if (obj == NULL)
|
||||
{
|
||||
}
|
||||
tmp_evts = _evtlist[i].filter;
|
||||
if (tmp_evts == EVFILT_READ) {
|
||||
revents |= KQ_EVENT_READ;
|
||||
}
|
||||
if (tmp_evts == EVFILT_WRITE) {
|
||||
revents |= KQ_EVENT_WRITE;
|
||||
}
|
||||
obj = item->GetNotifyObj();
|
||||
if (obj == NULL)
|
||||
{
|
||||
MTLOG_ERROR("fd notify obj null, failed, fd: %d", osfd);
|
||||
KqueueCtrlDel(osfd, (revents & (KQ_EVENT_READ | KQ_EVENT_WRITE)));
|
||||
continue;
|
||||
}
|
||||
obj->SetRcvEvents(revents);
|
||||
}
|
||||
obj->SetRcvEvents(revents);
|
||||
|
||||
if (tmp_evts == EV_ERROR)
|
||||
{
|
||||
obj->HangupNotify();
|
||||
continue;
|
||||
}
|
||||
if (tmp_evts == EV_ERROR)
|
||||
{
|
||||
obj->HangupNotify();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (revents & KQ_EVENT_READ)
|
||||
{
|
||||
ret = obj->InputNotify();
|
||||
if (ret != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (revents & KQ_EVENT_READ)
|
||||
{
|
||||
ret = obj->InputNotify();
|
||||
if (ret != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (revents & KQ_EVENT_WRITE)
|
||||
{
|
||||
ret = obj->OutputNotify();
|
||||
if (ret != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (revents & KQ_EVENT_WRITE)
|
||||
{
|
||||
ret = obj->OutputNotify();
|
||||
if (ret != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void KqueueProxy::KqueueDispatch()
|
||||
{
|
||||
int nfd;
|
||||
int wait_time = KqueueGetTimeout();
|
||||
if (wait_time) {
|
||||
struct timespec ts;
|
||||
ts.tv_sec = wait_time / 1000;
|
||||
ts.tv_nsec = 0;
|
||||
nfd = ff_kevent(_kqfd, NULL, 0, _evtlist, _maxfd, &ts);
|
||||
} else {
|
||||
nfd = ff_kevent(_kqfd, NULL, 0, _evtlist, _maxfd, NULL);
|
||||
}
|
||||
if (nfd <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
int nfd;
|
||||
int wait_time = KqueueGetTimeout();
|
||||
if (wait_time) {
|
||||
struct timespec ts;
|
||||
ts.tv_sec = wait_time / 1000;
|
||||
ts.tv_nsec = 0;
|
||||
nfd = ff_kevent(_kqfd, NULL, 0, _evtlist, _maxfd, &ts);
|
||||
} else {
|
||||
nfd = ff_kevent(_kqfd, NULL, 0, _evtlist, _maxfd, NULL);
|
||||
}
|
||||
if (nfd <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
KqueueRcvEventList(nfd);
|
||||
KqueueRcvEventList(nfd);
|
||||
}
|
||||
|
||||
int KqueuerObj::InputNotify()
|
||||
{
|
||||
MicroThread* thread = this->GetOwnerThread();
|
||||
if (thread == NULL)
|
||||
{
|
||||
kqueue_assert(0);
|
||||
MicroThread* thread = this->GetOwnerThread();
|
||||
if (thread == NULL)
|
||||
{
|
||||
kqueue_assert(0);
|
||||
MTLOG_ERROR("kqueue fd obj, no thread ptr, wrong");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (thread->HasFlag(MicroThread::IO_LIST))
|
||||
{
|
||||
if (thread->HasFlag(MicroThread::IO_LIST))
|
||||
{
|
||||
MtFrame* frame = MtFrame::Instance();
|
||||
frame->RemoveIoWait(thread);
|
||||
frame->InsertRunable(thread);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int KqueuerObj::OutputNotify()
|
||||
|
@ -476,7 +476,7 @@ int KqueuerObj::OutputNotify()
|
|||
return -1;
|
||||
}
|
||||
|
||||
// 多个事件同时到达, 防重复操作
|
||||
// Multiple events arrive at the same time
|
||||
if (thread->HasFlag(MicroThread::IO_LIST))
|
||||
{
|
||||
MtFrame* frame = MtFrame::Instance();
|
||||
|
@ -503,7 +503,7 @@ int KqueuerObj::KqueueCtlAdd(void* args)
|
|||
int osfd = this->GetOsfd();
|
||||
int new_events = this->GetEvents();
|
||||
|
||||
// 通知对象需要更新, FD通知对象理论上不会复用, 这里做冲突检查, 异常log记录
|
||||
// Notify object needs updating
|
||||
KqueuerObj* old_obj = fd_ref->GetNotifyObj();
|
||||
if ((old_obj != NULL) && (old_obj != this))
|
||||
{
|
||||
|
@ -512,7 +512,6 @@ int KqueuerObj::KqueueCtlAdd(void* args)
|
|||
}
|
||||
fd_ref->SetNotifyObj(this);
|
||||
|
||||
// 调用框架的epoll ctl接口, 屏蔽epoll ctrl细节
|
||||
if (!frame->KqueueCtrlAdd(osfd, new_events))
|
||||
{
|
||||
MTLOG_ERROR("kqfd ref add failed, log");
|
||||
|
@ -532,7 +531,6 @@ int KqueuerObj::KqueueCtlDel(void* args)
|
|||
int osfd = this->GetOsfd();
|
||||
int events = this->GetEvents();
|
||||
|
||||
// 通知对象需要更新, FD通知对象理论上不会复用, 这里做冲突检查, 异常log记录
|
||||
KqueuerObj* old_obj = fd_ref->GetNotifyObj();
|
||||
if (old_obj != this)
|
||||
{
|
||||
|
@ -541,8 +539,7 @@ int KqueuerObj::KqueueCtlDel(void* args)
|
|||
}
|
||||
fd_ref->SetNotifyObj(NULL);
|
||||
|
||||
// 调用框架的epoll ctl接口, 屏蔽epoll ctrl细节
|
||||
if (!frame->KqueueCtrlDelRef(osfd, events, false)) // 引用有风险, 弊大于利, 关闭掉
|
||||
if (!frame->KqueueCtrlDelRef(osfd, events, false))
|
||||
{
|
||||
MTLOG_ERROR("kqfd ref del failed, log");
|
||||
fd_ref->SetNotifyObj(old_obj);
|
||||
|
|
|
@ -45,10 +45,6 @@ namespace NS_MICRO_THREAD {
|
|||
#define KQ_EVENT_READ 1
|
||||
#define KQ_EVENT_WRITE 2
|
||||
|
||||
/******************************************************************************/
|
||||
/* 操作系统头文件适配定义 */
|
||||
/******************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief add more detail for linux <sys/queue.h>, freebsd and University of California
|
||||
* @info queue.h version 8.3 (suse) diff version 8.5 (tlinux)
|
||||
|
@ -90,119 +86,84 @@ do { \
|
|||
|
||||
|
||||
/******************************************************************************/
|
||||
/* Kqueue proxy 定义与实现部分 */
|
||||
/* Kqueue proxy definition and implementation */
|
||||
/******************************************************************************/
|
||||
|
||||
class KqueueProxy;
|
||||
class MicroThread;
|
||||
|
||||
/**
|
||||
* @brief kqueue通知对象基类定义
|
||||
*/
|
||||
class KqueuerObj
|
||||
{
|
||||
protected:
|
||||
int _fd;
|
||||
int _events;
|
||||
int _revents;
|
||||
int _type;
|
||||
MicroThread* _thread;
|
||||
protected:
|
||||
int _fd;
|
||||
int _events;
|
||||
int _revents;
|
||||
int _type;
|
||||
MicroThread* _thread;
|
||||
|
||||
public:
|
||||
public:
|
||||
|
||||
TAILQ_ENTRY(KqueuerObj) _entry;
|
||||
TAILQ_ENTRY(KqueuerObj) _entry;
|
||||
|
||||
explicit KqueuerObj(int fd = -1) {
|
||||
_fd = fd;
|
||||
_events = 0;
|
||||
_revents = 0;
|
||||
_type = 0;
|
||||
_thread = NULL;
|
||||
};
|
||||
virtual ~KqueuerObj(){};
|
||||
explicit KqueuerObj(int fd = -1) {
|
||||
_fd = fd;
|
||||
_events = 0;
|
||||
_revents = 0;
|
||||
_type = 0;
|
||||
_thread = NULL;
|
||||
};
|
||||
virtual ~KqueuerObj(){};
|
||||
|
||||
virtual int InputNotify();
|
||||
virtual int OutputNotify();
|
||||
virtual int HangupNotify();
|
||||
virtual int KqueueCtlAdd(void* args);
|
||||
virtual int KqueueCtlDel(void* args);
|
||||
virtual int InputNotify();
|
||||
virtual int OutputNotify();
|
||||
virtual int HangupNotify();
|
||||
virtual int KqueueCtlAdd(void* args);
|
||||
virtual int KqueueCtlDel(void* args);
|
||||
|
||||
/**
|
||||
* @brief fd打开可读事件侦听
|
||||
*/
|
||||
void EnableInput() { _events |= KQ_EVENT_READ; };
|
||||
void EnableInput() { _events |= KQ_EVENT_READ; };
|
||||
|
||||
/**
|
||||
* @brief fd打开可写事件侦听
|
||||
*/
|
||||
void EnableOutput() { _events |= KQ_EVENT_WRITE; };
|
||||
void EnableOutput() { _events |= KQ_EVENT_WRITE; };
|
||||
|
||||
/**
|
||||
* @brief fd关闭可读事件侦听
|
||||
*/
|
||||
void DisableInput() { _events &= ~KQ_EVENT_READ; };
|
||||
void DisableInput() { _events &= ~KQ_EVENT_READ; };
|
||||
|
||||
/**
|
||||
* @brief fd关闭可写事件侦听
|
||||
*/
|
||||
void DisableOutput() { _events &= ~KQ_EVENT_WRITE; };
|
||||
void DisableOutput() { _events &= ~KQ_EVENT_WRITE; };
|
||||
|
||||
/**
|
||||
* @brief 系统socket设置读取封装
|
||||
*/
|
||||
int GetOsfd() { return _fd; };
|
||||
void SetOsfd(int fd) { _fd = fd; };
|
||||
int GetOsfd() { return _fd; };
|
||||
void SetOsfd(int fd) { _fd = fd; };
|
||||
|
||||
/**
|
||||
* @brief 监听事件与收到事件的访问方法
|
||||
*/
|
||||
int GetEvents() { return _events; };
|
||||
void SetRcvEvents(int revents) { _revents = revents; };
|
||||
int GetRcvEvents() { return _revents; };
|
||||
int GetEvents() { return _events; };
|
||||
void SetRcvEvents(int revents) { _revents = revents; };
|
||||
int GetRcvEvents() { return _revents; };
|
||||
|
||||
/**
|
||||
* @brief 工厂管理方法, 获取真实类型
|
||||
*/
|
||||
int GetNtfyType() { return _type; };
|
||||
virtual void Reset() {
|
||||
_fd = -1;
|
||||
_events = 0;
|
||||
_revents = 0;
|
||||
_type = 0;
|
||||
_thread = NULL;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 设置与获取所属的微线程句柄接口
|
||||
* @param thread 关联的线程指针
|
||||
*/
|
||||
void SetOwnerThread(MicroThread* thread) { _thread = thread; };
|
||||
MicroThread* GetOwnerThread() { return _thread; };
|
||||
int GetNtfyType() { return _type; };
|
||||
virtual void Reset() {
|
||||
_fd = -1;
|
||||
_events = 0;
|
||||
_revents = 0;
|
||||
_type = 0;
|
||||
_thread = NULL;
|
||||
};
|
||||
|
||||
void SetOwnerThread(MicroThread* thread) { _thread = thread; };
|
||||
MicroThread* GetOwnerThread() { return _thread; };
|
||||
|
||||
};
|
||||
|
||||
typedef TAILQ_HEAD(__KqFdList, KqueuerObj) KqObjList; ///< 高效的双链管理
|
||||
typedef struct kevent KqEvent; ///< 重定义一下kqueue event
|
||||
typedef TAILQ_HEAD(__KqFdList, KqueuerObj) KqObjList;
|
||||
typedef struct kevent KqEvent;
|
||||
|
||||
|
||||
/**
|
||||
* @brief EPOLL支持同一FD多个线程侦听, 建立一个引用计数数组, 元素定义
|
||||
* @info 引用计数弊大于利, 没有实际意义, 字段保留, 功能移除掉 20150623
|
||||
*/
|
||||
class KqFdRef
|
||||
{
|
||||
private:
|
||||
int _wr_ref; ///< 监听写的引用计数
|
||||
int _rd_ref; ///< 监听读的引用计数
|
||||
int _events; ///< 当前正在侦听的事件列表
|
||||
int _revents; ///< 当前该fd收到的事件信息, 仅在epoll_wait后处理中有效
|
||||
KqueuerObj* _kqobj; ///< 单独注册调度器对象,一个fd关联一个对象
|
||||
int _wr_ref;
|
||||
int _rd_ref;
|
||||
int _events;
|
||||
int _revents;
|
||||
KqueuerObj* _kqobj;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief 构造与析构函数
|
||||
*/
|
||||
KqFdRef() {
|
||||
_wr_ref = 0;
|
||||
_rd_ref = 0;
|
||||
|
@ -212,9 +173,6 @@ public:
|
|||
};
|
||||
~KqFdRef(){};
|
||||
|
||||
/**
|
||||
* @brief 监听事件获取与设置接口
|
||||
*/
|
||||
void SetListenEvents(int events) {
|
||||
_events = events;
|
||||
};
|
||||
|
@ -222,9 +180,6 @@ public:
|
|||
return _events;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 监听对象获取与设置接口
|
||||
*/
|
||||
void SetNotifyObj(KqueuerObj* ntfy) {
|
||||
_kqobj = ntfy;
|
||||
};
|
||||
|
@ -232,9 +187,6 @@ public:
|
|||
return _kqobj;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 监听引用计数的更新
|
||||
*/
|
||||
void AttachEvents(int event) {
|
||||
if (event & KQ_EVENT_READ) {
|
||||
_rd_ref++;
|
||||
|
@ -260,9 +212,7 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 获取引用计数
|
||||
*/
|
||||
|
||||
int ReadRefCnt() { return _rd_ref; };
|
||||
int WriteRefCnt() { return _wr_ref; };
|
||||
|
||||
|
@ -271,47 +221,47 @@ public:
|
|||
|
||||
class KqueueProxy
|
||||
{
|
||||
public:
|
||||
static const int DEFAULT_MAX_FD_NUM = 100000;
|
||||
public:
|
||||
static const int DEFAULT_MAX_FD_NUM = 100000;
|
||||
|
||||
private:
|
||||
int _kqfd;
|
||||
int _maxfd;
|
||||
KqEvent* _evtlist;
|
||||
KqFdRef* _kqrefs;
|
||||
private:
|
||||
int _kqfd;
|
||||
int _maxfd;
|
||||
KqEvent* _evtlist;
|
||||
KqFdRef* _kqrefs;
|
||||
|
||||
public:
|
||||
KqueueProxy();
|
||||
virtual ~KqueueProxy(){};
|
||||
public:
|
||||
KqueueProxy();
|
||||
virtual ~KqueueProxy(){};
|
||||
|
||||
int InitKqueue(int max_num);
|
||||
void TermKqueue(void);
|
||||
int InitKqueue(int max_num);
|
||||
void TermKqueue(void);
|
||||
|
||||
virtual int KqueueGetTimeout(void) { return 0; };
|
||||
virtual bool KqueueSchedule(KqObjList* fdlist, KqueuerObj* fd, int timeout) { return false; };
|
||||
|
||||
bool KqueueAdd(KqObjList& fdset);
|
||||
bool KqueueDel(KqObjList& fdset);
|
||||
void KqueueDispatch(void);
|
||||
bool KqueueAddObj(KqueuerObj* obj);
|
||||
bool KqueueDelObj(KqueuerObj* obj);
|
||||
bool KqueueCtrlAdd(int fd, int new_events);
|
||||
bool KqueueCtrlDel(int fd, int new_events);
|
||||
bool KqueueCtrlDelRef(int fd, int new_events, bool use_ref);
|
||||
virtual int KqueueGetTimeout(void) { return 0; };
|
||||
virtual bool KqueueSchedule(KqObjList* fdlist, KqueuerObj* fd, int timeout) { return false; };
|
||||
|
||||
bool KqueueAdd(KqObjList& fdset);
|
||||
bool KqueueDel(KqObjList& fdset);
|
||||
void KqueueDispatch(void);
|
||||
bool KqueueAddObj(KqueuerObj* obj);
|
||||
bool KqueueDelObj(KqueuerObj* obj);
|
||||
bool KqueueCtrlAdd(int fd, int new_events);
|
||||
bool KqueueCtrlDel(int fd, int new_events);
|
||||
bool KqueueCtrlDelRef(int fd, int new_events, bool use_ref);
|
||||
|
||||
KqFdRef* KqFdRefGet(int fd) {
|
||||
return ((fd >= _maxfd) || (fd < 0)) ? (KqFdRef*)NULL : &_kqrefs[fd];
|
||||
}
|
||||
KqFdRef* KqFdRefGet(int fd) {
|
||||
return ((fd >= _maxfd) || (fd < 0)) ? (KqFdRef*)NULL : &_kqrefs[fd];
|
||||
}
|
||||
|
||||
void KqueueNtfyReg(int fd, KqueuerObj* obj) {
|
||||
KqFdRef* ref = KqFdRefGet(fd);
|
||||
if (ref) {
|
||||
ref->SetNotifyObj(obj);
|
||||
}
|
||||
};
|
||||
void KqueueNtfyReg(int fd, KqueuerObj* obj) {
|
||||
KqFdRef* ref = KqFdRefGet(fd);
|
||||
if (ref) {
|
||||
ref->SetNotifyObj(obj);
|
||||
}
|
||||
};
|
||||
|
||||
protected:
|
||||
void KqueueRcvEventList(int evtfdnum);
|
||||
protected:
|
||||
void KqueueRcvEventList(int evtfdnum);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -35,29 +35,12 @@ using namespace NS_MICRO_THREAD;
|
|||
#define ASSERT(statement)
|
||||
//#define ASSERT(statement) assert(statement)
|
||||
|
||||
/**
|
||||
* @brief 汇编实现保存上下文函数
|
||||
* @param jbf jmpbuff数组指针
|
||||
*/
|
||||
extern "C" int save_context(jmp_buf jbf);
|
||||
|
||||
/**
|
||||
* @brief 汇编实现恢复上下文函数
|
||||
* @param jbf jmpbuff数组指针
|
||||
* @param ret 切回的返回值, 默认1
|
||||
*/
|
||||
extern "C" void restore_context(jmp_buf jbf, int ret);
|
||||
|
||||
/**
|
||||
* @brief 汇编实现替换调用栈函数
|
||||
* @param jbf jmpbuff数组指针
|
||||
* @param esp 堆栈指针
|
||||
*/
|
||||
extern "C" void replace_esp(jmp_buf jbf, void* esp);
|
||||
|
||||
/**
|
||||
* @brief 构造函数, 默认参数栈大小
|
||||
*/
|
||||
Thread::Thread(int stack_size)
|
||||
{
|
||||
_stack_size = stack_size ? stack_size : ThreadPool::default_stack_size;
|
||||
|
@ -68,7 +51,7 @@ Thread::Thread(int stack_size)
|
|||
|
||||
|
||||
/**
|
||||
* @brief LINUX x86/x86_64下的栈申请, 其它架构下需要注意差异
|
||||
* @brief LINUX x86/x86_64's allocated stacks.
|
||||
*/
|
||||
bool Thread::InitStack()
|
||||
{
|
||||
|
@ -76,7 +59,7 @@ bool Thread::InitStack()
|
|||
return true;
|
||||
}
|
||||
|
||||
///< 栈索引与栈内存分离, 防越界
|
||||
///< stack index and memory are separated to prevent out of bounds.
|
||||
_stack = (MtStack*)calloc(1, sizeof(MtStack));
|
||||
if (NULL == _stack)
|
||||
{
|
||||
|
@ -102,8 +85,8 @@ bool Thread::InitStack()
|
|||
_stack->_stk_size = _stack_size;
|
||||
_stack->_stk_bottom = _stack->_vaddr + MEM_PAGE_SIZE;
|
||||
_stack->_stk_top = _stack->_stk_bottom + _stack->_stk_size;
|
||||
// valgrind support: register stack frame
|
||||
_stack->valgrind_id = VALGRIND_STACK_REGISTER(_stack->_stk_bottom, _stack->_stk_top);
|
||||
// valgrind support: register stack frame
|
||||
_stack->valgrind_id = VALGRIND_STACK_REGISTER(_stack->_stk_bottom, _stack->_stk_top);
|
||||
|
||||
_stack->_esp = _stack->_stk_top - STACK_PAD_SIZE;
|
||||
|
||||
|
@ -114,29 +97,23 @@ bool Thread::InitStack()
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 释放堆栈信息
|
||||
*/
|
||||
void Thread::FreeStack()
|
||||
{
|
||||
if (!_stack) {
|
||||
return;
|
||||
}
|
||||
munmap(_stack->_vaddr, _stack->_vaddr_size);
|
||||
// valgrind support: deregister stack frame
|
||||
VALGRIND_STACK_DEREGISTER(_stack->valgrind_id);
|
||||
// valgrind support: deregister stack frame
|
||||
VALGRIND_STACK_DEREGISTER(_stack->valgrind_id);
|
||||
free(_stack);
|
||||
_stack = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 初始化上下文,设置寄存器,堆栈
|
||||
*/
|
||||
void Thread::InitContext()
|
||||
{
|
||||
if (save_context(_jmpbuf) != 0)
|
||||
{
|
||||
ScheduleObj::Instance()->ScheduleStartRun(); // 直接调用 this->run?
|
||||
ScheduleObj::Instance()->ScheduleStartRun();
|
||||
}
|
||||
|
||||
if (_stack != NULL)
|
||||
|
@ -145,9 +122,6 @@ void Thread::InitContext()
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 主动切换, 保存状态, 触发调度
|
||||
*/
|
||||
void Thread::SwitchContext()
|
||||
{
|
||||
if (save_context(_jmpbuf) == 0)
|
||||
|
@ -156,17 +130,12 @@ void Thread::SwitchContext()
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 恢复上下文, 切换回断点,继续运行
|
||||
*/
|
||||
void Thread::RestoreContext()
|
||||
{
|
||||
restore_context(_jmpbuf, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 初始化线程,如堆栈与上下文初始化
|
||||
*/
|
||||
|
||||
bool Thread::Initial()
|
||||
{
|
||||
if (!InitStack())
|
||||
|
@ -180,18 +149,12 @@ bool Thread::Initial()
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 终止线程,如堆栈与上下文释放
|
||||
*/
|
||||
void Thread::Destroy()
|
||||
{
|
||||
FreeStack();
|
||||
memset(&_jmpbuf, 0, sizeof(_jmpbuf));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 线程状态重置, 可复用状态
|
||||
*/
|
||||
void Thread::Reset()
|
||||
{
|
||||
_wakeup_time = 0;
|
||||
|
@ -201,10 +164,6 @@ void Thread::Reset()
|
|||
CleanState();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 线程主动进入睡眠, 单位毫秒
|
||||
* @param ms 睡眠毫秒数
|
||||
*/
|
||||
void Thread::sleep(int ms)
|
||||
{
|
||||
utime64_t now = ScheduleObj::Instance()->ScheduleGetTime();
|
||||
|
@ -216,9 +175,6 @@ void Thread::sleep(int ms)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 进入阻塞状态, 等待所有子线程结束
|
||||
*/
|
||||
void Thread::Wait()
|
||||
{
|
||||
if (save_context(_jmpbuf) == 0)
|
||||
|
@ -227,24 +183,17 @@ void Thread::Wait()
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 初始化上下文,设置寄存器,堆栈
|
||||
*/
|
||||
bool Thread::CheckStackHealth(char *esp)
|
||||
{
|
||||
if (!_stack)
|
||||
return false;
|
||||
if (!_stack)
|
||||
return false;
|
||||
|
||||
if (esp > _stack->_stk_bottom && esp < _stack->_stk_top)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
if (esp > _stack->_stk_bottom && esp < _stack->_stk_top)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 微线程构造, 默认是普通线程
|
||||
* @param type 类型, 默认普通
|
||||
*/
|
||||
MicroThread::MicroThread(ThreadType type)
|
||||
{
|
||||
memset(&_entry, 0, sizeof(_entry));
|
||||
|
@ -258,9 +207,6 @@ MicroThread::MicroThread(ThreadType type)
|
|||
_parent = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @breif 微线程复用状态清理
|
||||
*/
|
||||
void MicroThread::CleanState()
|
||||
{
|
||||
TAILQ_INIT(&_fdset);
|
||||
|
@ -273,16 +219,12 @@ void MicroThread::CleanState()
|
|||
_parent = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 线程的实际工作函数
|
||||
*/
|
||||
void MicroThread::Run()
|
||||
{
|
||||
if (_start) {
|
||||
_start(_args);
|
||||
}
|
||||
|
||||
// 二级线程, 触发父线程进入可运行态
|
||||
if (this->IsSubThread()) {
|
||||
this->WakeupParent();
|
||||
}
|
||||
|
@ -291,9 +233,6 @@ void MicroThread::Run()
|
|||
ScheduleObj::Instance()->ScheduleThread();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 二级子线程唤醒父线程处理
|
||||
*/
|
||||
void MicroThread::WakeupParent()
|
||||
{
|
||||
MicroThread* parent = this->GetParent();
|
||||
|
@ -311,17 +250,11 @@ void MicroThread::WakeupParent()
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 是否还有其它的二级子线程
|
||||
*/
|
||||
bool MicroThread::HasNoSubThread()
|
||||
{
|
||||
return TAILQ_EMPTY(&_sub_list);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 将指定子线程加入二级线程列表
|
||||
*/
|
||||
void MicroThread::AddSubThread(MicroThread* sub)
|
||||
{
|
||||
ASSERT(!sub->HasFlag(MicroThread::SUB_LIST));
|
||||
|
@ -334,9 +267,6 @@ void MicroThread::AddSubThread(MicroThread* sub)
|
|||
sub->SetFlag(MicroThread::SUB_LIST);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 将指定线程移出二级线程列表
|
||||
*/
|
||||
void MicroThread::RemoveSubThread(MicroThread* sub)
|
||||
{
|
||||
ASSERT(sub->HasFlag(MicroThread::SUB_LIST));
|
||||
|
@ -349,11 +279,7 @@ void MicroThread::RemoveSubThread(MicroThread* sub)
|
|||
sub->UnsetFlag(MicroThread::SUB_LIST);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 单例类访问句柄入口
|
||||
*/
|
||||
ScheduleObj *ScheduleObj::_instance = NULL; ///< 静态句柄初始化
|
||||
ScheduleObj *ScheduleObj::_instance = NULL;
|
||||
inline ScheduleObj* ScheduleObj::Instance()
|
||||
{
|
||||
if (NULL == _instance)
|
||||
|
@ -364,18 +290,12 @@ inline ScheduleObj* ScheduleObj::Instance()
|
|||
return _instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 调度其它微线程来运行, 包裹接口
|
||||
*/
|
||||
void ScheduleObj::ScheduleThread()
|
||||
{
|
||||
MtFrame* frame = MtFrame::Instance();
|
||||
frame->ThreadSchdule();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 获取全局的时间戳, 毫秒单位
|
||||
*/
|
||||
utime64_t ScheduleObj::ScheduleGetTime()
|
||||
{
|
||||
MtFrame* frame = MtFrame::Instance();
|
||||
|
@ -390,9 +310,6 @@ utime64_t ScheduleObj::ScheduleGetTime()
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 线程调度主动进入sleep状态
|
||||
*/
|
||||
void ScheduleObj::ScheduleSleep()
|
||||
{
|
||||
MtFrame* frame = MtFrame::Instance();
|
||||
|
@ -406,9 +323,6 @@ void ScheduleObj::ScheduleSleep()
|
|||
frame->ThreadSchdule();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 线程调度主动进入pend状态
|
||||
*/
|
||||
void ScheduleObj::SchedulePend()
|
||||
{
|
||||
MtFrame* frame = MtFrame::Instance();
|
||||
|
@ -422,9 +336,6 @@ void ScheduleObj::SchedulePend()
|
|||
frame->ThreadSchdule();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 线程调度取消pend状态, 外部调度取消
|
||||
*/
|
||||
void ScheduleObj::ScheduleUnpend(void* pthread)
|
||||
{
|
||||
MtFrame* frame = MtFrame::Instance();
|
||||
|
@ -438,11 +349,6 @@ void ScheduleObj::ScheduleUnpend(void* pthread)
|
|||
frame->InsertRunable(thread);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief 线程执行完毕后, 回收处理
|
||||
*/
|
||||
void ScheduleObj::ScheduleReclaim()
|
||||
{
|
||||
MtFrame* frame = MtFrame::Instance();
|
||||
|
@ -455,9 +361,6 @@ void ScheduleObj::ScheduleReclaim()
|
|||
frame->FreeThread(thread);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 调度器调度初始执行
|
||||
*/
|
||||
void ScheduleObj::ScheduleStartRun()
|
||||
{
|
||||
MtFrame* frame = MtFrame::Instance();
|
||||
|
@ -471,15 +374,9 @@ void ScheduleObj::ScheduleStartRun()
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 微线程池全局参数初始化
|
||||
*/
|
||||
unsigned int ThreadPool::default_thread_num = DEFAULT_THREAD_NUM; ///< 默认2000微线程待命
|
||||
unsigned int ThreadPool::default_stack_size = DEFAULT_STACK_SIZE; ///< 默认128K栈大小
|
||||
unsigned int ThreadPool::default_thread_num = DEFAULT_THREAD_NUM; ///< 2000 micro threads.
|
||||
unsigned int ThreadPool::default_stack_size = DEFAULT_STACK_SIZE; ///< 128k stack.
|
||||
|
||||
/**
|
||||
* @brief 微线程池初始化
|
||||
*/
|
||||
bool ThreadPool::InitialPool(int max_num)
|
||||
{
|
||||
MicroThread *thread = NULL;
|
||||
|
@ -509,9 +406,6 @@ bool ThreadPool::InitialPool(int max_num)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 微线程池反初始化
|
||||
*/
|
||||
void ThreadPool::DestroyPool()
|
||||
{
|
||||
MicroThread* thread = NULL;
|
||||
|
@ -527,13 +421,9 @@ void ThreadPool::DestroyPool()
|
|||
_use_num = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 微线程分配接口
|
||||
* @return 微线程对象
|
||||
*/
|
||||
MicroThread* ThreadPool::AllocThread()
|
||||
{
|
||||
MT_ATTR_API_SET(492069, _total_num); // 微线程池大小
|
||||
MT_ATTR_API_SET(492069, _total_num);
|
||||
|
||||
MicroThread* thread = NULL;
|
||||
if (!_freelist.empty())
|
||||
|
@ -569,10 +459,6 @@ MicroThread* ThreadPool::AllocThread()
|
|||
return thread;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 微线程释放接口
|
||||
* @param thread 微线程对象
|
||||
*/
|
||||
void ThreadPool::FreeThread(MicroThread* thread)
|
||||
{
|
||||
ASSERT(!thread->HasFlag(MicroThread::FREE_LIST));
|
||||
|
@ -581,7 +467,6 @@ void ThreadPool::FreeThread(MicroThread* thread)
|
|||
_freelist.push(thread);
|
||||
thread->SetFlag(MicroThread::FREE_LIST);
|
||||
|
||||
///< 空闲队列 > default_thread_num, 则释放最老的, 不可以释放当前
|
||||
unsigned int free_num = _freelist.size();
|
||||
if ((free_num > default_thread_num) && (free_num > 1))
|
||||
{
|
||||
|
@ -595,12 +480,9 @@ void ThreadPool::FreeThread(MicroThread* thread)
|
|||
|
||||
int ThreadPool::GetUsedNum(void)
|
||||
{
|
||||
return _use_num;
|
||||
return _use_num;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 微线程框架类, 全局实例获取
|
||||
*/
|
||||
MtFrame *MtFrame::_instance = NULL;
|
||||
inline MtFrame* MtFrame::Instance ()
|
||||
{
|
||||
|
@ -612,30 +494,20 @@ inline MtFrame* MtFrame::Instance ()
|
|||
return _instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief HOOK系统api的设置
|
||||
*/
|
||||
void MtFrame::SetHookFlag() {
|
||||
mt_set_hook_flag();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief 框架初始化, 默认不带日志运行
|
||||
*/
|
||||
bool MtFrame::InitFrame(LogAdapter* logadpt, int max_thread_num)
|
||||
{
|
||||
_log_adpt = logadpt;
|
||||
|
||||
// 设置最大允许的线程数目, 尝试调节epoll监控的fd数目
|
||||
if ((this->InitKqueue(max_thread_num) < 0) || !this->InitialPool(max_thread_num))
|
||||
{
|
||||
MTLOG_ERROR("Init epoll or thread pool failed");
|
||||
this->Destroy();
|
||||
return false;
|
||||
}
|
||||
|
||||
// 按需重置堆大小, 放大堆个数为2倍
|
||||
if (_sleeplist.HeapResize(max_thread_num * 2) < 0)
|
||||
{
|
||||
MTLOG_ERROR("Init heap list failed");
|
||||
|
@ -643,7 +515,6 @@ bool MtFrame::InitFrame(LogAdapter* logadpt, int max_thread_num)
|
|||
return false;
|
||||
}
|
||||
|
||||
// 定时器管理初始化, 放大堆个数为2倍
|
||||
_timer = new CTimerMng(max_thread_num * 2);
|
||||
if (NULL == _timer)
|
||||
{
|
||||
|
@ -652,7 +523,6 @@ bool MtFrame::InitFrame(LogAdapter* logadpt, int max_thread_num)
|
|||
return false;
|
||||
}
|
||||
|
||||
// 守护线程单独初始化
|
||||
_daemon = AllocThread();
|
||||
if (NULL == _daemon)
|
||||
{
|
||||
|
@ -664,7 +534,6 @@ bool MtFrame::InitFrame(LogAdapter* logadpt, int max_thread_num)
|
|||
_daemon->SetState(MicroThread::RUNABLE);
|
||||
_daemon->SetSartFunc(MtFrame::DaemonRun, this);
|
||||
|
||||
// 特殊线程, 无需INIT, 不初始化栈, 也无回调注册, 但需要统一调度
|
||||
_primo = new MicroThread(MicroThread::PRIMORDIAL);
|
||||
if (NULL == _primo)
|
||||
{
|
||||
|
@ -675,20 +544,16 @@ bool MtFrame::InitFrame(LogAdapter* logadpt, int max_thread_num)
|
|||
_primo->SetState(MicroThread::RUNNING);
|
||||
SetActiveThread(_primo);
|
||||
|
||||
// 更新最新时间戳
|
||||
_last_clock = GetSystemMS();
|
||||
TAILQ_INIT(&_iolist);
|
||||
TAILQ_INIT(&_pend_list);
|
||||
|
||||
//SetHookFlag();
|
||||
//SetHookFlag();
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 框架反初始化
|
||||
*/
|
||||
void MtFrame::Destroy(void)
|
||||
{
|
||||
if (NULL == _instance )
|
||||
|
@ -741,20 +606,11 @@ void MtFrame::Destroy(void)
|
|||
_instance = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 微线程框架版本获取
|
||||
*/
|
||||
char* MtFrame::Version()
|
||||
{
|
||||
return IMT_VERSION;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 微线程创建接口
|
||||
* @param entry 线程入口函数
|
||||
* @param args 线程入口参数
|
||||
* @return 微线程指针, NULL表示失败
|
||||
*/
|
||||
MicroThread* MtFrame::CreateThread(ThreadStart entry, void *args, bool runable)
|
||||
{
|
||||
MtFrame* mtframe = MtFrame::Instance();
|
||||
|
@ -778,39 +634,32 @@ int MtFrame::Loop(void* args)
|
|||
MtFrame* mtframe = MtFrame::Instance();
|
||||
MicroThread* daemon = mtframe->DaemonThread();
|
||||
|
||||
mtframe->KqueueDispatch();
|
||||
mtframe->SetLastClock(mtframe->GetSystemMS());
|
||||
mtframe->WakeupTimeout();
|
||||
mtframe->CheckExpired();
|
||||
daemon->SwitchContext();
|
||||
mtframe->KqueueDispatch();
|
||||
mtframe->SetLastClock(mtframe->GetSystemMS());
|
||||
mtframe->WakeupTimeout();
|
||||
mtframe->CheckExpired();
|
||||
daemon->SwitchContext();
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 守护线程入口函数, 函数指针要求static类型
|
||||
* @param args 线程入口参数
|
||||
*/
|
||||
void MtFrame::DaemonRun(void* args)
|
||||
{
|
||||
/*
|
||||
/*
|
||||
MtFrame* mtframe = MtFrame::Instance();
|
||||
MicroThread* daemon = mtframe->DaemonThread();
|
||||
|
||||
while (true) {
|
||||
mtframe->KqueueDispatch();
|
||||
mtframe->SetLastClock(mtframe->GetSystemMS());
|
||||
mtframe->WakeupTimeout();
|
||||
mtframe->CheckExpired();
|
||||
daemon->SwitchContext();
|
||||
}
|
||||
*/
|
||||
ff_run(MtFrame::Loop, NULL);
|
||||
while (true) {
|
||||
mtframe->KqueueDispatch();
|
||||
mtframe->SetLastClock(mtframe->GetSystemMS());
|
||||
mtframe->WakeupTimeout();
|
||||
mtframe->CheckExpired();
|
||||
daemon->SwitchContext();
|
||||
}
|
||||
*/
|
||||
ff_run(MtFrame::Loop, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 获取当前线程的根线程
|
||||
*/
|
||||
MicroThread *MtFrame::GetRootThread()
|
||||
{
|
||||
if (NULL == _curr_thread)
|
||||
|
@ -837,9 +686,6 @@ MicroThread *MtFrame::GetRootThread()
|
|||
return parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 框架调度线程运行
|
||||
*/
|
||||
void MtFrame::ThreadSchdule()
|
||||
{
|
||||
MicroThread* thread = NULL;
|
||||
|
@ -860,9 +706,6 @@ void MtFrame::ThreadSchdule()
|
|||
thread->RestoreContext();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 框架处理定时回调函数
|
||||
*/
|
||||
void MtFrame::CheckExpired()
|
||||
{
|
||||
static utime64_t check_time = 0;
|
||||
|
@ -881,9 +724,6 @@ void MtFrame::CheckExpired()
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 框架检测到超时, 唤醒所有的超时线程
|
||||
*/
|
||||
void MtFrame::WakeupTimeout()
|
||||
{
|
||||
utime64_t now = GetLastClock();
|
||||
|
@ -891,7 +731,7 @@ void MtFrame::WakeupTimeout()
|
|||
while (thread && (thread->GetWakeupTime() <= now))
|
||||
{
|
||||
if (thread->HasFlag(MicroThread::IO_LIST))
|
||||
{
|
||||
{
|
||||
RemoveIoWait(thread);
|
||||
}
|
||||
else
|
||||
|
@ -905,16 +745,13 @@ void MtFrame::WakeupTimeout()
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 框架调用epoll wait前, 判定等待时间信息
|
||||
*/
|
||||
int MtFrame::KqueueGetTimeout()
|
||||
{
|
||||
utime64_t now = GetLastClock();
|
||||
MicroThread* thread = dynamic_cast<MicroThread*>(_sleeplist.HeapTop());
|
||||
if (!thread)
|
||||
{
|
||||
return 10; //默认10ms epollwait
|
||||
return 10; //default 10ms epollwait
|
||||
}
|
||||
else if (thread->GetWakeupTime() < now)
|
||||
{
|
||||
|
@ -926,10 +763,6 @@ int MtFrame::KqueueGetTimeout()
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 框架管理线程单元, 插入排序堆
|
||||
* @param thread 微线程对象
|
||||
*/
|
||||
inline void MtFrame::InsertSleep(MicroThread* thread)
|
||||
{
|
||||
ASSERT(!thread->HasFlag(MicroThread::SLEEP_LIST));
|
||||
|
@ -944,10 +777,6 @@ inline void MtFrame::InsertSleep(MicroThread* thread)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 框架管理线程单元, 移除排序堆
|
||||
* @param thread 微线程对象
|
||||
*/
|
||||
inline void MtFrame::RemoveSleep(MicroThread* thread)
|
||||
{
|
||||
ASSERT(thread->HasFlag(MicroThread::SLEEP_LIST));
|
||||
|
@ -961,10 +790,6 @@ inline void MtFrame::RemoveSleep(MicroThread* thread)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 框架管理线程单元, 执行IO等待状态
|
||||
* @param thread 微线程对象
|
||||
*/
|
||||
inline void MtFrame::InsertIoWait(MicroThread* thread)
|
||||
{
|
||||
ASSERT(!thread->HasFlag(MicroThread::IO_LIST));
|
||||
|
@ -973,10 +798,6 @@ inline void MtFrame::InsertIoWait(MicroThread* thread)
|
|||
InsertSleep(thread);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 框架管理线程单元, 移除IO等待状态
|
||||
* @param thread 微线程对象
|
||||
*/
|
||||
void MtFrame::RemoveIoWait(MicroThread* thread)
|
||||
{
|
||||
ASSERT(thread->HasFlag(MicroThread::IO_LIST));
|
||||
|
@ -986,10 +807,6 @@ void MtFrame::RemoveIoWait(MicroThread* thread)
|
|||
RemoveSleep(thread);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 框架管理线程单元, 插入可运行队列
|
||||
* @param thread 微线程对象
|
||||
*/
|
||||
void MtFrame::InsertRunable(MicroThread* thread)
|
||||
{
|
||||
ASSERT(!thread->HasFlag(MicroThread::RUN_LIST));
|
||||
|
@ -1000,10 +817,6 @@ void MtFrame::InsertRunable(MicroThread* thread)
|
|||
_waitnum++;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 框架管理线程单元, 移出可运行队列
|
||||
* @param thread 微线程对象
|
||||
*/
|
||||
inline void MtFrame::RemoveRunable(MicroThread* thread)
|
||||
{
|
||||
ASSERT(thread->HasFlag(MicroThread::RUN_LIST));
|
||||
|
@ -1014,11 +827,6 @@ inline void MtFrame::RemoveRunable(MicroThread* thread)
|
|||
_waitnum--;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 框架管理线程单元, 执行pend等待状态
|
||||
* @param thread 微线程对象
|
||||
*/
|
||||
void MtFrame::InsertPend(MicroThread* thread)
|
||||
{
|
||||
ASSERT(!thread->HasFlag(MicroThread::PEND_LIST));
|
||||
|
@ -1027,10 +835,6 @@ void MtFrame::InsertPend(MicroThread* thread)
|
|||
thread->SetState(MicroThread::PENDING);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 框架管理线程单元, 移除PEND等待状态
|
||||
* @param thread 微线程对象
|
||||
*/
|
||||
void MtFrame::RemovePend(MicroThread* thread)
|
||||
{
|
||||
ASSERT(thread->HasFlag(MicroThread::PEND_LIST));
|
||||
|
@ -1038,10 +842,6 @@ void MtFrame::RemovePend(MicroThread* thread)
|
|||
TAILQ_REMOVE(&_pend_list, thread, _entry);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 微线程主动切换, 等待其它线程的唤醒
|
||||
* @param timeout 最长等待时间, 毫秒
|
||||
*/
|
||||
void MtFrame::WaitNotify(utime64_t timeout)
|
||||
{
|
||||
MicroThread* thread = GetActiveThread();
|
||||
|
@ -1051,13 +851,6 @@ void MtFrame::WaitNotify(utime64_t timeout)
|
|||
thread->SwitchContext();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 微线程触发切换函数,调用成功 则让出cpu
|
||||
* @param fdlist 多路并发的socket列表
|
||||
* @param fd 单个请求的fd信息
|
||||
* @param timeout 最长等待时间, 毫秒
|
||||
* @return true 成功, false 失败
|
||||
*/
|
||||
bool MtFrame::KqueueSchedule(KqObjList* fdlist, KqueuerObj* fd, int timeout)
|
||||
{
|
||||
MicroThread* thread = GetActiveThread();
|
||||
|
@ -1067,7 +860,6 @@ bool MtFrame::KqueueSchedule(KqObjList* fdlist, KqueuerObj* fd, int timeout)
|
|||
return false;
|
||||
}
|
||||
|
||||
// 1. 整合该线程需要关心的epoll调度对象
|
||||
thread->ClearAllFd();
|
||||
if (fdlist)
|
||||
{
|
||||
|
@ -1078,7 +870,6 @@ bool MtFrame::KqueueSchedule(KqObjList* fdlist, KqueuerObj* fd, int timeout)
|
|||
thread->AddFd(fd);
|
||||
}
|
||||
|
||||
// 2. 设置epoll监听事件, 调整超时时间, 切换IO等待状态, 触发切换
|
||||
thread->SetWakeupTime(timeout + this->GetLastClock());
|
||||
if (!this->KqueueAdd(thread->GetFdSet()))
|
||||
{
|
||||
|
@ -1088,7 +879,6 @@ bool MtFrame::KqueueSchedule(KqObjList* fdlist, KqueuerObj* fd, int timeout)
|
|||
this->InsertIoWait(thread);
|
||||
thread->SwitchContext();
|
||||
|
||||
// 3. 调度OK, 判定超时, epoll ctrl 还原状态
|
||||
int rcvnum = 0;
|
||||
KqObjList& rcvfds = thread->GetFdSet();
|
||||
KqueuerObj* fdata = NULL;
|
||||
|
@ -1099,9 +889,9 @@ bool MtFrame::KqueueSchedule(KqObjList* fdlist, KqueuerObj* fd, int timeout)
|
|||
rcvnum++;
|
||||
}
|
||||
}
|
||||
this->KqueueDel(rcvfds); // 在一个函数中ADD, DEL 闭环控制
|
||||
this->KqueueDel(rcvfds);
|
||||
|
||||
if (rcvnum == 0) // 超时处理, 返回错误
|
||||
if (rcvnum == 0)
|
||||
{
|
||||
errno = ETIME;
|
||||
return false;
|
||||
|
@ -1110,16 +900,6 @@ bool MtFrame::KqueueSchedule(KqObjList* fdlist, KqueuerObj* fd, int timeout)
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 微线程包裹的系统IO函数 recvfrom
|
||||
* @param fd 系统socket信息
|
||||
* @param buf 接收消息缓冲区指针
|
||||
* @param len 接收消息缓冲区长度
|
||||
* @param from 来源地址的指针
|
||||
* @param fromlen 来源地址的结构长度
|
||||
* @param timeout 最长等待时间, 毫秒
|
||||
* @return >0 成功接收长度, <0 失败
|
||||
*/
|
||||
int MtFrame::recvfrom(int fd, void *buf, int len, int flags, struct sockaddr *from, socklen_t *fromlen, int timeout)
|
||||
{
|
||||
MtFrame* mtframe = MtFrame::Instance();
|
||||
|
@ -1129,9 +909,9 @@ int MtFrame::recvfrom(int fd, void *buf, int len, int flags, struct sockaddr *fr
|
|||
|
||||
if(fd<0 || !buf || len<1)
|
||||
{
|
||||
errno = EINVAL;
|
||||
MTLOG_ERROR("recvfrom failed, errno: %d (%m)", errno);
|
||||
return -10;
|
||||
errno = EINVAL;
|
||||
MTLOG_ERROR("recvfrom failed, errno: %d (%m)", errno);
|
||||
return -10;
|
||||
}
|
||||
|
||||
if (timeout <= -1)
|
||||
|
@ -1180,16 +960,6 @@ int MtFrame::recvfrom(int fd, void *buf, int len, int flags, struct sockaddr *fr
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 微线程包裹的系统IO函数 sendto
|
||||
* @param fd 系统socket信息
|
||||
* @param msg 待发送的消息指针
|
||||
* @param len 待发送的消息长度
|
||||
* @param to 目的地址的指针
|
||||
* @param tolen 目的地址的结构长度
|
||||
* @param timeout 最长等待时间, 毫秒
|
||||
* @return >0 成功发送长度, <0 失败
|
||||
*/
|
||||
int MtFrame::sendto(int fd, const void *msg, int len, int flags, const struct sockaddr *to, int tolen, int timeout)
|
||||
{
|
||||
MtFrame* mtframe = MtFrame::Instance();
|
||||
|
@ -1199,9 +969,9 @@ int MtFrame::sendto(int fd, const void *msg, int len, int flags, const struct so
|
|||
|
||||
if(fd<0 || !msg || len<1)
|
||||
{
|
||||
errno = EINVAL;
|
||||
MTLOG_ERROR("sendto failed, errno: %d (%m)", errno);
|
||||
return -10;
|
||||
errno = EINVAL;
|
||||
MTLOG_ERROR("sendto failed, errno: %d (%m)", errno);
|
||||
return -10;
|
||||
}
|
||||
|
||||
int n = 0;
|
||||
|
@ -1236,14 +1006,6 @@ int MtFrame::sendto(int fd, const void *msg, int len, int flags, const struct so
|
|||
return n;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 微线程包裹的系统IO函数 connect
|
||||
* @param fd 系统socket信息
|
||||
* @param addr 指定server的目的地址
|
||||
* @param addrlen 地址的长度
|
||||
* @param timeout 最长等待时间, 毫秒
|
||||
* @return =0 连接成功, <0 失败
|
||||
*/
|
||||
int MtFrame::connect(int fd, const struct sockaddr *addr, int addrlen, int timeout)
|
||||
{
|
||||
MtFrame* mtframe = MtFrame::Instance();
|
||||
|
@ -1253,9 +1015,9 @@ int MtFrame::connect(int fd, const struct sockaddr *addr, int addrlen, int timeo
|
|||
|
||||
if(fd<0 || !addr || addrlen<1)
|
||||
{
|
||||
errno = EINVAL;
|
||||
MTLOG_ERROR("connect failed, errno: %d (%m)", errno);
|
||||
return -10;
|
||||
errno = EINVAL;
|
||||
MTLOG_ERROR("connect failed, errno: %d (%m)", errno);
|
||||
return -10;
|
||||
}
|
||||
|
||||
int n = 0;
|
||||
|
@ -1269,7 +1031,7 @@ int MtFrame::connect(int fd, const struct sockaddr *addr, int addrlen, int timeo
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (errno == EISCONN) // 已连接, 返回成功
|
||||
if (errno == EISCONN)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
@ -1295,14 +1057,6 @@ int MtFrame::connect(int fd, const struct sockaddr *addr, int addrlen, int timeo
|
|||
return n;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 微线程包裹的系统IO函数 accept
|
||||
* @param fd 监听套接字
|
||||
* @param addr 客户端地址
|
||||
* @param addrlen 地址的长度
|
||||
* @param timeout 最长等待时间, 毫秒
|
||||
* @return >=0 accept的socket描述符, <0 失败
|
||||
*/
|
||||
int MtFrame::accept(int fd, struct sockaddr *addr, socklen_t *addrlen, int timeout)
|
||||
{
|
||||
MtFrame* mtframe = MtFrame::Instance();
|
||||
|
@ -1312,9 +1066,9 @@ int MtFrame::accept(int fd, struct sockaddr *addr, socklen_t *addrlen, int timeo
|
|||
|
||||
if(fd<0)
|
||||
{
|
||||
errno = EINVAL;
|
||||
MTLOG_ERROR("accept failed, errno: %d (%m)", errno);
|
||||
return -10;
|
||||
errno = EINVAL;
|
||||
MTLOG_ERROR("accept failed, errno: %d (%m)", errno);
|
||||
return -10;
|
||||
}
|
||||
|
||||
int acceptfd = 0;
|
||||
|
@ -1349,15 +1103,6 @@ int MtFrame::accept(int fd, struct sockaddr *addr, socklen_t *addrlen, int timeo
|
|||
return acceptfd;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 微线程包裹的系统IO函数 read
|
||||
* @param fd 系统socket信息
|
||||
* @param buf 接收消息缓冲区指针
|
||||
* @param nbyte 接收消息缓冲区长度
|
||||
* @param timeout 最长等待时间, 毫秒
|
||||
* @return >0 成功接收长度, <0 失败
|
||||
*/
|
||||
ssize_t MtFrame::read(int fd, void *buf, size_t nbyte, int timeout)
|
||||
{
|
||||
MtFrame* mtframe = MtFrame::Instance();
|
||||
|
@ -1367,9 +1112,9 @@ ssize_t MtFrame::read(int fd, void *buf, size_t nbyte, int timeout)
|
|||
|
||||
if(fd<0 || !buf || nbyte<1)
|
||||
{
|
||||
errno = EINVAL;
|
||||
MTLOG_ERROR("read failed, errno: %d (%m)", errno);
|
||||
return -10;
|
||||
errno = EINVAL;
|
||||
MTLOG_ERROR("read failed, errno: %d (%m)", errno);
|
||||
return -10;
|
||||
}
|
||||
|
||||
ssize_t n = 0;
|
||||
|
@ -1404,14 +1149,6 @@ ssize_t MtFrame::read(int fd, void *buf, size_t nbyte, int timeout)
|
|||
return n;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 微线程包裹的系统IO函数 write
|
||||
* @param fd 系统socket信息
|
||||
* @param buf 待发送的消息指针
|
||||
* @param nbyte 待发送的消息长度
|
||||
* @param timeout 最长等待时间, 毫秒
|
||||
* @return >0 成功发送长度, <0 失败
|
||||
*/
|
||||
ssize_t MtFrame::write(int fd, const void *buf, size_t nbyte, int timeout)
|
||||
{
|
||||
MtFrame* mtframe = MtFrame::Instance();
|
||||
|
@ -1421,9 +1158,9 @@ ssize_t MtFrame::write(int fd, const void *buf, size_t nbyte, int timeout)
|
|||
|
||||
if(fd<0 || !buf || nbyte<1)
|
||||
{
|
||||
errno = EINVAL;
|
||||
MTLOG_ERROR("write failed, errno: %d (%m)", errno);
|
||||
return -10;
|
||||
errno = EINVAL;
|
||||
MTLOG_ERROR("write failed, errno: %d (%m)", errno);
|
||||
return -10;
|
||||
}
|
||||
|
||||
ssize_t n = 0;
|
||||
|
@ -1470,15 +1207,6 @@ ssize_t MtFrame::write(int fd, const void *buf, size_t nbyte, int timeout)
|
|||
return nbyte;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 微线程包裹的系统IO函数 recv
|
||||
* @param fd 系统socket信息
|
||||
* @param buf 接收消息缓冲区指针
|
||||
* @param len 接收消息缓冲区长度
|
||||
* @param timeout 最长等待时间, 毫秒
|
||||
* @return >0 成功接收长度, <0 失败
|
||||
*/
|
||||
int MtFrame::recv(int fd, void *buf, int len, int flags, int timeout)
|
||||
{
|
||||
MtFrame* mtframe = MtFrame::Instance();
|
||||
|
@ -1488,9 +1216,9 @@ int MtFrame::recv(int fd, void *buf, int len, int flags, int timeout)
|
|||
|
||||
if(fd<0 || !buf || len<1)
|
||||
{
|
||||
errno = EINVAL;
|
||||
MTLOG_ERROR("recv failed, errno: %d (%m)", errno);
|
||||
return -10;
|
||||
errno = EINVAL;
|
||||
MTLOG_ERROR("recv failed, errno: %d (%m)", errno);
|
||||
return -10;
|
||||
}
|
||||
|
||||
if (timeout <= -1)
|
||||
|
@ -1539,14 +1267,6 @@ int MtFrame::recv(int fd, void *buf, int len, int flags, int timeout)
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 微线程包裹的系统IO函数 send
|
||||
* @param fd 系统socket信息
|
||||
* @param buf 待发送的消息指针
|
||||
* @param nbyte 待发送的消息长度
|
||||
* @param timeout 最长等待时间, 毫秒
|
||||
* @return >0 成功发送长度, <0 失败
|
||||
*/
|
||||
ssize_t MtFrame::send(int fd, const void *buf, size_t nbyte, int flags, int timeout)
|
||||
{
|
||||
MtFrame* mtframe = MtFrame::Instance();
|
||||
|
@ -1556,9 +1276,9 @@ ssize_t MtFrame::send(int fd, const void *buf, size_t nbyte, int flags, int time
|
|||
|
||||
if(fd<0 || !buf || nbyte<1)
|
||||
{
|
||||
errno = EINVAL;
|
||||
MTLOG_ERROR("send failed, errno: %d (%m)", errno);
|
||||
return -10;
|
||||
errno = EINVAL;
|
||||
MTLOG_ERROR("send failed, errno: %d (%m)", errno);
|
||||
return -10;
|
||||
}
|
||||
|
||||
ssize_t n = 0;
|
||||
|
@ -1605,11 +1325,6 @@ ssize_t MtFrame::send(int fd, const void *buf, size_t nbyte, int flags, int time
|
|||
return nbyte;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief 微线程主动sleep接口, 单位ms
|
||||
*/
|
||||
void MtFrame::sleep(int ms)
|
||||
{
|
||||
MtFrame* frame = MtFrame::Instance();
|
||||
|
@ -1620,13 +1335,6 @@ void MtFrame::sleep(int ms)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 微线程包裹的系统IO函数 recv
|
||||
* @param fd 系统socket信息
|
||||
* @param events 事件类型 EPOLLIN or EPOLLOUT
|
||||
* @param timeout 最长等待时间, 毫秒
|
||||
* @return >0 成功接收长度, <0 失败
|
||||
*/
|
||||
int MtFrame::WaitEvents(int fd, int events, int timeout)
|
||||
{
|
||||
MtFrame* mtframe = MtFrame::Instance();
|
||||
|
@ -1669,5 +1377,3 @@ int MtFrame::WaitEvents(int fd, int events, int timeout)
|
|||
return epfd.GetRcvEvents();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -54,269 +54,159 @@ using std::queue;
|
|||
|
||||
namespace NS_MICRO_THREAD {
|
||||
|
||||
#define STACK_PAD_SIZE 128 ///< 栈上下隔离区域的大小
|
||||
#define MEM_PAGE_SIZE 4096 ///< 内存页默认大小
|
||||
#define DEFAULT_STACK_SIZE 128*1024 ///< 默认栈大小128K
|
||||
#define DEFAULT_THREAD_NUM 2000 ///< 默认2000个初始线程
|
||||
#define STACK_PAD_SIZE 128
|
||||
#define MEM_PAGE_SIZE 4096
|
||||
#define DEFAULT_STACK_SIZE 128*1024
|
||||
#define DEFAULT_THREAD_NUM 2000
|
||||
|
||||
typedef unsigned long long utime64_t; ///< 64位的时间定义
|
||||
typedef void (*ThreadStart)(void*); ///< 微线程入口函数定义
|
||||
typedef unsigned long long utime64_t;
|
||||
typedef void (*ThreadStart)(void*);
|
||||
|
||||
/**
|
||||
* @brief 线程调度的适配对象定义, 框架类最小接口封装
|
||||
*/
|
||||
class ScheduleObj
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief 单例类访问句柄入口
|
||||
*/
|
||||
static ScheduleObj* Instance (void);
|
||||
|
||||
/**
|
||||
* @brief 获取全局的时间戳, 毫秒单位
|
||||
*/
|
||||
utime64_t ScheduleGetTime(void);
|
||||
|
||||
/**
|
||||
* @brief 调度其它微线程来运行
|
||||
*/
|
||||
void ScheduleThread(void);
|
||||
|
||||
/**
|
||||
* @brief 线程调度主动进入sleep状态
|
||||
*/
|
||||
void ScheduleSleep(void);
|
||||
|
||||
/**
|
||||
* @brief 线程调度主动进入pend状态
|
||||
*/
|
||||
void SchedulePend(void);
|
||||
|
||||
/**
|
||||
* @brief 线程调度取消pend状态, 外部调度取消
|
||||
*/
|
||||
void ScheduleUnpend(void* thread);
|
||||
|
||||
/**
|
||||
* @brief 线程执行完毕后, 回收处理
|
||||
*/
|
||||
void ScheduleReclaim(void);
|
||||
|
||||
/**
|
||||
* @brief 调度器调度初始执行
|
||||
*/
|
||||
void ScheduleStartRun(void);
|
||||
|
||||
private:
|
||||
static ScheduleObj* _instance; // 私有句柄
|
||||
static ScheduleObj* _instance;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief 线程通用的栈帧结构定义
|
||||
*/
|
||||
struct MtStack
|
||||
{
|
||||
int _stk_size; ///< 栈的大小, 有效使用空间
|
||||
int _vaddr_size; ///< 申请的buff总大小
|
||||
char *_vaddr; ///< 申请的内存基地址
|
||||
void *_esp; ///< 栈的esp寄存器
|
||||
char *_stk_bottom; ///< 栈最低的地址空间
|
||||
char *_stk_top; ///< 栈最高的地址空间
|
||||
void *_private; ///< 线程私有数据
|
||||
int valgrind_id; ///< valgrind id
|
||||
int _stk_size;
|
||||
int _vaddr_size;
|
||||
char *_vaddr;
|
||||
void *_esp;
|
||||
char *_stk_bottom;
|
||||
char *_stk_top;
|
||||
void *_private;
|
||||
int valgrind_id;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief 通用的线程模型定义
|
||||
*/
|
||||
class Thread : public HeapEntry
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief 构造与析构函数
|
||||
*/
|
||||
explicit Thread(int stack_size = 0);
|
||||
virtual ~Thread(){};
|
||||
|
||||
/**
|
||||
* @brief 线程的实际工作函数
|
||||
*/
|
||||
virtual void Run(void){};
|
||||
|
||||
/**
|
||||
* @brief 初始化线程,如堆栈与上下文初始化
|
||||
*/
|
||||
bool Initial(void);
|
||||
|
||||
/**
|
||||
* @brief 终止线程,如堆栈与上下文释放
|
||||
*/
|
||||
void Destroy(void);
|
||||
|
||||
/**
|
||||
* @brief 线程状态重置, 可复用状态
|
||||
*/
|
||||
void Reset(void);
|
||||
|
||||
/**
|
||||
* @brief 线程主动进入睡眠, 单位毫秒
|
||||
* @param ms 睡眠毫秒数
|
||||
*/
|
||||
void sleep(int ms);
|
||||
|
||||
/**
|
||||
* @brief 线程主动进入等待, 让二级线程先运行
|
||||
*/
|
||||
void Wait();
|
||||
|
||||
/**
|
||||
* @brief 主动切换, 保存状态, 触发调度
|
||||
*/
|
||||
void SwitchContext(void);
|
||||
|
||||
/**
|
||||
* @brief 恢复上下文, 切换运行
|
||||
*/
|
||||
void RestoreContext(void);
|
||||
|
||||
/**
|
||||
* @brief 获取最后唤醒时间
|
||||
* @return 线程的唤醒时间点
|
||||
*/
|
||||
utime64_t GetWakeupTime(void) {
|
||||
return _wakeup_time;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 设置最后唤醒时间
|
||||
* @param waketime 线程的唤醒时间点
|
||||
*/
|
||||
void SetWakeupTime(utime64_t waketime) {
|
||||
_wakeup_time = waketime;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 设置线程私有数据
|
||||
* @param data 线程私有数据指针,使用者需自己申请内存,这里只保存指针
|
||||
*/
|
||||
void SetPrivate(void *data)
|
||||
{
|
||||
_stack->_private = data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 获取线程私有数据
|
||||
*/
|
||||
void* GetPrivate()
|
||||
{
|
||||
return _stack->_private;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 初始化上下文,设置寄存器,堆栈
|
||||
*/
|
||||
bool CheckStackHealth(char *esp);
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* @brief 清理线程处理状态, 准备复用
|
||||
*/
|
||||
virtual void CleanState(void){};
|
||||
|
||||
/**
|
||||
* @brief 初始化堆栈信息
|
||||
*/
|
||||
virtual bool InitStack(void);
|
||||
|
||||
/**
|
||||
* @brief 释放堆栈信息
|
||||
*/
|
||||
virtual void FreeStack(void);
|
||||
|
||||
/**
|
||||
* @brief 初始化上下文,设置寄存器,堆栈
|
||||
*/
|
||||
virtual void InitContext(void);
|
||||
|
||||
private:
|
||||
MtStack* _stack; ///< 私有栈指针
|
||||
jmp_buf _jmpbuf; ///< 上下文jmpbuff
|
||||
int _stack_size; ///< 栈大小字段
|
||||
utime64_t _wakeup_time; ///< 睡眠唤醒时间
|
||||
MtStack* _stack;
|
||||
jmp_buf _jmpbuf;
|
||||
int _stack_size;
|
||||
utime64_t _wakeup_time;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief 微线程数据结构定义
|
||||
*/
|
||||
class MicroThread : public Thread
|
||||
{
|
||||
public:
|
||||
enum ThreadType
|
||||
{
|
||||
NORMAL = 0, ///< 默认普通线程, 没有动态申请的栈信息
|
||||
PRIMORDIAL = 1, ///< 原生线程, main函数开启
|
||||
DAEMON = 2, ///< 守护线程, 底层IO EPOLL管理与调度触发
|
||||
SUB_THREAD = 3, ///< 二级线程, 仅执行简单工作
|
||||
NORMAL = 0, ///< normal thread, no dynamic allocated stack infomations.
|
||||
PRIMORDIAL = 1, ///< primordial thread, created when frame initialized.
|
||||
DAEMON = 2, ///< daemon thread, IO event management and scheduling trigger.
|
||||
SUB_THREAD = 3, ///< sub thread, run simple task.
|
||||
};
|
||||
|
||||
enum ThreadFlag
|
||||
{
|
||||
NOT_INLIST = 0x0, ///< 无队列状态
|
||||
FREE_LIST = 0x1, ///< 空闲队列中
|
||||
IO_LIST = 0x2, ///< IO等待队列中
|
||||
SLEEP_LIST = 0x4, ///< 主动SLEEP中
|
||||
RUN_LIST = 0x8, ///< 可运行队列中
|
||||
PEND_LIST = 0x10, ///< 阻塞队列中
|
||||
SUB_LIST = 0x20, ///< 二级线程队列中
|
||||
NOT_INLIST = 0x0,
|
||||
FREE_LIST = 0x1,
|
||||
IO_LIST = 0x2,
|
||||
SLEEP_LIST = 0x4,
|
||||
RUN_LIST = 0x8,
|
||||
PEND_LIST = 0x10,
|
||||
SUB_LIST = 0x20,
|
||||
|
||||
};
|
||||
|
||||
enum ThreadState
|
||||
{
|
||||
INITIAL = 0, ///< 初始化状态
|
||||
RUNABLE = 1, ///< 可运行状态
|
||||
RUNNING = 2, ///< 正在运行中
|
||||
SLEEPING = 3, ///< IO等待或SLEEP中
|
||||
PENDING = 4, ///< 阻塞状态中, 等待子线程OK等
|
||||
INITIAL = 0,
|
||||
RUNABLE = 1,
|
||||
RUNNING = 2,
|
||||
SLEEPING = 3,
|
||||
PENDING = 4,
|
||||
};
|
||||
|
||||
typedef TAILQ_ENTRY(MicroThread) ThreadLink; ///< 微线程链接
|
||||
typedef TAILQ_HEAD(__ThreadSubTailq, MicroThread) SubThreadList; ///< 微线程队列定义
|
||||
typedef TAILQ_ENTRY(MicroThread) ThreadLink;
|
||||
typedef TAILQ_HEAD(__ThreadSubTailq, MicroThread) SubThreadList;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief 微线程构造与析构
|
||||
*/
|
||||
MicroThread(ThreadType type = NORMAL);
|
||||
~MicroThread(){};
|
||||
|
||||
ThreadLink _entry; ///< 状态队列入口
|
||||
ThreadLink _sub_entry; ///< 子线程队列入口
|
||||
ThreadLink _entry;
|
||||
ThreadLink _sub_entry;
|
||||
|
||||
/**
|
||||
* @brief 微线程堆排序函数实现,按唤醒时间从早到晚排序
|
||||
* @return 线程的实际唤醒时间
|
||||
*/
|
||||
virtual utime64_t HeapValue() {
|
||||
return GetWakeupTime();
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 线程的实际工作函数
|
||||
*/
|
||||
virtual void Run(void);
|
||||
|
||||
/**
|
||||
* @breif fd侦听管理对列操作
|
||||
*/
|
||||
|
||||
void ClearAllFd(void) {
|
||||
TAILQ_INIT(&_fdset);
|
||||
};
|
||||
|
@ -330,9 +220,6 @@ public:
|
|||
return _fdset;
|
||||
};
|
||||
|
||||
/**
|
||||
* @breif 微线程类型管理操作
|
||||
*/
|
||||
void SetType(ThreadType type) {
|
||||
_type = type;
|
||||
};
|
||||
|
@ -340,9 +227,6 @@ public:
|
|||
return _type;
|
||||
};
|
||||
|
||||
/**
|
||||
* @breif 微线程类型检查接口
|
||||
*/
|
||||
bool IsDaemon(void) {
|
||||
return (DAEMON == _type);
|
||||
};
|
||||
|
@ -353,9 +237,6 @@ public:
|
|||
return (SUB_THREAD == _type);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 父线程设置与更新
|
||||
*/
|
||||
void SetParent(MicroThread* parent) {
|
||||
_parent = parent;
|
||||
};
|
||||
|
@ -364,16 +245,10 @@ public:
|
|||
};
|
||||
void WakeupParent();
|
||||
|
||||
/**
|
||||
* @brief 子线程的管理
|
||||
*/
|
||||
void AddSubThread(MicroThread* sub);
|
||||
void RemoveSubThread(MicroThread* sub);
|
||||
bool HasNoSubThread();
|
||||
|
||||
/**
|
||||
* @brief 微线程类型状态操作
|
||||
*/
|
||||
void SetState(ThreadState state) {
|
||||
_state = state;
|
||||
};
|
||||
|
@ -381,25 +256,19 @@ public:
|
|||
return _state;
|
||||
}
|
||||
|
||||
/**
|
||||
* @breif 微线程标记位处理
|
||||
*/
|
||||
void SetFlag(ThreadFlag flag) {
|
||||
_flag = (ThreadFlag)(_flag | flag);
|
||||
_flag = (ThreadFlag)(_flag | flag);
|
||||
};
|
||||
void UnsetFlag(ThreadFlag flag) {
|
||||
_flag = (ThreadFlag)(_flag & ~flag);
|
||||
};
|
||||
bool HasFlag(ThreadFlag flag) {
|
||||
return _flag & flag;
|
||||
return _flag & flag;
|
||||
};
|
||||
ThreadFlag GetFlag() {
|
||||
return _flag;
|
||||
};
|
||||
|
||||
/**
|
||||
* @breif 微线程入口函数管理注册
|
||||
*/
|
||||
void SetSartFunc(ThreadStart func, void* args) {
|
||||
_start = func;
|
||||
_args = args;
|
||||
|
@ -411,464 +280,217 @@ public:
|
|||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* @breif 微线程复用状态清理
|
||||
*/
|
||||
virtual void CleanState(void);
|
||||
|
||||
private:
|
||||
ThreadState _state; ///< 微线程当前状态
|
||||
ThreadType _type; ///< 微线程类型
|
||||
ThreadFlag _flag; ///< 微线程标记位
|
||||
KqObjList _fdset; ///< 微线程关注的socket列表
|
||||
SubThreadList _sub_list; ///< 二级线程的队列
|
||||
MicroThread* _parent; ///< 二级线程的父线程
|
||||
ThreadStart _start; ///< 微线程注册函数
|
||||
void* _args; ///< 微线程注册参数
|
||||
ThreadState _state;
|
||||
ThreadType _type;
|
||||
ThreadFlag _flag;
|
||||
KqObjList _fdset;
|
||||
SubThreadList _sub_list;
|
||||
MicroThread* _parent;
|
||||
ThreadStart _start;
|
||||
void* _args;
|
||||
|
||||
};
|
||||
typedef std::set<MicroThread*> ThreadSet; ///< 微线程set管理结构
|
||||
typedef std::queue<MicroThread*> ThreadList; ///< 微线程queue管理结构
|
||||
typedef std::set<MicroThread*> ThreadSet;
|
||||
typedef std::queue<MicroThread*> ThreadList;
|
||||
|
||||
|
||||
/**
|
||||
* @brief 微线程日志接口, 底层库, 日志由调用者注入
|
||||
*/
|
||||
class LogAdapter
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief 日志构造与析构
|
||||
*/
|
||||
LogAdapter(){};
|
||||
virtual ~LogAdapter(){};
|
||||
|
||||
/**
|
||||
* @brief 日志优先按等级过滤, 减少解析参数的开销
|
||||
* @return true 可以打印该级别, false 跳过不打印该级别
|
||||
*/
|
||||
virtual bool CheckDebug(){ return true;};
|
||||
virtual bool CheckTrace(){ return true;};
|
||||
virtual bool CheckError(){ return true;};
|
||||
|
||||
/**
|
||||
* @brief 日志分级记录接口
|
||||
*/
|
||||
virtual void LogDebug(char* fmt, ...){};
|
||||
virtual void LogTrace(char* fmt, ...){};
|
||||
virtual void LogError(char* fmt, ...){};
|
||||
|
||||
/**
|
||||
* @brief 属性上报接口
|
||||
*/
|
||||
virtual void AttrReportAdd(int attr, int iValue){};
|
||||
virtual void AttrReportSet(int attr, int iValue){};
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief 微线程池简单实现
|
||||
*/
|
||||
class ThreadPool
|
||||
{
|
||||
public:
|
||||
|
||||
static unsigned int default_thread_num; ///< 默认2000微线程待命
|
||||
static unsigned int default_stack_size; ///< 默认128K栈大小
|
||||
static unsigned int default_thread_num;
|
||||
static unsigned int default_stack_size;
|
||||
|
||||
/**
|
||||
* @brief 设置微线程的最小保留数目
|
||||
*/
|
||||
static void SetDefaultThreadNum(unsigned int num) {
|
||||
default_thread_num = num;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 设置微线程的默认栈大小, 需初始化前设置
|
||||
*/
|
||||
static void SetDefaultStackSize(unsigned int size) {
|
||||
default_stack_size = (size + MEM_PAGE_SIZE - 1) / MEM_PAGE_SIZE * MEM_PAGE_SIZE;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 微线程池初始化
|
||||
*/
|
||||
bool InitialPool(int max_num);
|
||||
|
||||
/**
|
||||
* @brief 微线程池反初始化
|
||||
*/
|
||||
void DestroyPool (void);
|
||||
|
||||
/**
|
||||
* @brief 微线程分配接口
|
||||
* @return 微线程对象
|
||||
*/
|
||||
MicroThread* AllocThread(void);
|
||||
|
||||
/**
|
||||
* @brief 微线程释放接口
|
||||
* @param thread 微线程对象
|
||||
*/
|
||||
void FreeThread(MicroThread* thread);
|
||||
|
||||
/**
|
||||
* @brief 获取当前微线程数量
|
||||
* @param thread 微线程对象
|
||||
*/
|
||||
int GetUsedNum(void);
|
||||
|
||||
private:
|
||||
ThreadList _freelist; ///< 空闲待命的微线程队列
|
||||
int _total_num; ///< 目前总的微线程数目,后续按需控制上限
|
||||
int _use_num; ///< 当前正在使用的微线程数目
|
||||
int _max_num; ///< 最大并发限制数, 放置内存过度使用
|
||||
ThreadList _freelist;
|
||||
int _total_num;
|
||||
int _use_num;
|
||||
int _max_num;
|
||||
};
|
||||
|
||||
typedef TAILQ_HEAD(__ThreadTailq, MicroThread) ThreadTailq; ///< 微线程队列定义
|
||||
typedef TAILQ_HEAD(__ThreadTailq, MicroThread) ThreadTailq;
|
||||
|
||||
/**
|
||||
* @brief 微线程框架类, 全局的单例类
|
||||
*/
|
||||
class MtFrame : public KqueueProxy, public ThreadPool
|
||||
{
|
||||
private:
|
||||
static MtFrame* _instance; ///< 单例指针
|
||||
LogAdapter* _log_adpt; ///< 日志接口
|
||||
ThreadList _runlist; ///< 可运行queue, 无优先级
|
||||
ThreadTailq _iolist; ///< 等待队列,可随机脱离队列
|
||||
ThreadTailq _pend_list; ///< 等待队列,可随机脱离队列
|
||||
HeapList _sleeplist; ///< 等待超时的堆, 可随机脱离, 且随时获取最小堆首
|
||||
MicroThread* _daemon; ///< 守护线程, 执行epoll wait, 超时检测
|
||||
MicroThread* _primo; ///< 原生线程, 使用的是原生堆栈
|
||||
MicroThread* _curr_thread; ///< 当前运行线程
|
||||
utime64_t _last_clock; ///< 全局时间戳, 每次idle获取一次
|
||||
int _waitnum; ///< 等待运行的总线程数, 可调节调度的节奏
|
||||
CTimerMng* _timer; ///< TCP保活专用的timer定时器
|
||||
int _realtime; /// < 使用实时时间0, 未设置
|
||||
static MtFrame* _instance;
|
||||
LogAdapter* _log_adpt;
|
||||
ThreadList _runlist;
|
||||
ThreadTailq _iolist;
|
||||
ThreadTailq _pend_list;
|
||||
HeapList _sleeplist;
|
||||
MicroThread* _daemon;
|
||||
MicroThread* _primo;
|
||||
MicroThread* _curr_thread;
|
||||
utime64_t _last_clock;
|
||||
int _waitnum;
|
||||
CTimerMng* _timer;
|
||||
int _realtime;
|
||||
|
||||
public:
|
||||
friend class ScheduleObj; ///< 调度器对象, 是框架类的门面模式, 友元处理
|
||||
|
||||
friend class ScheduleObj;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief 微线程框架类, 全局实例获取
|
||||
*/
|
||||
static MtFrame* Instance (void);
|
||||
|
||||
/**
|
||||
* @brief 微线程包裹的系统IO函数 sendto
|
||||
* @param fd 系统socket信息
|
||||
* @param msg 待发送的消息指针
|
||||
* @param len 待发送的消息长度
|
||||
* @param to 目的地址的指针
|
||||
* @param tolen 目的地址的结构长度
|
||||
* @param timeout 最长等待时间, 毫秒
|
||||
* @return >0 成功发送长度, <0 失败
|
||||
*/
|
||||
|
||||
static int sendto(int fd, const void *msg, int len, int flags, const struct sockaddr *to, int tolen, int timeout);
|
||||
|
||||
/**
|
||||
* @brief 微线程包裹的系统IO函数 recvfrom
|
||||
* @param fd 系统socket信息
|
||||
* @param buf 接收消息缓冲区指针
|
||||
* @param len 接收消息缓冲区长度
|
||||
* @param from 来源地址的指针
|
||||
* @param fromlen 来源地址的结构长度
|
||||
* @param timeout 最长等待时间, 毫秒
|
||||
* @return >0 成功接收长度, <0 失败
|
||||
*/
|
||||
static int recvfrom(int fd, void *buf, int len, int flags, struct sockaddr *from, socklen_t *fromlen, int timeout);
|
||||
|
||||
/**
|
||||
* @brief 微线程包裹的系统IO函数 connect
|
||||
* @param fd 系统socket信息
|
||||
* @param addr 指定server的目的地址
|
||||
* @param addrlen 地址的长度
|
||||
* @param timeout 最长等待时间, 毫秒
|
||||
* @return >0 成功发送长度, <0 失败
|
||||
*/
|
||||
static int connect(int fd, const struct sockaddr *addr, int addrlen, int timeout);
|
||||
|
||||
/**
|
||||
* @brief 微线程包裹的系统IO函数 accept
|
||||
* @param fd 监听套接字
|
||||
* @param addr 客户端地址
|
||||
* @param addrlen 地址的长度
|
||||
* @param timeout 最长等待时间, 毫秒
|
||||
* @return >=0 accept的socket描述符, <0 失败
|
||||
*/
|
||||
static int accept(int fd, struct sockaddr *addr, socklen_t *addrlen, int timeout);
|
||||
|
||||
/**
|
||||
* @brief 微线程包裹的系统IO函数 read
|
||||
* @param fd 系统socket信息
|
||||
* @param buf 接收消息缓冲区指针
|
||||
* @param nbyte 接收消息缓冲区长度
|
||||
* @param timeout 最长等待时间, 毫秒
|
||||
* @return >0 成功接收长度, <0 失败
|
||||
*/
|
||||
static ssize_t read(int fd, void *buf, size_t nbyte, int timeout);
|
||||
|
||||
/**
|
||||
* @brief 微线程包裹的系统IO函数 write
|
||||
* @param fd 系统socket信息
|
||||
* @param buf 发送消息缓冲区指针
|
||||
* @param nbyte 发送消息缓冲区长度
|
||||
* @param timeout 最长等待时间, 毫秒
|
||||
* @return >0 成功发送长度, <0 失败
|
||||
*/
|
||||
static ssize_t write(int fd, const void *buf, size_t nbyte, int timeout);
|
||||
|
||||
/**
|
||||
* @brief 微线程包裹的系统IO函数 recv
|
||||
* @param fd 系统socket信息
|
||||
* @param buf 接收消息缓冲区指针
|
||||
* @param len 接收消息缓冲区长度
|
||||
* @param timeout 最长等待时间, 毫秒
|
||||
* @return >0 成功接收长度, <0 失败
|
||||
*/
|
||||
static int recv(int fd, void *buf, int len, int flags, int timeout);
|
||||
|
||||
/**
|
||||
* @brief 微线程包裹的系统IO函数 send
|
||||
* @param fd 系统socket信息
|
||||
* @param buf 待发送的消息指针
|
||||
* @param nbyte 待发送的消息长度
|
||||
* @param timeout 最长等待时间, 毫秒
|
||||
* @return >0 成功发送长度, <0 失败
|
||||
*/
|
||||
static ssize_t send(int fd, const void *buf, size_t nbyte, int flags, int timeout);
|
||||
|
||||
|
||||
/**
|
||||
* @brief 微线程主动sleep接口, 单位ms
|
||||
*/
|
||||
static void sleep(int ms);
|
||||
|
||||
/**
|
||||
* @brief 微线程仅等待事件,不做额外的操作
|
||||
* @param fd 系统socket信息
|
||||
* @param events 事件类型 EPOLLIN or EPOLLOUT
|
||||
* @param timeout 最长等待时间, 毫秒
|
||||
* @return >0 成功接收长度, <0 失败
|
||||
*/
|
||||
static int WaitEvents(int fd, int events, int timeout);
|
||||
|
||||
/**
|
||||
* @brief 微线程创建接口
|
||||
* @param entry 线程入口函数
|
||||
* @param args 线程入口参数
|
||||
* @return 微线程指针, NULL表示失败
|
||||
*/
|
||||
static MicroThread* CreateThread(ThreadStart entry, void *args, bool runable = true);
|
||||
|
||||
/**
|
||||
* @brief 守护线程入口函数, 函数指针要求static类型
|
||||
* @param args 线程入口参数
|
||||
*/
|
||||
static void DaemonRun(void* args);
|
||||
static int Loop(void* args);
|
||||
static int Loop(void* args);
|
||||
|
||||
/**
|
||||
* @brief 获取当前线程的根线程
|
||||
*/
|
||||
MicroThread *GetRootThread();
|
||||
|
||||
/**
|
||||
* @brief 框架初始化, 默认不带日志运行
|
||||
*/
|
||||
bool InitFrame(LogAdapter* logadpt = NULL, int max_thread_num = 50000);
|
||||
|
||||
/**
|
||||
* @brief HOOK系统api的设置
|
||||
*/
|
||||
void SetHookFlag();
|
||||
|
||||
/**
|
||||
* @brief 框架反初始化
|
||||
*/
|
||||
void Destroy (void);
|
||||
|
||||
/**
|
||||
* @brief 微线程框架版本获取
|
||||
*/
|
||||
char* Version(void);
|
||||
|
||||
/**
|
||||
* @brief 框架获取全局时间戳
|
||||
*/
|
||||
utime64_t GetLastClock(void) {
|
||||
if(_realtime)
|
||||
{
|
||||
return GetSystemMS();
|
||||
}
|
||||
if(_realtime)
|
||||
{
|
||||
return GetSystemMS();
|
||||
}
|
||||
return _last_clock;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief 框架获取当前线程
|
||||
*/
|
||||
MicroThread* GetActiveThread(void) {
|
||||
return _curr_thread;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 返回当前待运行的线程数, 直接计数, 效率高
|
||||
* @return 等待线程数
|
||||
*/
|
||||
int RunWaitNum(void) {
|
||||
return _waitnum;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 框架被注入的日志句柄访问
|
||||
*/
|
||||
LogAdapter* GetLogAdpt(void) {
|
||||
return _log_adpt;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 获取框架保活定时器指针
|
||||
*/
|
||||
CTimerMng* GetTimerMng(void) {
|
||||
return _timer;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 框架调用epoll wait前, 判定等待时间信息
|
||||
*/
|
||||
virtual int KqueueGetTimeout(void);
|
||||
|
||||
/**
|
||||
* @brief 微线程触发切换函数,调用成功 则让出cpu, 内部接口
|
||||
* @param fdlist 多路并发的socket列表
|
||||
* @param fd 单个请求的fd信息
|
||||
* @param timeout 最长等待时间, 毫秒
|
||||
* @return true 成功, false 失败
|
||||
*/
|
||||
virtual bool KqueueSchedule(KqObjList* fdlist, KqueuerObj* fd, int timeout);
|
||||
|
||||
|
||||
/**
|
||||
* @brief 微线程主动切换, 等待其它线程的唤醒
|
||||
* @param timeout 最长等待时间, 毫秒
|
||||
*/
|
||||
void WaitNotify(utime64_t timeout);
|
||||
|
||||
/**
|
||||
* @brief 框架管理线程单元, 移除IO等待状态, 内部接口
|
||||
* @param thread 微线程对象
|
||||
*/
|
||||
void RemoveIoWait(MicroThread* thread);
|
||||
|
||||
/**
|
||||
* @brief 框架管理线程单元, 插入可运行队列, 内部接口
|
||||
* @param thread 微线程对象
|
||||
*/
|
||||
void InsertRunable(MicroThread* thread);
|
||||
|
||||
/**
|
||||
* @brief 框架管理线程单元, 执行pend等待状态
|
||||
* @param thread 微线程对象
|
||||
*/
|
||||
void InsertPend(MicroThread* thread);
|
||||
|
||||
/**
|
||||
* @brief 框架管理线程单元, 移除PEND等待状态
|
||||
* @param thread 微线程对象
|
||||
*/
|
||||
|
||||
void RemovePend(MicroThread* thread);
|
||||
|
||||
void SetRealTime(int realtime_)
|
||||
{
|
||||
_realtime =realtime_;
|
||||
}
|
||||
void SetRealTime(int realtime_)
|
||||
{
|
||||
_realtime =realtime_;
|
||||
}
|
||||
private:
|
||||
|
||||
/**
|
||||
* @brief 微线程私有构造
|
||||
*/
|
||||
MtFrame():_realtime(1){ _curr_thread = NULL; };
|
||||
|
||||
/**
|
||||
* @brief 微线程私有获取守护线程
|
||||
*/
|
||||
MicroThread* DaemonThread(void){
|
||||
return _daemon;
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 框架调度线程运行
|
||||
*/
|
||||
void ThreadSchdule(void);
|
||||
|
||||
/**
|
||||
* @brief 框架处理定时回调函数
|
||||
*/
|
||||
void CheckExpired();
|
||||
|
||||
/**
|
||||
* @brief 框架检测到超时, 唤醒所有的超时线程
|
||||
*/
|
||||
void WakeupTimeout(void);
|
||||
|
||||
/**
|
||||
* @brief 框架更新全局时间戳
|
||||
*/
|
||||
void SetLastClock(utime64_t clock) {
|
||||
_last_clock = clock;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 框架设置当前线程
|
||||
*/
|
||||
void SetActiveThread(MicroThread* thread) {
|
||||
_curr_thread = thread;
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 框架的时钟源接口, 返回毫秒级别时钟
|
||||
*/
|
||||
utime64_t GetSystemMS(void) {
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
return (tv.tv_sec * 1000ULL + tv.tv_usec / 1000ULL);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 框架管理线程单元, 执行IO等待状态
|
||||
* @param thread 微线程对象
|
||||
*/
|
||||
void InsertSleep(MicroThread* thread);
|
||||
|
||||
/**
|
||||
* @brief 框架管理线程单元, 移除IO等待状态
|
||||
* @param thread 微线程对象
|
||||
*/
|
||||
void RemoveSleep(MicroThread* thread);
|
||||
|
||||
/**
|
||||
* @brief 框架管理线程单元, 执行IO等待状态
|
||||
* @param thread 微线程对象
|
||||
*/
|
||||
void InsertIoWait(MicroThread* thread);
|
||||
|
||||
/**
|
||||
* @brief 框架管理线程单元, 移出可运行队列
|
||||
* @param thread 微线程对象
|
||||
*/
|
||||
void RemoveRunable(MicroThread* thread);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 日志宏的定义部分
|
||||
*/
|
||||
#define MTLOG_DEBUG(fmt, args...) \
|
||||
do { \
|
||||
register NS_MICRO_THREAD::MtFrame *fm = NS_MICRO_THREAD::MtFrame::Instance(); \
|
||||
|
@ -909,13 +531,13 @@ do { \
|
|||
} while (0)
|
||||
|
||||
#define MT_ATTR_API_SET(ATTR, VALUE) \
|
||||
do { \
|
||||
register NS_MICRO_THREAD::MtFrame *fm = NS_MICRO_THREAD::MtFrame::Instance(); \
|
||||
if (fm && fm->GetLogAdpt()) \
|
||||
{ \
|
||||
fm->GetLogAdpt()->AttrReportSet(ATTR, VALUE); \
|
||||
} \
|
||||
} while (0)
|
||||
do { \
|
||||
register NS_MICRO_THREAD::MtFrame *fm = NS_MICRO_THREAD::MtFrame::Instance(); \
|
||||
if (fm && fm->GetLogAdpt()) \
|
||||
{ \
|
||||
fm->GetLogAdpt()->AttrReportSet(ATTR, VALUE); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -17,12 +17,6 @@
|
|||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @file mt_action.cpp
|
||||
* @info 微线程ACTION基类实现
|
||||
* @time 20130924
|
||||
**/
|
||||
|
||||
#include "micro_thread.h"
|
||||
#include "mt_notify.h"
|
||||
#include "mt_connection.h"
|
||||
|
@ -32,10 +26,6 @@
|
|||
using namespace std;
|
||||
using namespace NS_MICRO_THREAD;
|
||||
|
||||
|
||||
/**
|
||||
* @brief 初始item状态
|
||||
*/
|
||||
void IMtAction::Init()
|
||||
{
|
||||
_flag = MULTI_FLAG_UNDEF;
|
||||
|
@ -50,12 +40,8 @@ void IMtAction::Init()
|
|||
memset(&_addr, 0, sizeof(_addr));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 允许复用, 清理item状态
|
||||
*/
|
||||
void IMtAction::Reset()
|
||||
{
|
||||
// 长连接, 处理成功才复用, 否则强制关闭
|
||||
bool force_free = false;
|
||||
if (_errno != ERR_NONE) {
|
||||
force_free = true;
|
||||
|
@ -67,9 +53,6 @@ void IMtAction::Reset()
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 获取连接对象, 通知对象, 消息对象
|
||||
*/
|
||||
KqueuerObj* IMtAction::GetNtfyObj() {
|
||||
IMtConnection* conn = GetIConnection();
|
||||
if (conn) {
|
||||
|
@ -79,10 +62,6 @@ KqueuerObj* IMtAction::GetNtfyObj() {
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief 后端连接环境初始化
|
||||
*/
|
||||
int IMtAction::InitConnEnv()
|
||||
{
|
||||
MtFrame* mtframe = MtFrame::Instance();
|
||||
|
@ -96,23 +75,22 @@ int IMtAction::InitConnEnv()
|
|||
return -100;
|
||||
}
|
||||
|
||||
// 1. 分类获取conn句柄
|
||||
CONN_OBJ_TYPE conn_obj_type = OBJ_CONN_UNDEF;
|
||||
NTFY_OBJ_TYPE ntfy_obj_type = NTFY_OBJ_UNDEF;
|
||||
|
||||
MULTI_PROTO proto = this->GetProtoType();
|
||||
MULTI_CONNECT type = this->GetConnType();
|
||||
if ((MT_UDP == proto) && (CONN_TYPE_SESSION == type)) // UDP session模式
|
||||
if ((MT_UDP == proto) && (CONN_TYPE_SESSION == type)) // UDP session
|
||||
{
|
||||
conn_obj_type = OBJ_UDP_SESSION;
|
||||
ntfy_obj_type = NTFY_OBJ_SESSION;
|
||||
}
|
||||
else if (MT_UDP == proto) // UDP 其它模式
|
||||
else if (MT_UDP == proto) // UDP
|
||||
{
|
||||
conn_obj_type = OBJ_SHORT_CONN;
|
||||
ntfy_obj_type = NTFY_OBJ_THREAD;
|
||||
}
|
||||
else // TCP 模式
|
||||
else // TCP
|
||||
{
|
||||
conn_obj_type = OBJ_TCP_KEEP;
|
||||
ntfy_obj_type = NTFY_OBJ_THREAD;
|
||||
|
@ -125,7 +103,6 @@ int IMtAction::InitConnEnv()
|
|||
}
|
||||
_conn->SetIMtActon(this);
|
||||
|
||||
// 2. 获取msg buff句柄
|
||||
int max_len = this->GetMsgBuffSize();
|
||||
MtMsgBuf* msg_buff = msgmgr->GetMsgBuf(max_len);
|
||||
if (!msg_buff) {
|
||||
|
@ -135,7 +112,6 @@ int IMtAction::InitConnEnv()
|
|||
msg_buff->SetBuffType(BUFF_SEND);
|
||||
_conn->SetMtMsgBuff(msg_buff);
|
||||
|
||||
// 3. 获取 ntfy 对象句柄
|
||||
KqueuerObj* ntfy_obj = ntfymgr->GetNtfyObj(ntfy_obj_type, _ntfy_name);
|
||||
if (!ntfy_obj) {
|
||||
MTLOG_ERROR("Maybe no memory, ntfy type: %d, get failed", ntfy_obj_type);
|
||||
|
@ -143,7 +119,6 @@ int IMtAction::InitConnEnv()
|
|||
}
|
||||
_conn->SetNtfyObj(ntfy_obj);
|
||||
|
||||
// 4. SESSION模型, 建立session
|
||||
MicroThread* thread = mtframe->GetActiveThread();
|
||||
ntfy_obj->SetOwnerThread(thread);
|
||||
this->SetIMsgPtr((IMtMsg*)thread->GetThreadArgs());
|
||||
|
@ -158,10 +133,6 @@ int IMtAction::InitConnEnv()
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 代理虚函数, 简化接口与实现部分
|
||||
*/
|
||||
int IMtAction::DoEncode()
|
||||
{
|
||||
MtMsgBuf* msg_buff = NULL;
|
||||
|
@ -185,9 +156,6 @@ int IMtAction::DoEncode()
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 代理虚函数, 简化接口与实现部分
|
||||
*/
|
||||
int IMtAction::DoInput()
|
||||
{
|
||||
MtMsgBuf* msg_buff = NULL;
|
||||
|
@ -210,7 +178,6 @@ int IMtAction::DoInput()
|
|||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int IMtAction::DoProcess()
|
||||
{
|
||||
MtMsgBuf* msg_buff = NULL;
|
||||
|
@ -238,15 +205,11 @@ int IMtAction::DoError()
|
|||
return this->HandleError((int)_errno, _msg);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief 构造与析构处理
|
||||
*/
|
||||
IMtAction::IMtAction()
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
IMtAction::~IMtAction()
|
||||
{
|
||||
Reset();
|
||||
|
|
|
@ -16,12 +16,6 @@
|
|||
* and limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @file mt_action.h
|
||||
* @info 微线程ACTION基类定义
|
||||
**/
|
||||
|
||||
#ifndef __MT_ACTION_H__
|
||||
#define __MT_ACTION_H__
|
||||
|
||||
|
@ -34,244 +28,136 @@
|
|||
namespace NS_MICRO_THREAD {
|
||||
|
||||
|
||||
/**
|
||||
* @brief 并发处理状态标记定义
|
||||
*/
|
||||
enum MULTI_STATE
|
||||
{
|
||||
MULTI_FLAG_UNDEF = 0x0, ///< 初始化, 未启动
|
||||
MULTI_FLAG_INIT = 0x1, ///< socket创建已成功
|
||||
MULTI_FLAG_OPEN = 0x2, ///< socket连接已打开
|
||||
MULTI_FLAG_SEND = 0x4, ///< 请求报文已经发送
|
||||
MULTI_FLAG_FIN = 0x8, ///< 应答报文已经接收到
|
||||
MULTI_FLAG_UNDEF = 0x0,
|
||||
MULTI_FLAG_INIT = 0x1,
|
||||
MULTI_FLAG_OPEN = 0x2,
|
||||
MULTI_FLAG_SEND = 0x4,
|
||||
MULTI_FLAG_FIN = 0x8,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 协议连接类型定义
|
||||
*/
|
||||
enum MULTI_CONNECT
|
||||
{
|
||||
CONN_UNKNOWN = 0,
|
||||
CONN_TYPE_SHORT = 0x1, ///< 短连接, 一次交互后关闭
|
||||
CONN_TYPE_LONG = 0x2, ///< 长连接,每次使用后, 可回收重复使用
|
||||
CONN_TYPE_SESSION = 0x4, ///< 长连接,按session id 复用, 防串包
|
||||
CONN_TYPE_SHORT = 0x1,
|
||||
CONN_TYPE_LONG = 0x2,
|
||||
CONN_TYPE_SESSION = 0x4,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 错误码定义
|
||||
*/
|
||||
enum MULTI_ERROR
|
||||
{
|
||||
ERR_NONE = 0,
|
||||
ERR_SOCKET_FAIL = -1, ///< 创建sock失败
|
||||
ERR_CONNECT_FAIL = -2, ///< 连接失败
|
||||
ERR_SEND_FAIL = -3, ///< 发送报文失败
|
||||
ERR_RECV_FAIL = -4, ///< 接收失败
|
||||
ERR_RECV_TIMEOUT = -5, ///< 接收超时
|
||||
ERR_KQUEUE_FAIL = -6, ///< epoll失败
|
||||
ERR_FRAME_ERROR = -7, ///< 框架失败
|
||||
ERR_PEER_CLOSE = -8, ///< 对方关闭
|
||||
ERR_PARAM_ERROR = -9, ///< 参数错误
|
||||
ERR_MEMORY_ERROR = -10, ///< 内存申请失败
|
||||
ERR_ENCODE_ERROR = -11, ///< 封包失败
|
||||
ERR_DST_ADDR_ERROR = -12, ///< 目标地址获取失败
|
||||
ERR_SOCKET_FAIL = -1,
|
||||
ERR_CONNECT_FAIL = -2,
|
||||
ERR_SEND_FAIL = -3,
|
||||
ERR_RECV_FAIL = -4,
|
||||
ERR_RECV_TIMEOUT = -5,
|
||||
ERR_KQUEUE_FAIL = -6,
|
||||
ERR_FRAME_ERROR = -7,
|
||||
ERR_PEER_CLOSE = -8,
|
||||
ERR_PARAM_ERROR = -9,
|
||||
ERR_MEMORY_ERROR = -10,
|
||||
ERR_ENCODE_ERROR = -11,
|
||||
ERR_DST_ADDR_ERROR = -12,
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief 微线程的后端交互抽象基类
|
||||
*/
|
||||
class IMtAction : public ISession
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief 微线程并发行为基类
|
||||
*/
|
||||
IMtAction();
|
||||
virtual ~IMtAction();
|
||||
|
||||
/**
|
||||
* @brief 设置请求报文信息 (保证接口最大灵活兼容, 不使用inline)
|
||||
* @param dst -请求包待发送的地址
|
||||
*/
|
||||
void SetMsgDstAddr(struct sockaddr_in* dst) {
|
||||
void SetMsgDstAddr(struct sockaddr_in* dst) {
|
||||
memcpy(&_addr, dst, sizeof(_addr));
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 获取消息目的地址信息
|
||||
* @return 注册的目的地址
|
||||
*/
|
||||
struct sockaddr_in* GetMsgDstAddr() {
|
||||
return &_addr;
|
||||
};
|
||||
};
|
||||
|
||||
struct sockaddr_in* GetMsgDstAddr() {
|
||||
return &_addr;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 设置buff大小, 决定实际使用的msgbuff队列
|
||||
* @return 0成功
|
||||
*/
|
||||
void SetMsgBuffSize(int buff_size) {
|
||||
_buff_size = buff_size;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 获取预置的buff大小
|
||||
* @return 框架申请的消息buff最大长度
|
||||
*/
|
||||
int GetMsgBuffSize() {
|
||||
return (_buff_size > 0) ? _buff_size : 65535;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 设置长连接session的名字id
|
||||
* @return 0成功
|
||||
*/
|
||||
void SetSessionName(int name) {
|
||||
_ntfy_name = name;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 获取连接session的名字id
|
||||
* @return session 注册名
|
||||
*/
|
||||
int GetSessionName() {
|
||||
return _ntfy_name;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 设置本次处理的proto信息
|
||||
*/
|
||||
void SetProtoType(MULTI_PROTO proto) {
|
||||
_proto = proto;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 获取本次处理的proto信息
|
||||
* @return proto type
|
||||
*/
|
||||
MULTI_PROTO GetProtoType() {
|
||||
return _proto;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 设置本次处理的连接类型信息
|
||||
*/
|
||||
void SetConnType(MULTI_CONNECT type) {
|
||||
_conn_type = type;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 获取本次处理的连接类型信息
|
||||
* @return conn type
|
||||
*/
|
||||
MULTI_CONNECT GetConnType() {
|
||||
return _conn_type;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 设置本次处理的errno
|
||||
*/
|
||||
void SetErrno(MULTI_ERROR err) {
|
||||
_errno = err;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 获取本次处理的ERRNO信息
|
||||
* @return ERRONO
|
||||
*/
|
||||
MULTI_ERROR GetErrno() {
|
||||
return _errno;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 设置本次处理的timecost
|
||||
*/
|
||||
void SetCost(int cost) {
|
||||
_time_cost = cost;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 获取本次处理的timecost信息
|
||||
* @return timecost
|
||||
*/
|
||||
int GetCost() {
|
||||
return _time_cost;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 设置处理状态信息
|
||||
* @param flag -消息处理状态
|
||||
*/
|
||||
void SetMsgFlag(MULTI_STATE flag) {
|
||||
void SetMsgFlag(MULTI_STATE flag) {
|
||||
_flag = flag;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 获取处理状态信息
|
||||
* @return flag -消息处理状态
|
||||
*/
|
||||
};
|
||||
|
||||
MULTI_STATE GetMsgFlag() {
|
||||
return _flag;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 设置内部消息指针
|
||||
* @return IMtConn指针
|
||||
*/
|
||||
void SetIMsgPtr(IMtMsg* msg ) {
|
||||
_msg = msg;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 获取内部消息指针
|
||||
* @return IMtConn指针
|
||||
*/
|
||||
IMtMsg* GetIMsgPtr() {
|
||||
return _msg;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 设置内部连接器指针
|
||||
* @return IMtConn指针
|
||||
*/
|
||||
|
||||
void SetIConnection(IMtConnection* conn) {
|
||||
_conn = conn;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 获取内部连接器指针
|
||||
* @return IMtConn指针
|
||||
*/
|
||||
IMtConnection* GetIConnection() {
|
||||
return _conn;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 初始化必要字段信息
|
||||
*/
|
||||
void Init();
|
||||
|
||||
/**
|
||||
* @brief 允许复用, 清理Action状态
|
||||
*/
|
||||
void Reset();
|
||||
|
||||
/**
|
||||
* @brief 获取连接对象, 通知对象, 消息对象
|
||||
*/
|
||||
KqueuerObj* GetNtfyObj();
|
||||
|
||||
/**
|
||||
* @brief 获取连接对象, 通知对象, 消息对象
|
||||
*/
|
||||
int InitConnEnv();
|
||||
|
||||
/**
|
||||
* @brief 代理虚函数, 简化接口与实现部分
|
||||
*/
|
||||
int DoEncode();
|
||||
int DoInput();
|
||||
int DoProcess();
|
||||
|
@ -279,46 +165,28 @@ public:
|
|||
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief 本次连接的消息打包接口
|
||||
* @return >0 -成功, < 0 失败
|
||||
*/
|
||||
virtual int HandleEncode(void* buf, int& len, IMtMsg* msg){return 0;};
|
||||
|
||||
/**
|
||||
* @brief 本次连接的CHECK接口, TCP的分包接口
|
||||
* @return > 0 已经成功接收,返回完整包大小, =0 继续等待, <0 出错(其中-65535 UDP串包)
|
||||
*/
|
||||
virtual int HandleInput(void* buf, int len, IMtMsg* msg){return 0;};
|
||||
|
||||
/**
|
||||
* @brief 本次连接的应答处理接口, 接收一个完整分段包后调用
|
||||
* @return 0 成功, 其他失败
|
||||
*/
|
||||
virtual int HandleProcess(void* buf, int len, IMtMsg* msg){return 0;};
|
||||
|
||||
/**
|
||||
* @brief 本次连接处理的错误通知, 定义参见 MULTI_ERROR 枚举
|
||||
* @info 除handleprocess失败, 其它异常都调用该接口
|
||||
* @return 0 成功, 其他失败
|
||||
*/
|
||||
virtual int HandleError(int err, IMtMsg* msg){return 0;};
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
MULTI_STATE _flag; // 处理结束标记信息, 当前状态信息
|
||||
MULTI_PROTO _proto; // 协议类型 UDP/TCP
|
||||
MULTI_CONNECT _conn_type; // 连接类型 长短连接
|
||||
MULTI_ERROR _errno; // 错误码信息, 0成功其他错误
|
||||
struct sockaddr_in _addr; // 请求时填写,指定发送的stAddr
|
||||
int _time_cost; // 本次请求应答耗时, 毫秒
|
||||
int _buff_size; // 本次请求最大请求与应答长度
|
||||
int _ntfy_name; // 关联的session ntfy的名字, session模型适用
|
||||
|
||||
IMtMsg* _msg; // 消息指针, 上级指针
|
||||
IMtConnection* _conn; // 连接器指针, 下级指针, 管理生存期
|
||||
MULTI_STATE _flag;
|
||||
MULTI_PROTO _proto;
|
||||
MULTI_CONNECT _conn_type;
|
||||
MULTI_ERROR _errno;
|
||||
struct sockaddr_in _addr;
|
||||
int _time_cost;
|
||||
int _buff_size;
|
||||
int _ntfy_name;
|
||||
|
||||
IMtMsg* _msg;
|
||||
IMtConnection* _conn;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -19,7 +19,6 @@
|
|||
|
||||
/**
|
||||
* @filename mt_api.h
|
||||
* @info 微线程封装系统api, 同步调用微线程API,实现异步调度
|
||||
*/
|
||||
|
||||
#ifndef __MT_API_H__
|
||||
|
@ -32,377 +31,109 @@ using std::vector;
|
|||
|
||||
namespace NS_MICRO_THREAD {
|
||||
|
||||
/******************************************************************************/
|
||||
/* 微线程用户接口定义: UDP短连接收发接口 */
|
||||
/******************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief 采用随机端口的socket收发接口, 由socket来决定上下文, 业务来保证上下文
|
||||
* [注意] UDP发送buff, 不推荐static变量, 有一定风险导致上下文错乱[重要]
|
||||
* @param dst -请求发送的目的地址
|
||||
* @param pkg -请求包封装的包体
|
||||
* @param len -请求包封装的包体长度
|
||||
* @param rcv_buf -接收应答包的buff
|
||||
* @param buf_size -modify-接收应答包的buff大小, 成功返回时, 修改为应答包长度
|
||||
* @param timeout -超时时间, 单位ms
|
||||
* @return 0 成功, -1 打开socket失败, -2 发送请求失败, -3 接收应答失败, 可打印errno
|
||||
*/
|
||||
int mt_udpsendrcv(struct sockaddr_in* dst, void* pkg, int len, void* rcv_buf, int& buf_size, int timeout);
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
/* 微线程用户接口定义: TCP连接池收发接口 */
|
||||
/******************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief TCP检测报文是否接收完整的回调函数定义
|
||||
* @param buf 报文保存缓冲区
|
||||
* @param len 已经接收的长度
|
||||
* @return >0 实际的报文长度; 0 还需要等待接收; <0 报文异常
|
||||
*/
|
||||
typedef int (*MtFuncTcpMsgLen)(void* buf, int len);
|
||||
|
||||
/**
|
||||
* @brief TCP会采用连接池的方式复用IP/PORT连接, 连接保持默认10分钟
|
||||
* [注意] tcp接收发送buff, 不可以是static变量, 否则会上下文错乱 [重要]
|
||||
* @param dst -请求发送的目的地址
|
||||
* @param pkg -请求包封装的包体
|
||||
* @param len -请求包封装的包体长度
|
||||
* @param rcv_buf -接收应答包的buff
|
||||
* @param buf_size -modify-接收应答包的buff大小, 成功返回时, 修改为应答包长度
|
||||
* @param timeout -超时时间, 单位ms
|
||||
* @param check_func -检测报文是否成功到达函数
|
||||
* @return 0 成功, -1 打开socket失败, -2 发送请求失败, -3 接收应答失败,
|
||||
* -4 连接失败, -5 检测报文失败, -6 接收空间不够, -7 后端主动关闭连接,-10 参数无效
|
||||
*/
|
||||
int mt_tcpsendrcv(struct sockaddr_in* dst, void* pkg, int len, void* rcv_buf, int& buf_size,
|
||||
int timeout, MtFuncTcpMsgLen chek_func);
|
||||
|
||||
|
||||
enum MT_TCP_CONN_TYPE
|
||||
{
|
||||
MT_TCP_SHORT = 1, /// 短连接
|
||||
MT_TCP_LONG = 2, /// 长连接
|
||||
MT_TCP_SHORT_SNDONLY = 3, /// 短连接只发
|
||||
MT_TCP_LONG_SNDONLY = 4, /// 长连接只发
|
||||
MT_TCP_SHORT = 1,
|
||||
MT_TCP_LONG = 2,
|
||||
MT_TCP_SHORT_SNDONLY = 3,
|
||||
MT_TCP_LONG_SNDONLY = 4,
|
||||
MT_TCP_BUTT
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief TCP收发接口,可以选择后端保持连接或者短连接
|
||||
* [注意] tcp接收发送buff, 不可以是static变量, 否则会上下文错乱 [重要]
|
||||
* @param dst -请求发送的目的地址
|
||||
* @param pkg -请求包封装的包体
|
||||
* @param len -请求包封装的包体长度
|
||||
* @param rcv_buf -接收应答包的buff,只发不收可以设置为NULL
|
||||
* @param buf_size -modify-接收应答包的buff大小, 成功返回时, 修改为应答包长度,只发不收,设置为NULL
|
||||
* @param timeout -超时时间, 单位ms
|
||||
* @param check_func -检测报文是否成功到达函数
|
||||
* @param type - 连接类型
|
||||
* MT_TCP_SHORT: 一收一发短连接;
|
||||
* MT_TCP_LONG : 一发一收长连接;
|
||||
* MT_TCP_LONG_SNDONLY : 只发不收长连接;
|
||||
* MT_TCP_SHORT_SNDONLY: 只发不收短连接;
|
||||
* @return 0 成功, -1 打开socket失败, -2 发送请求失败, -3 接收应答失败,
|
||||
* -4 连接失败, -5 检测报文失败, -6 接收空间不够, -7 后端主动关闭连接, -10 参数无效
|
||||
*/
|
||||
int mt_tcpsendrcv_ex(struct sockaddr_in* dst, void* pkg, int len, void* rcv_buf, int* buf_size,
|
||||
int timeout, MtFuncTcpMsgLen func, MT_TCP_CONN_TYPE type = MT_TCP_LONG);
|
||||
|
||||
/**
|
||||
* @brief TCP检测报文是否接收完整的回调函数
|
||||
* @param buf 报文保存缓冲区
|
||||
* @param len 已经接收的长度
|
||||
* @param closed 远端关闭连接,兼容通过链接关闭来确定报文长度的业务
|
||||
* @param msg_ctx 解析报文的上下文变量。通过该值,业务可以实现报文解析状态机等,避免重复检查
|
||||
* 业务在mt_tcpsendrcv中传入该参数,框架回调时传递给业务。该变量可以为类或者结构体,业务自定义。
|
||||
* 报文解析结果,保存在变量中,mt_tcpsendrcv返回后,直接使用
|
||||
* 【注意】 该回调函数传入的buf指针可能变化,所以报文解析状态机相关位置信息请使用偏移量
|
||||
* @param msg_len_detected 传出参数 如果业务确定了报文长度,则将其设置为true,否则为false。传入时为false。
|
||||
* 【注意】如果该值返回true,框架以函数返回值作为报文长度(>0)持续收包,在收包完成前,不再调用该MtFuncTcpMsgChecker函数;报文接收完成后,调用MtFuncTcpMsgChecker函数检查一次报文。减少因零碎收包引起的无效调用。
|
||||
* @return >0 建议的接收缓冲大小; 0 还需要等待接收; <0 报文异常
|
||||
* 【注意】
|
||||
* 以下两种情况可以返回大于0:
|
||||
* 1,业务确定报文长度,返回报文长度
|
||||
* 2,业务不确定报文长度,给出接收buf的建议长度,如果长度大于现有buf长度,框架根据该值realloc buf。
|
||||
*
|
||||
* 返回值为0,表示业务无法确定报文长度,需要接续接收。如果buf收满,框架将realloc buf,buf大小扩大一倍
|
||||
* 返回值小于0,表示业务确定报文错误
|
||||
*/
|
||||
typedef int (*MtFuncTcpMsgChecker)(void* buf, int len, bool closed, void* msg_ctx, bool &msg_len_detected);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief TCP收发接口,可以选择后端保持连接或者短连接
|
||||
* [注意] tcp接收发送buff, 不可以是static变量, 否则会上下文错乱 [重要]
|
||||
* @param dst -请求发送的目的地址
|
||||
* @param pkg -请求包封装的包体
|
||||
* @param len -请求包封装的包体长度
|
||||
* @param rcv_buf -【传出参数】,参考参数 keep_rcv_buf。业务不需要malloc该内存。void* rcv_buf=NULL: 传给框架即可
|
||||
* @param recv_pkg_size -接收应答包的buff的初始大小。函数返回0时,返回报文实际长度。
|
||||
* @param timeout -超时时间, 单位ms
|
||||
* @param check_func -检测报文是否成功到达函数
|
||||
* @param msg_ctx -解析报文的上下文变量。
|
||||
*
|
||||
* @param type - 连接类型
|
||||
* MT_TCP_SHORT: 一收一发短连接;
|
||||
* MT_TCP_LONG : 一发一收长连接;
|
||||
* MT_TCP_LONG_SNDONLY : 只发不收长连接;
|
||||
* MT_TCP_SHORT_SNDONLY: 只发不收短连接;
|
||||
* @param keep_rcv_buf -true,调用成功后,框架将最后的rcv_buf赋值给传出参数,业务负责释放该buf。否则框架在调用结束前释放该buf。【注意】
|
||||
* 业务需要自己在msg_ctx中保留相关信息。【框架通过malloc申请内存】 默认框架自动释放该buf,业务需要在ctx保存信息
|
||||
* @return 0 成功, -1 打开socket失败, -2 发送请求失败, -3 接收应答失败,
|
||||
* -4 连接失败, -5 检测报文失败, -6 接收空间不够, -7 后端主动关闭连接, -10 参数无效, -11,申请接收buf失败
|
||||
*/
|
||||
int mt_tcpsendrcv_ex(struct sockaddr_in* dst, void* pkg, int len, void*& rcv_buf, int& recv_pkg_size,
|
||||
int timeout, MtFuncTcpMsgChecker check_func, void* msg_ctx=NULL,
|
||||
MT_TCP_CONN_TYPE type = MT_TCP_LONG, bool keep_rcv_buf=false);
|
||||
|
||||
/**
|
||||
* @brief TCP会采用连接池的方式复用IP/PORT连接, 连接保持默认10分钟
|
||||
* [注意] tcp接收发送buff, 不可以是static变量, 否则会上下文错乱 [重要]
|
||||
* @param dst -请求发送的目的地址
|
||||
* @param pkg -请求包封装的包体
|
||||
* @param len -请求包封装的包体长度
|
||||
* @param rcv_buf -【传出参数】,参考参数 keep_rcv_buf。
|
||||
* @param recv_pkg_size -接收应答包的buff的初始大小。函数返回0时,返回报文实际长度。
|
||||
* @param timeout -超时时间, 单位ms
|
||||
* @param check_func -检测报文是否成功到达函数
|
||||
* @param msg_ctx -解析报文的上下文变量。
|
||||
* @param keep_rcv_buf -true,框架将最后的rcv_buf赋值给传出参数,业务负责释放该buf。否则框架在调用结束前释放该buf。【注意】
|
||||
* 业务需要自己在msg_ctx中保留相关信息。【框架通过malloc申请内存】
|
||||
* @return 0 成功, -1 打开socket失败, -2 发送请求失败, -3 接收应答失败,
|
||||
* -4 连接失败, -5 检测报文失败, -6 接收空间不够, -7 后端主动关闭连接, -10 参数无效
|
||||
*/
|
||||
|
||||
int mt_tcpsendrcv(struct sockaddr_in* dst, void* pkg, int len, void*& rcv_buf, int& recv_pkg_size,
|
||||
int timeout, MtFuncTcpMsgChecker check_func, void* msg_ctx=NULL, bool keep_rcv_buf=false);
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
/* 微线程用户接口定义: 微线程Task多路并发模型接口定义 */
|
||||
/******************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief 微线程子任务对象定义
|
||||
*/
|
||||
class IMtTask
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief 微线程任务类的处理流程入口函数
|
||||
* @return 0 -成功, < 0 失败
|
||||
*/
|
||||
virtual int Process() { return -1; };
|
||||
|
||||
/**
|
||||
* @brief 设置task执行结果
|
||||
* @info 即Process返回值
|
||||
*/
|
||||
void SetResult(int rc)
|
||||
{
|
||||
_result = rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 获取task执行结果
|
||||
* @info 即Process返回值
|
||||
*/
|
||||
int GetResult(void)
|
||||
{
|
||||
return _result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 设置task类型
|
||||
*/
|
||||
void SetTaskType(int type)
|
||||
{
|
||||
_type = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 获取task类型
|
||||
* @info 如果业务有多种task,可以使用该字段区分不同的task类型
|
||||
* @return 获取task类型
|
||||
*/
|
||||
int GetTaskType(void)
|
||||
{
|
||||
return _type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 微线程任务基类构造与析构
|
||||
*/
|
||||
IMtTask() {};
|
||||
virtual ~IMtTask() {};
|
||||
|
||||
protected:
|
||||
|
||||
int _type; // task类型,多种类型task,业务可以自定义类型,方便从基类转换
|
||||
int _result; // task执行结果,即Process返回值
|
||||
int _type;
|
||||
int _result;
|
||||
};
|
||||
|
||||
typedef vector<IMtTask*> IMtTaskList;
|
||||
|
||||
/**
|
||||
* @brief 多路IO并发, Task-fork-wait模式接口
|
||||
* @param req_list -task list 封装独立api的task列表
|
||||
* @return 0 成功, -1 创建子线程失败
|
||||
*/
|
||||
int mt_exec_all_task(IMtTaskList& req_list);
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
/* 微线程用户接口定义: 微线程封装系统接口 */
|
||||
/******************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief 微线程主动sleep接口, 单位ms
|
||||
* @info 业务需要主动让出CPU时使用
|
||||
*/
|
||||
void mt_sleep(int ms);
|
||||
|
||||
/**
|
||||
* @brief 微线程获取系统时间,单位ms
|
||||
*/
|
||||
unsigned long long mt_time_ms(void);
|
||||
|
||||
/******************************************************************************/
|
||||
/* 微线程用户接口定义: 微线程用户私有数据接口 */
|
||||
/******************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief 设置当前IMtMsg的私有变量
|
||||
* @info 只保存指针,内存需要业务分配
|
||||
*/
|
||||
void mt_set_msg_private(void *data);
|
||||
|
||||
/**
|
||||
* @brief 获取当前IMtMsg的私有变量
|
||||
* @return 私有变量指针
|
||||
*/
|
||||
void* mt_get_msg_private();
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
/* 微线程用户接口定义: 微线程封装系统接口(不推荐使用) */
|
||||
/******************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief 微线程框架初始化
|
||||
* @info 业务不使用spp,裸用微线程,需要调用该函数初始化框架;
|
||||
* 使用spp,直接调用SyncFrame的框架初始化函数即可
|
||||
* @return false:初始化失败 true:初始化成功
|
||||
*/
|
||||
bool mt_init_frame(int argc=0, char * const argv[]=NULL);
|
||||
|
||||
/**
|
||||
* @brief 设置微线程独立栈空间大小
|
||||
* @info 非必须设置,默认大小为128K
|
||||
*/
|
||||
void mt_set_stack_size(unsigned int bytes);
|
||||
|
||||
/**
|
||||
* @brief 微线程包裹的系统IO函数 recvfrom
|
||||
* @param fd 系统socket信息
|
||||
* @param buf 接收消息缓冲区指针
|
||||
* @param len 接收消息缓冲区长度
|
||||
* @param from 来源地址的指针
|
||||
* @param fromlen 来源地址的结构长度
|
||||
* @param timeout 最长等待时间, 毫秒
|
||||
* @return >0 成功接收长度, <0 失败
|
||||
*/
|
||||
int mt_recvfrom(int fd, void *buf, int len, int flags, struct sockaddr *from, socklen_t *fromlen, int timeout);
|
||||
|
||||
/**
|
||||
* @brief 微线程包裹的系统IO函数 sendto
|
||||
* @param fd 系统socket信息
|
||||
* @param msg 待发送的消息指针
|
||||
* @param len 待发送的消息长度
|
||||
* @param to 目的地址的指针
|
||||
* @param tolen 目的地址的结构长度
|
||||
* @param timeout 最长等待时间, 毫秒
|
||||
* @return >0 成功发送长度, <0 失败
|
||||
*/
|
||||
int mt_sendto(int fd, const void *msg, int len, int flags, const struct sockaddr *to, int tolen, int timeout);
|
||||
|
||||
|
||||
/**
|
||||
* @brief 微线程包裹的系统IO函数 connect
|
||||
* @param fd 系统socket信息
|
||||
* @param addr 指定server的目的地址
|
||||
* @param addrlen 地址的长度
|
||||
* @param timeout 最长等待时间, 毫秒
|
||||
* @return >0 成功发送长度, <0 失败
|
||||
*/
|
||||
int mt_connect(int fd, const struct sockaddr *addr, int addrlen, int timeout);
|
||||
|
||||
/**
|
||||
* @brief 微线程包裹的系统IO函数 accept
|
||||
* @param fd 监听套接字
|
||||
* @param addr 客户端地址
|
||||
* @param addrlen 地址的长度
|
||||
* @param timeout 最长等待时间, 毫秒
|
||||
* @return >=0 accept的socket描述符, <0 失败
|
||||
*/
|
||||
int mt_accept(int fd, struct sockaddr *addr, socklen_t *addrlen, int timeout);
|
||||
|
||||
/**
|
||||
* @brief 微线程包裹的系统IO函数 read
|
||||
* @param fd 系统socket信息
|
||||
* @param buf 接收消息缓冲区指针
|
||||
* @param nbyte 接收消息缓冲区长度
|
||||
* @param timeout 最长等待时间, 毫秒
|
||||
* @return >0 成功接收长度, <0 失败
|
||||
*/
|
||||
ssize_t mt_read(int fd, void *buf, size_t nbyte, int timeout);
|
||||
|
||||
/**
|
||||
* @brief 微线程包裹的系统IO函数 write
|
||||
* @param fd 系统socket信息
|
||||
* @param buf 待发送的消息指针
|
||||
* @param nbyte 待发送的消息长度
|
||||
* @param timeout 最长等待时间, 毫秒
|
||||
* @return >0 成功发送长度, <0 失败
|
||||
*/
|
||||
ssize_t mt_write(int fd, const void *buf, size_t nbyte, int timeout);
|
||||
|
||||
/**
|
||||
* @brief 微线程包裹的系统IO函数 recv
|
||||
* @param fd 系统socket信息
|
||||
* @param buf 接收消息缓冲区指针
|
||||
* @param len 接收消息缓冲区长度
|
||||
* @param timeout 最长等待时间, 毫秒
|
||||
* @return >0 成功接收长度, <0 失败
|
||||
*/
|
||||
ssize_t mt_recv(int fd, void *buf, int len, int flags, int timeout);
|
||||
|
||||
/**
|
||||
* @brief 微线程包裹的系统IO函数 send
|
||||
* @param fd 系统socket信息
|
||||
* @param buf 待发送的消息指针
|
||||
* @param nbyte 待发送的消息长度
|
||||
* @param timeout 最长等待时间, 毫秒
|
||||
* @return >0 成功发送长度, <0 失败
|
||||
*/
|
||||
ssize_t mt_send(int fd, const void *buf, size_t nbyte, int flags, int timeout);
|
||||
|
||||
|
||||
/**
|
||||
* @brief 微线程等待epoll事件的包裹函数
|
||||
* @param fd 系统socket信息
|
||||
* @param events 等待的事件 IN/OUT
|
||||
* @param timeout 最长等待时间, 毫秒
|
||||
* @return >0 到达的事件, <0 失败
|
||||
*/
|
||||
int mt_wait_events(int fd, int events, int timeout);
|
||||
|
||||
|
||||
void* mt_start_thread(void* entry, void* args);
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
|
||||
/**
|
||||
* @filename mt_cache.cpp
|
||||
* @info TCP接入buffer管理实现
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
@ -37,12 +36,6 @@
|
|||
|
||||
namespace NS_MICRO_THREAD {
|
||||
|
||||
|
||||
/**
|
||||
* @brief Buffer创建操作
|
||||
* @param size 实际的buff大小
|
||||
* @return 非NULL block块, 其它失败
|
||||
*/
|
||||
TSkBuffer* new_sk_buffer(uint32_t size)
|
||||
{
|
||||
uint32_t total = sizeof(TSkBuffer) + size;
|
||||
|
@ -65,11 +58,6 @@ TSkBuffer* new_sk_buffer(uint32_t size)
|
|||
return block;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Buffer释放操作
|
||||
* @param block -buff块
|
||||
*/
|
||||
void delete_sk_buffer(TSkBuffer* block)
|
||||
{
|
||||
if (NULL == block) {
|
||||
|
@ -79,13 +67,6 @@ void delete_sk_buffer(TSkBuffer* block)
|
|||
free(block);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 保留更大长度信息(非资源池化的buff,可扩展)
|
||||
* @param buff -已有的buff指针
|
||||
* @param size -需要扩展的最终长度大小
|
||||
* @return 实际的buff信息
|
||||
*/
|
||||
TSkBuffer* reserve_sk_buffer(TSkBuffer* buff, uint32_t size)
|
||||
{
|
||||
if (NULL == buff) {
|
||||
|
@ -107,13 +88,6 @@ TSkBuffer* reserve_sk_buffer(TSkBuffer* buff, uint32_t size)
|
|||
return new_buff;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief cache 池的初始化接口
|
||||
* @param mng -管理池的指针
|
||||
* @param expired -保活的时间, 单位秒
|
||||
* @param size -本管理块默认生成的块大小
|
||||
*/
|
||||
void sk_buffer_mng_init(TSkBuffMng* mng, uint32_t expired, uint32_t size)
|
||||
{
|
||||
TAILQ_INIT(&mng->free_list);
|
||||
|
@ -122,10 +96,6 @@ void sk_buffer_mng_init(TSkBuffMng* mng, uint32_t expired, uint32_t size)
|
|||
mng->size = size;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief cache 池的销毁接口
|
||||
* @param mng -管理池的指针
|
||||
*/
|
||||
void sk_buffer_mng_destroy(TSkBuffMng * mng)
|
||||
{
|
||||
TSkBuffer* item = NULL;
|
||||
|
@ -138,12 +108,6 @@ void sk_buffer_mng_destroy(TSkBuffMng * mng)
|
|||
mng->count = 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 申请或复用一块buff
|
||||
* @param mng -管理池的指针
|
||||
* @return 非NULL为成功获取的buff块指针
|
||||
*/
|
||||
TSkBuffer* alloc_sk_buffer(TSkBuffMng* mng)
|
||||
{
|
||||
if (NULL == mng) {
|
||||
|
@ -167,12 +131,6 @@ TSkBuffer* alloc_sk_buffer(TSkBuffMng* mng)
|
|||
return item;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 释放指定的buff块
|
||||
* @param mng -管理池的指针
|
||||
* @param buff -待释放的buff指针
|
||||
*/
|
||||
void free_sk_buffer(TSkBuffMng* mng, TSkBuffer* buff)
|
||||
{
|
||||
if ((NULL == mng) || (NULL == buff)) {
|
||||
|
@ -187,12 +145,6 @@ void free_sk_buffer(TSkBuffMng* mng, TSkBuffer* buff)
|
|||
buff->data_len = 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 回收过期的buff块
|
||||
* @param mng -管理池的指针
|
||||
* @param now -当前的时间, 秒级别
|
||||
*/
|
||||
void recycle_sk_buffer(TSkBuffMng* mng, uint32_t now)
|
||||
{
|
||||
TSkBuffer* item = NULL;
|
||||
|
@ -210,12 +162,6 @@ void recycle_sk_buffer(TSkBuffMng* mng, uint32_t now)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Cache管理链初始化
|
||||
* @param cache -管理块指针
|
||||
* @param pool -buff池指针
|
||||
*/
|
||||
void rw_cache_init(TRWCache* cache, TSkBuffMng* pool)
|
||||
{
|
||||
TAILQ_INIT(&cache->list);
|
||||
|
@ -224,10 +170,6 @@ void rw_cache_init(TRWCache* cache, TSkBuffMng* pool)
|
|||
cache->pool = pool;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Cache管理链销毁
|
||||
* @param cache -管理块指针
|
||||
*/
|
||||
void rw_cache_destroy(TRWCache* cache)
|
||||
{
|
||||
if ((cache == NULL) || (cache->pool == NULL)) {
|
||||
|
@ -246,14 +188,6 @@ void rw_cache_destroy(TRWCache* cache)
|
|||
cache->pool = NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Cache删除并拷贝指定长度数据
|
||||
* @param cache -管理块指针
|
||||
* @param buff -存放buff的指针
|
||||
* @param len -待删除的长度
|
||||
* @return 实际拷贝长度
|
||||
*/
|
||||
uint32_t cache_copy_out(TRWCache* cache, void* buff, uint32_t len)
|
||||
{
|
||||
if ((cache == NULL) || (cache->pool == NULL)) {
|
||||
|
@ -266,7 +200,6 @@ uint32_t cache_copy_out(TRWCache* cache, void* buff, uint32_t len)
|
|||
TSkBuffer* tmp = NULL;
|
||||
TAILQ_FOREACH_SAFE(item, &cache->list, entry, tmp)
|
||||
{
|
||||
// 1. 确认拷贝数据大小
|
||||
skip_len = (item->data_len > left) ? left : item->data_len;
|
||||
if (out_buff != NULL)
|
||||
{
|
||||
|
@ -282,21 +215,18 @@ uint32_t cache_copy_out(TRWCache* cache, void* buff, uint32_t len)
|
|||
break;
|
||||
}
|
||||
|
||||
// 2. 移除一个block
|
||||
if (cache->count > 0) {
|
||||
cache->count--;
|
||||
}
|
||||
TAILQ_REMOVE(&cache->list, item, entry);
|
||||
free_sk_buffer(cache->pool, item);
|
||||
|
||||
// 3. 循环变量控制
|
||||
if (left == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 整体考虑数据长度问题, 是否有足够的数据移除
|
||||
skip_len = len - left;
|
||||
if (cache->len > skip_len)
|
||||
{
|
||||
|
@ -310,22 +240,11 @@ uint32_t cache_copy_out(TRWCache* cache, void* buff, uint32_t len)
|
|||
return skip_len;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Cache删除掉指定长度数据
|
||||
* @param cache -管理块指针
|
||||
* @param len -待删除的长度
|
||||
*/
|
||||
void cache_skip_data(TRWCache* cache, uint32_t len)
|
||||
{
|
||||
cache_copy_out(cache, NULL, len);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Cache追加指定长度数据
|
||||
* @param cache -管理块指针
|
||||
* @param buff -待追加的块指针
|
||||
*/
|
||||
void cache_append_buffer(TRWCache* cache, TSkBuffer* buff)
|
||||
{
|
||||
if ((NULL == cache) || (NULL == buff))
|
||||
|
@ -338,10 +257,6 @@ void cache_append_buffer(TRWCache* cache, TSkBuffer* buff)
|
|||
cache->count++;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Cache移除第一块内存, 但不free
|
||||
* @param cache -管理块指针
|
||||
*/
|
||||
TSkBuffer* cache_skip_first_buffer(TRWCache* cache)
|
||||
{
|
||||
TSkBuffer* buff = TAILQ_FIRST(&cache->list);
|
||||
|
@ -364,13 +279,6 @@ TSkBuffer* cache_skip_first_buffer(TRWCache* cache)
|
|||
return buff;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Cache追加指定长度数据
|
||||
* @param cache -管理块指针
|
||||
* @param data -待追加的指针
|
||||
* @param len -待追加的长度
|
||||
*/
|
||||
int32_t cache_append_data(TRWCache* cache, const void* data, uint32_t len)
|
||||
{
|
||||
if ((NULL == data) || (NULL == cache) || (NULL == cache->pool))
|
||||
|
@ -386,7 +294,6 @@ int32_t cache_append_data(TRWCache* cache, const void* data, uint32_t len)
|
|||
uint32_t left = len;
|
||||
uint32_t remain = 0;
|
||||
|
||||
// 1. 尾空间先进行append, 因为需要回滚, 前一部分先不拷贝
|
||||
TSkBuffer* tail = TAILQ_LAST(&cache->list, __sk_buff_list);
|
||||
if (tail != NULL)
|
||||
{
|
||||
|
@ -403,8 +310,7 @@ int32_t cache_append_data(TRWCache* cache, const void* data, uint32_t len)
|
|||
return (int32_t)len;
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 有剩余buff待处理, 先申请剩余的buff, 在修改尾节点
|
||||
|
||||
TRWCache keep_list;
|
||||
rw_cache_init(&keep_list, cache->pool);
|
||||
left -= remain;
|
||||
|
@ -429,8 +335,7 @@ int32_t cache_append_data(TRWCache* cache, const void* data, uint32_t len)
|
|||
item->data_len = item->size;
|
||||
left -= item->size;
|
||||
}
|
||||
|
||||
// 3. 尝试拷贝最初的buff, 这里不会回滚了
|
||||
|
||||
if ((tail != NULL) && (remain > 0))
|
||||
{
|
||||
memcpy(tail->data + tail->data_len, data, remain);
|
||||
|
@ -444,14 +349,6 @@ int32_t cache_append_data(TRWCache* cache, const void* data, uint32_t len)
|
|||
return (int32_t)len;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Cache整合的UDP收报接口, 消耗内存比较多, 不建议32位使用
|
||||
* @param cache -管理块指针
|
||||
* @param fd - 准备收报的fd句柄
|
||||
* @param remote_addr -对端ip地址
|
||||
* @return 实际接收长度
|
||||
*/
|
||||
int32_t cache_udp_recv(TRWCache* cache, uint32_t fd, struct sockaddr_in* remote_addr)
|
||||
{
|
||||
if (NULL == cache)
|
||||
|
@ -494,13 +391,6 @@ int32_t cache_udp_recv(TRWCache* cache, uint32_t fd, struct sockaddr_in* remote_
|
|||
return total;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Cache整合的TCP收报接口
|
||||
* @param cache -管理块指针
|
||||
* @param fd - 准备收报的fd句柄
|
||||
* @return 实际接收长度
|
||||
*/
|
||||
int32_t cache_tcp_recv(TRWCache* cache, uint32_t fd)
|
||||
{
|
||||
if (NULL == cache)
|
||||
|
@ -511,7 +401,6 @@ int32_t cache_tcp_recv(TRWCache* cache, uint32_t fd)
|
|||
int32_t total = 0;
|
||||
for (uint32_t i = 0; i < 100; i++)
|
||||
{
|
||||
// 1. 每次检查尾空间, 空间满或初始状态, 申请新空间
|
||||
TSkBuffer* item = TAILQ_LAST(&cache->list, __sk_buff_list);
|
||||
if ((NULL == item)
|
||||
|| ((item->data_len + item->data) >= item->end))
|
||||
|
@ -524,7 +413,6 @@ int32_t cache_tcp_recv(TRWCache* cache, uint32_t fd)
|
|||
cache_append_buffer(cache, item);
|
||||
}
|
||||
|
||||
// 2. 单次最多接收size大小, 默认64K
|
||||
uint8_t* buff = item->data + item->data_len;
|
||||
uint32_t remain = item->end - item->data - item->data_len;
|
||||
mt_hook_syscall(recv);
|
||||
|
@ -551,7 +439,7 @@ int32_t cache_tcp_recv(TRWCache* cache, uint32_t fd)
|
|||
item->data_len += recvd_len;
|
||||
cache->len += recvd_len;
|
||||
total += recvd_len;
|
||||
if (recvd_len < (int32_t)remain) // 收不满, 可认为本次OK
|
||||
if (recvd_len < (int32_t)remain)
|
||||
{
|
||||
return total;
|
||||
}
|
||||
|
@ -561,12 +449,6 @@ int32_t cache_tcp_recv(TRWCache* cache, uint32_t fd)
|
|||
return total;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Cache整合的TCP发送接口
|
||||
* @param cache -管理块指针
|
||||
* @param fd - 准备发包的fd句柄
|
||||
* @return 实际发送长度
|
||||
*/
|
||||
int32_t cache_tcp_send(TRWCache* cache, uint32_t fd)
|
||||
{
|
||||
if ((NULL == cache) || (NULL == cache->pool))
|
||||
|
@ -578,8 +460,7 @@ int32_t cache_tcp_send(TRWCache* cache, uint32_t fd)
|
|||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int32_t ret = 0, total = 0;
|
||||
TSkBuffer* item = NULL;
|
||||
TSkBuffer* tmp = NULL;
|
||||
|
@ -612,15 +493,6 @@ int32_t cache_tcp_send(TRWCache* cache, uint32_t fd)
|
|||
return total;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Cache整合的TCP发送接口, 未使用IOVEC
|
||||
* @param cache -管理块指针
|
||||
* @param fd - 准备发包的fd句柄
|
||||
* @param data -发送完cache后, 继续发送的buff
|
||||
* @param len -继续发送的buff长度
|
||||
* @return 实际发送长度
|
||||
*/
|
||||
int32_t cache_tcp_send_buff(TRWCache* cache, uint32_t fd, const void* data, uint32_t len)
|
||||
{
|
||||
if ((NULL == cache) || (NULL == data))
|
||||
|
@ -628,7 +500,6 @@ int32_t cache_tcp_send_buff(TRWCache* cache, uint32_t fd, const void* data, uint
|
|||
return -1;
|
||||
}
|
||||
|
||||
// 1. 优先发送CACHE数据
|
||||
int32_t ret = cache_tcp_send(cache, fd);
|
||||
if (ret < 0)
|
||||
{
|
||||
|
@ -636,7 +507,6 @@ int32_t cache_tcp_send_buff(TRWCache* cache, uint32_t fd, const void* data, uint
|
|||
return ret;
|
||||
}
|
||||
|
||||
// 2. CACHE已经无数据
|
||||
int32_t send_len = 0;
|
||||
if (cache->len == 0)
|
||||
{
|
||||
|
@ -666,12 +536,6 @@ int32_t cache_tcp_send_buff(TRWCache* cache, uint32_t fd, const void* data, uint
|
|||
return send_len;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 获取cache有效数据总长度
|
||||
* @param multi -管理块指针
|
||||
* @return 实际有效数据长度
|
||||
*/
|
||||
uint32_t get_data_len(TBuffVecPtr multi)
|
||||
{
|
||||
TRWCache* cache = (TRWCache*)multi;
|
||||
|
@ -682,11 +546,6 @@ uint32_t get_data_len(TBuffVecPtr multi)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 获取cache有效数据块个数
|
||||
* @param multi -管理块指针
|
||||
* @return 实际有效数据块个数
|
||||
*/
|
||||
uint32_t get_block_count(TBuffVecPtr multi)
|
||||
{
|
||||
TRWCache* cache = (TRWCache*)multi;
|
||||
|
@ -697,11 +556,6 @@ uint32_t get_block_count(TBuffVecPtr multi)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 获取cache的第一块数据指针
|
||||
* @param multi -管理块指针
|
||||
* @return 第一块数据指针
|
||||
*/
|
||||
TBuffBlockPtr get_first_block(TBuffVecPtr multi)
|
||||
{
|
||||
TRWCache* cache = (TRWCache*)multi;
|
||||
|
@ -712,12 +566,6 @@ TBuffBlockPtr get_first_block(TBuffVecPtr multi)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 获取cache的下一块数据指针
|
||||
* @param multi -管理块指针
|
||||
* @param block -当前块指针
|
||||
* @return 下一块数据指针
|
||||
*/
|
||||
TBuffBlockPtr get_next_block(TBuffVecPtr multi, TBuffBlockPtr block)
|
||||
{
|
||||
TRWCache* cache = (TRWCache*)multi;
|
||||
|
@ -731,12 +579,6 @@ TBuffBlockPtr get_next_block(TBuffVecPtr multi, TBuffBlockPtr block)
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 获取数据块的指针与数据长度
|
||||
* @param block -当前块指针
|
||||
* @param data -数据指针-modify参数
|
||||
* @param len -长度指针 modify参数
|
||||
*/
|
||||
void get_block_data(TBuffBlockPtr block, const void** data, int32_t* len)
|
||||
{
|
||||
TSkBuffer* item = (TSkBuffer*)block;
|
||||
|
@ -756,14 +598,6 @@ void get_block_data(TBuffBlockPtr block, const void** data, int32_t* len)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 获取数据块的指针与数据长度
|
||||
* @param multi -管理块指针
|
||||
* @param data -数据写入区域指针
|
||||
* @param len -长度
|
||||
* @return 数据读取的数据长度
|
||||
*/
|
||||
uint32_t read_cache_data(TBuffVecPtr multi, void* data, uint32_t len)
|
||||
{
|
||||
TRWCache* cache = (TRWCache*)multi;
|
||||
|
@ -803,15 +637,6 @@ uint32_t read_cache_data(TBuffVecPtr multi, void* data, uint32_t len)
|
|||
return offset;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief 获取数据块的指针与数据长度
|
||||
* @param multi -管理块指针
|
||||
* @param data -数据写入区域指针
|
||||
* @param len -长度
|
||||
* @return 数据读取的数据长度
|
||||
*/
|
||||
uint32_t read_cache_begin(TBuffVecPtr multi, uint32_t begin, void* data, uint32_t len)
|
||||
{
|
||||
TRWCache* cache = (TRWCache*)multi;
|
||||
|
@ -829,7 +654,6 @@ uint32_t read_cache_begin(TBuffVecPtr multi, uint32_t begin, void* data, uint32_
|
|||
TSkBuffer* item = NULL;
|
||||
TAILQ_FOREACH(item, &cache->list, entry)
|
||||
{
|
||||
// 1. 开始位置有剩余, 则跳过该部分
|
||||
uint8_t* start_ptr = item->data;
|
||||
uint32_t real_left = item->data_len;
|
||||
if (pos_left > 0)
|
||||
|
@ -840,13 +664,11 @@ uint32_t read_cache_begin(TBuffVecPtr multi, uint32_t begin, void* data, uint32_
|
|||
start_ptr += skip_len;
|
||||
}
|
||||
|
||||
// 2. 跳过后无长度剩余, 则等待下一块
|
||||
if (real_left == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// 3. 有剩余, 尽力拷贝最大长度
|
||||
uint32_t copy_len = copy_left > real_left ? real_left : copy_left;
|
||||
if (data != NULL)
|
||||
{
|
||||
|
@ -863,7 +685,4 @@ uint32_t read_cache_begin(TBuffVecPtr multi, uint32_t begin, void* data, uint32_
|
|||
return offset;
|
||||
}
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
|
||||
/**
|
||||
* @filename mt_cache.h
|
||||
* @info TCP接入buffer管理定义
|
||||
*/
|
||||
|
||||
#ifndef ___MT_BUFFER_CACHE_H
|
||||
|
@ -31,268 +30,99 @@
|
|||
|
||||
namespace NS_MICRO_THREAD {
|
||||
|
||||
|
||||
// 默认的buff大小
|
||||
#define SK_DFLT_BUFF_SIZE 64*1024
|
||||
#define SK_DFLT_ALIGN_SIZE 8
|
||||
|
||||
#define SK_ERR_NEED_CLOSE 10000
|
||||
|
||||
/**
|
||||
* @brief 用户态 buffer 结构定义
|
||||
*/
|
||||
|
||||
typedef struct _sk_buffer_tag
|
||||
{
|
||||
TAILQ_ENTRY(_sk_buffer_tag) entry; // list entry buffer LRU等
|
||||
uint32_t last_time; // 上次使用时间戳
|
||||
uint32_t size; // buffer节点的空间大小
|
||||
uint8_t* head; // buff数据区头指针
|
||||
uint8_t* end; // buff数据区结束指针
|
||||
uint8_t* data; // 有效数据的头指针
|
||||
uint32_t data_len; // 有效的数据长度
|
||||
uint8_t buff[0]; // 原始指针区域
|
||||
TAILQ_ENTRY(_sk_buffer_tag) entry;
|
||||
uint32_t last_time;
|
||||
uint32_t size;
|
||||
uint8_t* head;
|
||||
uint8_t* end;
|
||||
uint8_t* data;
|
||||
uint32_t data_len;
|
||||
uint8_t buff[0];
|
||||
} TSkBuffer;
|
||||
typedef TAILQ_HEAD(__sk_buff_list, _sk_buffer_tag) TSkBuffList; // multi 事务命令队列
|
||||
typedef TAILQ_HEAD(__sk_buff_list, _sk_buffer_tag) TSkBuffList;
|
||||
|
||||
|
||||
/**
|
||||
* @brief 申请指定大小的buff块
|
||||
* @param size 有效数据区大小
|
||||
* @return 非NULL为成功返回的buff指针
|
||||
*/
|
||||
TSkBuffer* new_sk_buffer(uint32_t size = SK_DFLT_BUFF_SIZE);
|
||||
|
||||
/**
|
||||
* @brief 释放指定的buff块
|
||||
* @param 待释放的buff指针
|
||||
*/
|
||||
void delete_sk_buffer(TSkBuffer* buff);
|
||||
|
||||
|
||||
/**
|
||||
* @brief 保留更大长度信息(非资源池化的buff,可扩展)
|
||||
* @param buff -已有的buff指针
|
||||
* @param size -需要扩展的最终长度大小
|
||||
* @return 实际的buff信息
|
||||
*/
|
||||
TSkBuffer* reserve_sk_buffer(TSkBuffer* buff, uint32_t size);
|
||||
|
||||
|
||||
/**
|
||||
* @brief buffer cache 管理
|
||||
*/
|
||||
typedef struct _sk_buff_mng_tag
|
||||
{
|
||||
TSkBuffList free_list; // buff链表
|
||||
uint32_t expired; // 超时时间
|
||||
uint32_t size; // buff大小
|
||||
uint32_t count; // 块个数
|
||||
TSkBuffList free_list;
|
||||
uint32_t expired;
|
||||
uint32_t size;
|
||||
uint32_t count;
|
||||
} TSkBuffMng;
|
||||
|
||||
|
||||
/**
|
||||
* @brief cache 池的初始化接口
|
||||
* @param mng -管理池的指针
|
||||
* @param expired -保活的时间, 单位秒
|
||||
* @param size -本管理块默认生成的块大小
|
||||
*/
|
||||
void sk_buffer_mng_init(TSkBuffMng* mng, uint32_t expired, uint32_t size = SK_DFLT_BUFF_SIZE);
|
||||
|
||||
/**
|
||||
* @brief cache 池的销毁接口
|
||||
* @param mng -管理池的指针
|
||||
*/
|
||||
void sk_buffer_mng_destroy(TSkBuffMng * mng);
|
||||
|
||||
|
||||
/**
|
||||
* @brief 申请或复用一块buff
|
||||
* @param mng -管理池的指针
|
||||
* @return 非NULL为成功获取的buff块指针
|
||||
*/
|
||||
TSkBuffer* alloc_sk_buffer(TSkBuffMng* mng);
|
||||
|
||||
/**
|
||||
* @brief 释放指定的buff块
|
||||
* @param mng -管理池的指针
|
||||
* @param buff -待释放的buff指针
|
||||
*/
|
||||
void free_sk_buffer(TSkBuffMng* mng, TSkBuffer* buff);
|
||||
|
||||
/**
|
||||
* @brief 回收过期的buff块
|
||||
* @param mng -管理池的指针
|
||||
* @param now -当前的时间, 秒级别
|
||||
*/
|
||||
void recycle_sk_buffer(TSkBuffMng* mng, uint32_t now);
|
||||
|
||||
|
||||
/**
|
||||
* @brief 原始的 buffer cache 定义
|
||||
*/
|
||||
typedef struct _sk_rw_cache_tag
|
||||
{
|
||||
TSkBuffList list; // buff链表
|
||||
uint32_t len; // 数据长度
|
||||
uint32_t count; // 块个数
|
||||
TSkBuffMng *pool; // 全局buff池指针
|
||||
TSkBuffList list;
|
||||
uint32_t len;
|
||||
uint32_t count;
|
||||
TSkBuffMng *pool;
|
||||
} TRWCache;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Cache管理链初始化
|
||||
* @param cache -管理块指针
|
||||
* @param pool -buff池指针
|
||||
*/
|
||||
void rw_cache_init(TRWCache* cache, TSkBuffMng* pool);
|
||||
|
||||
/**
|
||||
* @brief Cache管理链销毁
|
||||
* @param cache -管理块指针
|
||||
*/
|
||||
void rw_cache_destroy(TRWCache* cache);
|
||||
|
||||
/**
|
||||
* @brief Cache删除掉指定长度数据
|
||||
* @param cache -管理块指针
|
||||
* @param len -待删除的长度
|
||||
*/
|
||||
void cache_skip_data(TRWCache* cache, uint32_t len);
|
||||
|
||||
/**
|
||||
* @brief Cache移除第一块内存
|
||||
* @param cache -管理块指针
|
||||
*/
|
||||
TSkBuffer* cache_skip_first_buffer(TRWCache* cache);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Cache追加指定长度数据
|
||||
* @param cache -管理块指针
|
||||
* @param data -待追加的指针
|
||||
* @param len -待追加的长度
|
||||
*/
|
||||
int32_t cache_append_data(TRWCache* cache, const void* data, uint32_t len);
|
||||
|
||||
/**
|
||||
* @brief Cache追加指定长度数据
|
||||
* @param cache -管理块指针
|
||||
* @param buff -待追加的块指针
|
||||
*/
|
||||
void cache_append_buffer(TRWCache* cache, TSkBuffer* buff);
|
||||
|
||||
/**
|
||||
* @brief Cache删除并拷贝指定长度数据
|
||||
* @param cache -管理块指针
|
||||
* @param buff -存放buff的指针
|
||||
* @param len -待删除的长度
|
||||
* @return 实际拷贝长度
|
||||
*/
|
||||
uint32_t cache_copy_out(TRWCache* cache, void* buff, uint32_t len);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Cache整合的UDP收报接口, 消耗内存比较多, 不建议32位使用
|
||||
* @param cache -管理块指针
|
||||
* @param fd - 准备收报的fd句柄
|
||||
* @param remote_addr -对端ip地址
|
||||
* @return 实际接收长度
|
||||
*/
|
||||
int32_t cache_udp_recv(TRWCache* cache, uint32_t fd, struct sockaddr_in* remote_addr);
|
||||
|
||||
/**
|
||||
* @brief Cache整合的TCP收报接口
|
||||
* @param cache -管理块指针
|
||||
* @param fd - 准备收报的fd句柄
|
||||
* @return 实际接收长度
|
||||
*/
|
||||
int32_t cache_tcp_recv(TRWCache* cache, uint32_t fd);
|
||||
|
||||
/**
|
||||
* @brief Cache整合的TCP发送接口
|
||||
* @param cache -管理块指针
|
||||
* @param fd - 准备发包的fd句柄
|
||||
* @return 实际发送长度
|
||||
*/
|
||||
int32_t cache_tcp_send(TRWCache* cache, uint32_t fd);
|
||||
|
||||
/**
|
||||
* @brief Cache整合的TCP发送接口, 未使用IOVEC
|
||||
* @param cache -管理块指针
|
||||
* @param fd - 准备发包的fd句柄
|
||||
* @param data -发送完cache后, 继续发送的buff
|
||||
* @param len -继续发送的buff长度
|
||||
* @return 实际发送长度
|
||||
*/
|
||||
int32_t cache_tcp_send_buff(TRWCache* cache, uint32_t fd, const void* data, uint32_t len);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// interface
|
||||
typedef void* TBuffVecPtr; ///< 多个block的cache管理指针句柄
|
||||
typedef void* TBuffBlockPtr; ///< 单个管理块指针句柄
|
||||
typedef void* TBuffVecPtr;
|
||||
typedef void* TBuffBlockPtr;
|
||||
|
||||
|
||||
/**
|
||||
* @brief 获取cache有效数据总长度
|
||||
* @param multi -管理块指针
|
||||
* @return 实际有效数据长度
|
||||
*/
|
||||
uint32_t get_data_len(TBuffVecPtr multi);
|
||||
|
||||
/**
|
||||
* @brief 获取cache有效数据块个数
|
||||
* @param multi -管理块指针
|
||||
* @return 实际有效数据块个数
|
||||
*/
|
||||
uint32_t get_block_count(TBuffVecPtr multi);
|
||||
|
||||
/**
|
||||
* @brief 获取cache的第一块数据指针
|
||||
* @param multi -管理块指针
|
||||
* @return 第一块数据指针
|
||||
*/
|
||||
TBuffBlockPtr get_first_block(TBuffVecPtr multi);
|
||||
|
||||
/**
|
||||
* @brief 获取cache的下一块数据指针
|
||||
* @param multi -管理块指针
|
||||
* @param block -当前块指针
|
||||
* @return 下一块数据指针
|
||||
*/
|
||||
TBuffBlockPtr get_next_block(TBuffVecPtr multi, TBuffBlockPtr block);
|
||||
|
||||
/**
|
||||
* @brief 获取数据块的指针与数据长度
|
||||
* @param block -当前块指针
|
||||
* @param data -数据指针-modify参数
|
||||
* @param len -长度指针 modify参数
|
||||
*/
|
||||
void get_block_data(TBuffBlockPtr block, const void** data, int32_t* len);
|
||||
|
||||
|
||||
/**
|
||||
* @brief 获取数据块的指针与数据长度
|
||||
* @param multi -管理块指针
|
||||
* @param data -数据写入区域指针
|
||||
* @param len -长度
|
||||
* @return 数据读取的数据长度
|
||||
*/
|
||||
uint32_t read_cache_data(TBuffVecPtr multi, void* data, uint32_t len);
|
||||
|
||||
|
||||
/**
|
||||
* @brief 获取数据块的指针与数据长度
|
||||
* @param multi -管理块指针
|
||||
* @param data -数据写入区域指针
|
||||
* @param len -长度
|
||||
* @return 数据读取的数据长度
|
||||
*/
|
||||
uint32_t read_cache_begin(TBuffVecPtr multi, uint32_t begin, void* data, uint32_t len);
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
|
||||
/**
|
||||
* @file mt_concurrent.c
|
||||
* @info 多路并处理模型扩展
|
||||
* @time 20130924
|
||||
**/
|
||||
|
||||
|
@ -32,14 +31,6 @@
|
|||
using namespace std;
|
||||
using namespace NS_MICRO_THREAD;
|
||||
|
||||
|
||||
/**
|
||||
* @brief 多路IO的处理优化, 异步调度等待处理
|
||||
* @param req_list - 连接列表
|
||||
* @param how - EPOLLIN EPOLLOUT
|
||||
* @param timeout - 超时时长 毫秒单位
|
||||
* @return 0 成功, <0失败 -3 处理超时
|
||||
*/
|
||||
int NS_MICRO_THREAD::mt_multi_netfd_poll(IMtActList& req_list, int how, int timeout)
|
||||
{
|
||||
KqObjList fdlist;
|
||||
|
@ -99,11 +90,6 @@ int NS_MICRO_THREAD::mt_multi_netfd_poll(IMtActList& req_list, int how, int time
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 为每个ITEM建立上下文的socket
|
||||
* @param req_list - 连接列表
|
||||
* @return 0 成功, <0失败
|
||||
*/
|
||||
int NS_MICRO_THREAD::mt_multi_newsock(IMtActList& req_list)
|
||||
{
|
||||
int sock = -1, has_ok = 0;
|
||||
|
@ -161,13 +147,6 @@ int NS_MICRO_THREAD::mt_multi_newsock(IMtActList& req_list)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 多路IO的处理, 打开连接
|
||||
* @param req_list - 连接列表
|
||||
* @param timeout - 超时时长 毫秒单位
|
||||
* @return 0 成功, <0失败
|
||||
*/
|
||||
int NS_MICRO_THREAD::mt_multi_open(IMtActList& req_list, int timeout)
|
||||
{
|
||||
utime64_t start_ms = MtFrame::Instance()->GetLastClock();
|
||||
|
@ -244,13 +223,6 @@ int NS_MICRO_THREAD::mt_multi_open(IMtActList& req_list, int timeout)
|
|||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 多路IO的处理, 发送数据
|
||||
* @param req_list - 连接列表
|
||||
* @param timeout - 超时时长 毫秒单位
|
||||
* @return 0 成功, <0失败
|
||||
*/
|
||||
int NS_MICRO_THREAD::mt_multi_sendto(IMtActList& req_list, int timeout)
|
||||
{
|
||||
utime64_t start_ms = MtFrame::Instance()->GetLastClock();
|
||||
|
@ -284,7 +256,6 @@ int NS_MICRO_THREAD::mt_multi_sendto(IMtActList& req_list, int timeout)
|
|||
return -2;
|
||||
}
|
||||
|
||||
// 0 -还要继续发送; -1 停止发送; > 0 发送OK
|
||||
ret = net_handler->SendData();
|
||||
if (ret == -1)
|
||||
{
|
||||
|
@ -335,11 +306,6 @@ int NS_MICRO_THREAD::mt_multi_sendto(IMtActList& req_list, int timeout)
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief 多路IO并发接收处理
|
||||
*/
|
||||
int NS_MICRO_THREAD::mt_multi_recvfrom(IMtActList& req_list, int timeout)
|
||||
{
|
||||
utime64_t start_ms = MtFrame::Instance()->GetLastClock();
|
||||
|
@ -360,7 +326,7 @@ int NS_MICRO_THREAD::mt_multi_recvfrom(IMtActList& req_list, int timeout)
|
|||
continue;
|
||||
}
|
||||
|
||||
if (MULTI_FLAG_FIN == action->GetMsgFlag()) ///< 已处理完毕
|
||||
if (MULTI_FLAG_FIN == action->GetMsgFlag())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
@ -373,7 +339,6 @@ int NS_MICRO_THREAD::mt_multi_recvfrom(IMtActList& req_list, int timeout)
|
|||
return -2;
|
||||
}
|
||||
|
||||
// <0 失败, 0 继续收, >0 成功
|
||||
ret = net_handler->RecvData();
|
||||
if (ret < 0)
|
||||
{
|
||||
|
@ -415,18 +380,15 @@ int NS_MICRO_THREAD::mt_multi_recvfrom(IMtActList& req_list, int timeout)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 多路IO并发接收处理
|
||||
*/
|
||||
int NS_MICRO_THREAD::mt_multi_sendrcv_ex(IMtActList& req_list, int timeout)
|
||||
{
|
||||
utime64_t start_ms = MtFrame::Instance()->GetLastClock();
|
||||
utime64_t curr_ms = 0;
|
||||
|
||||
int rc = mt_multi_newsock(req_list); // TODO, 可提取connect超时时间等
|
||||
int rc = mt_multi_newsock(req_list);
|
||||
if (rc < 0)
|
||||
{
|
||||
MT_ATTR_API(320842, 1); // socket失败
|
||||
MT_ATTR_API(320842, 1);
|
||||
MTLOG_ERROR("mt_multi_sendrcv new sock failed, ret: %d", rc);
|
||||
return -1;
|
||||
}
|
||||
|
@ -434,7 +396,7 @@ int NS_MICRO_THREAD::mt_multi_sendrcv_ex(IMtActList& req_list, int timeout)
|
|||
rc = mt_multi_open(req_list, timeout);
|
||||
if (rc < 0)
|
||||
{
|
||||
MT_ATTR_API(320843, 1); // connect失败
|
||||
MT_ATTR_API(320843, 1);
|
||||
MTLOG_ERROR("mt_multi_sendrcv open failed, ret: %d", rc);
|
||||
return -2;
|
||||
}
|
||||
|
@ -443,7 +405,7 @@ int NS_MICRO_THREAD::mt_multi_sendrcv_ex(IMtActList& req_list, int timeout)
|
|||
rc = mt_multi_sendto(req_list, timeout - (curr_ms - start_ms));
|
||||
if (rc < 0)
|
||||
{
|
||||
MT_ATTR_API(320844, 1); // 发送失败
|
||||
MT_ATTR_API(320844, 1);
|
||||
MTLOG_ERROR("mt_multi_sendrcv send failed, ret: %d", rc);
|
||||
return -3;
|
||||
}
|
||||
|
@ -452,7 +414,7 @@ int NS_MICRO_THREAD::mt_multi_sendrcv_ex(IMtActList& req_list, int timeout)
|
|||
rc = mt_multi_recvfrom(req_list, timeout - (curr_ms - start_ms));
|
||||
if (rc < 0)
|
||||
{
|
||||
MT_ATTR_API(320845, 1); // 接收未完全成功
|
||||
MT_ATTR_API(320845, 1);
|
||||
MTLOG_ERROR("mt_multi_sendrcv recv failed, ret: %d", rc);
|
||||
return -4;
|
||||
}
|
||||
|
@ -460,18 +422,10 @@ int NS_MICRO_THREAD::mt_multi_sendrcv_ex(IMtActList& req_list, int timeout)
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 多路IO并发接收处理接口, 封装ACTON接口模型, 内部关联msg
|
||||
* @param req_list -action list 实现封装函数接口
|
||||
* @param timeout -超时时间, 单位ms
|
||||
* @return 0 成功, -1 初始化环境失败, 其它成功或部分成功
|
||||
*/
|
||||
int NS_MICRO_THREAD::mt_msg_sendrcv(IMtActList& req_list, int timeout)
|
||||
{
|
||||
int iRet = 0;
|
||||
|
||||
// 第一步, 初始化action环境, 封装请求报文
|
||||
|
||||
for (IMtActList::iterator it = req_list.begin(); it != req_list.end(); ++it)
|
||||
{
|
||||
IMtAction* pAction = *it;
|
||||
|
@ -491,10 +445,8 @@ int NS_MICRO_THREAD::mt_msg_sendrcv(IMtActList& req_list, int timeout)
|
|||
|
||||
}
|
||||
|
||||
// 第二步, 同步收发消息, 失败也需要通知处理
|
||||
mt_multi_sendrcv_ex(req_list, timeout);
|
||||
|
||||
// 第三步, 同步通知解包处理
|
||||
for (IMtActList::iterator it = req_list.begin(); it != req_list.end(); ++it)
|
||||
{
|
||||
IMtAction* pAction = *it;
|
||||
|
@ -514,7 +466,6 @@ int NS_MICRO_THREAD::mt_msg_sendrcv(IMtActList& req_list, int timeout)
|
|||
}
|
||||
}
|
||||
|
||||
// 第四步, 清理框架内部资源, 兼容各类用法
|
||||
for (IMtActList::iterator it = req_list.begin(); it != req_list.end(); ++it)
|
||||
{
|
||||
IMtAction* pAction = *it;
|
||||
|
@ -523,6 +474,3 @@ int NS_MICRO_THREAD::mt_msg_sendrcv(IMtActList& req_list, int timeout)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
|
||||
/**
|
||||
* @file mt_concurrent.h
|
||||
* @info 扩展状态线程的处理模型
|
||||
* @time 20130515
|
||||
**/
|
||||
|
||||
|
@ -36,62 +35,19 @@ using std::vector;
|
|||
class IMtAction;
|
||||
typedef vector<IMtAction*> IMtActList;
|
||||
|
||||
/******************************************************************************/
|
||||
/* 微线程用户接口定义: 微线程Action多路并发模型接口定义 */
|
||||
/******************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief 多路IO并发接收处理接口, 封装ACTON接口模型, 内部关联msg
|
||||
* @param req_list -action list 实现封装函数接口
|
||||
* @param timeout -超时时间, 单位ms
|
||||
* @return 0 成功, -1 打开socket失败, -2 发送请求失败, -100 接收应答部分失败, 可打印errno
|
||||
*/
|
||||
int mt_msg_sendrcv(IMtActList& req_list, int timeout);
|
||||
|
||||
/******************************************************************************/
|
||||
/* 内部实现定义部分 */
|
||||
/******************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief 多路IO的处理优化, 异步调度等待处理
|
||||
* @param req_list - 连接列表
|
||||
* @param how - EPOLLIN EPOLLOUT
|
||||
* @param timeout - 超时时长 毫秒单位
|
||||
* @return 0 成功, <0失败 -3 处理超时
|
||||
*/
|
||||
int mt_multi_netfd_poll(IMtActList& req_list, int how, int timeout);
|
||||
|
||||
/**
|
||||
* @brief 为每个ITEM建立上下文的socket
|
||||
* @param req_list - 连接列表
|
||||
* @return 0 成功, <0失败
|
||||
*/
|
||||
int mt_multi_newsock(IMtActList& req_list);
|
||||
|
||||
/**
|
||||
* @brief 多路IO的处理, 打开连接
|
||||
* @param req_list - 连接列表
|
||||
* @param timeout - 超时时长 毫秒单位
|
||||
* @return 0 成功, <0失败
|
||||
*/
|
||||
int mt_multi_open(IMtActList& req_list, int timeout);
|
||||
|
||||
/**
|
||||
* @brief 多路IO的处理, 发送数据
|
||||
* @param req_list - 连接列表
|
||||
* @param timeout - 超时时长 毫秒单位
|
||||
* @return 0 成功, <0失败
|
||||
*/
|
||||
int mt_multi_sendto(IMtActList& req_list, int timeout);
|
||||
|
||||
/**
|
||||
* @brief 多路IO并发接收处理
|
||||
*/
|
||||
int mt_multi_recvfrom(IMtActList& req_list, int timeout);
|
||||
|
||||
/**
|
||||
* @brief 多路IO并发接收处理
|
||||
*/
|
||||
int mt_multi_sendrcv_ex(IMtActList& req_list, int timeout);
|
||||
|
||||
}
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
|
||||
/**
|
||||
* @file mt_connection.cpp
|
||||
* @info 微线程消息交互连接管理实现
|
||||
* @time 20130924
|
||||
**/
|
||||
#include <fcntl.h>
|
||||
|
@ -38,10 +37,6 @@
|
|||
using namespace std;
|
||||
using namespace NS_MICRO_THREAD;
|
||||
|
||||
|
||||
/**
|
||||
* @brief 微线程连接基类构造与析构
|
||||
*/
|
||||
IMtConnection::IMtConnection()
|
||||
{
|
||||
_type = OBJ_CONN_UNDEF;
|
||||
|
@ -62,10 +57,6 @@ IMtConnection::~IMtConnection()
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 连接回收复用清理操作
|
||||
*/
|
||||
void IMtConnection::Reset()
|
||||
{
|
||||
if (_ntfy_obj) {
|
||||
|
@ -83,22 +74,15 @@ void IMtConnection::Reset()
|
|||
_msg_buff = NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 连接的socket建立, 依赖连接的协议类型等
|
||||
* @return >0 -成功, 返回系统fd, < 0 失败
|
||||
*/
|
||||
int UdpShortConn::CreateSocket()
|
||||
{
|
||||
// 1. UDP短连接, 每次新创SOCKET
|
||||
_osfd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (_osfd < 0)
|
||||
{
|
||||
MTLOG_ERROR("socket create failed, errno %d(%s)", errno, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 2. 非阻塞设置
|
||||
|
||||
int flags = 1;
|
||||
if (ioctl(_osfd, FIONBIO, &flags) < 0)
|
||||
{
|
||||
|
@ -108,7 +92,6 @@ int UdpShortConn::CreateSocket()
|
|||
return -2;
|
||||
}
|
||||
|
||||
// 3. 更新管理信息
|
||||
if (_ntfy_obj) {
|
||||
_ntfy_obj->SetOsfd(_osfd);
|
||||
}
|
||||
|
@ -116,9 +99,6 @@ int UdpShortConn::CreateSocket()
|
|||
return _osfd;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 关闭系统socket, 重置一些状态
|
||||
*/
|
||||
int UdpShortConn::CloseSocket()
|
||||
{
|
||||
if (_osfd < 0)
|
||||
|
@ -132,11 +112,6 @@ int UdpShortConn::CloseSocket()
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 尝试发送数据, 仅发送一次
|
||||
* @return 0 发送被中断, 需重试. <0 系统失败. >0 本次发送成功
|
||||
*/
|
||||
int UdpShortConn::SendData()
|
||||
{
|
||||
if (!_action || !_msg_buff) {
|
||||
|
@ -167,11 +142,6 @@ int UdpShortConn::SendData()
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 尝试接收数据, 仅接收一次
|
||||
* @param buff 接收缓冲区指针
|
||||
* @return -1 对端关闭. -2 系统失败. >0 本次接收成功
|
||||
*/
|
||||
int UdpShortConn::RecvData()
|
||||
{
|
||||
if (!_action || !_msg_buff) {
|
||||
|
@ -194,19 +164,18 @@ int UdpShortConn::RecvData()
|
|||
{
|
||||
MTLOG_ERROR("socket recv failed, fd %d, errno %d(%s)", _osfd,
|
||||
errno, strerror(errno));
|
||||
return -2; // 系统错误
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
else if (ret == 0)
|
||||
{
|
||||
return -1; // 对端关闭
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
_msg_buff->SetHaveRcvLen(ret);
|
||||
}
|
||||
|
||||
// 上下文检查, >0 收包完整; =0 继续等待; <0(-65535串包)其它异常
|
||||
ret = _action->DoInput();
|
||||
if (ret > 0)
|
||||
{
|
||||
|
@ -228,20 +197,12 @@ int UdpShortConn::RecvData()
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 连接回收复用清理操作
|
||||
*/
|
||||
void UdpShortConn::Reset()
|
||||
{
|
||||
CloseSocket();
|
||||
this->IMtConnection::Reset();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 连接打开与远端会话通道, 如TCP的connect等
|
||||
* @return 0 -成功, < 0 失败
|
||||
*/
|
||||
int TcpKeepConn::OpenCnnect()
|
||||
{
|
||||
if (!_action || !_msg_buff) {
|
||||
|
@ -279,12 +240,9 @@ int TcpKeepConn::OpenCnnect()
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 基于sock的TCP复用连接
|
||||
*/
|
||||
int TcpKeepConn::CreateSocket()
|
||||
{
|
||||
if (_osfd > 0) // 复用连接时, 可跳过创建处理; 不能跳过设置ntfyfd
|
||||
if (_osfd > 0)
|
||||
{
|
||||
if (_ntfy_obj) {
|
||||
_ntfy_obj->SetOsfd(_osfd);
|
||||
|
@ -293,15 +251,13 @@ int TcpKeepConn::CreateSocket()
|
|||
return _osfd;
|
||||
}
|
||||
|
||||
// 第一次进入时, 创建socket
|
||||
_osfd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (_osfd < 0)
|
||||
{
|
||||
MTLOG_ERROR("create tcp socket failed, error: %d", errno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 非阻塞设置
|
||||
|
||||
int flags = 1;
|
||||
if (ioctl(_osfd, FIONBIO, &flags) < 0)
|
||||
{
|
||||
|
@ -311,7 +267,6 @@ int TcpKeepConn::CreateSocket()
|
|||
return -2;
|
||||
}
|
||||
|
||||
// 更新管理信息
|
||||
_keep_ntfy.SetOsfd(_osfd);
|
||||
_keep_ntfy.DisableOutput();
|
||||
_keep_ntfy.EnableInput();
|
||||
|
@ -323,13 +278,6 @@ int TcpKeepConn::CreateSocket()
|
|||
return _osfd;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 尝试发送数据, 仅发送一次
|
||||
* @param dst 发送目的地址
|
||||
* @param buff 发送缓冲区指针
|
||||
* @param size 待发送的最大长度
|
||||
* @return 0 发送被中断, 需重试. <0 系统失败. >0 本次发送成功
|
||||
*/
|
||||
int TcpKeepConn::SendData()
|
||||
{
|
||||
if (!_action || !_msg_buff) {
|
||||
|
@ -360,7 +308,6 @@ int TcpKeepConn::SendData()
|
|||
_msg_buff->SetHaveSndLen(have_send_len);
|
||||
}
|
||||
|
||||
// 全部发送完毕, 返回成功, 否则继续等待
|
||||
if (have_send_len >= msg_len)
|
||||
{
|
||||
return msg_len;
|
||||
|
@ -371,11 +318,6 @@ int TcpKeepConn::SendData()
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 尝试接收数据, 仅接收一次
|
||||
* @param buff 接收缓冲区指针
|
||||
* @return -1 对端关闭. -2 系统失败. >0 本次接收成功
|
||||
*/
|
||||
int TcpKeepConn::RecvData()
|
||||
{
|
||||
if (!_action || !_msg_buff) {
|
||||
|
@ -397,14 +339,14 @@ int TcpKeepConn::RecvData()
|
|||
else
|
||||
{
|
||||
MTLOG_ERROR("recv tcp socket failed, error: %d", errno);
|
||||
return -2; // 系统错误
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
else if (ret == 0)
|
||||
{
|
||||
MTLOG_ERROR("tcp remote close, address: %s[%d]",
|
||||
inet_ntoa(_dst_addr.sin_addr), ntohs(_dst_addr.sin_port));
|
||||
return -1; // 对端关闭
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -412,7 +354,6 @@ int TcpKeepConn::RecvData()
|
|||
_msg_buff->SetHaveRcvLen(have_rcv_len);
|
||||
}
|
||||
|
||||
// 上下文检查, >0 收包完整; =0 继续等待; <0(-65535串包)其它异常
|
||||
ret = _action->DoInput();
|
||||
if (ret > 0)
|
||||
{
|
||||
|
@ -429,9 +370,6 @@ int TcpKeepConn::RecvData()
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 关闭系统socket, 重置一些状态
|
||||
*/
|
||||
int TcpKeepConn::CloseSocket()
|
||||
{
|
||||
if (_osfd < 0)
|
||||
|
@ -446,9 +384,6 @@ int TcpKeepConn::CloseSocket()
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 连接回收复用清理操作
|
||||
*/
|
||||
void TcpKeepConn::Reset()
|
||||
{
|
||||
memset(&_dst_addr, 0 ,sizeof(_dst_addr));
|
||||
|
@ -456,17 +391,11 @@ void TcpKeepConn::Reset()
|
|||
this->IMtConnection::Reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 连接回收复用清理操作
|
||||
*/
|
||||
void TcpKeepConn::ConnReuseClean()
|
||||
{
|
||||
this->IMtConnection::Reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Idle缓存处理, epoll 侦听远端关闭等
|
||||
*/
|
||||
bool TcpKeepConn::IdleAttach()
|
||||
{
|
||||
if (_osfd < 0) {
|
||||
|
@ -482,7 +411,6 @@ bool TcpKeepConn::IdleAttach()
|
|||
_keep_ntfy.DisableOutput();
|
||||
_keep_ntfy.EnableInput();
|
||||
|
||||
// 保活定时器添加
|
||||
CTimerMng* timer = MtFrame::Instance()->GetTimerMng();
|
||||
if ((NULL == timer) || !timer->start_timer(this, _keep_time))
|
||||
{
|
||||
|
@ -502,9 +430,6 @@ bool TcpKeepConn::IdleAttach()
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Idle取消缓存处理, 不再由空闲线程侦听远端关闭
|
||||
*/
|
||||
bool TcpKeepConn::IdleDetach()
|
||||
{
|
||||
if (_osfd < 0) {
|
||||
|
@ -520,7 +445,6 @@ bool TcpKeepConn::IdleDetach()
|
|||
_keep_ntfy.DisableOutput();
|
||||
_keep_ntfy.EnableInput();
|
||||
|
||||
// 保活定时器删除
|
||||
CTimerMng* timer = MtFrame::Instance()->GetTimerMng();
|
||||
if (NULL != timer)
|
||||
{
|
||||
|
@ -539,19 +463,12 @@ bool TcpKeepConn::IdleDetach()
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 超时通知函数, 子类实现逻辑
|
||||
*/
|
||||
void TcpKeepConn::timer_notify()
|
||||
{
|
||||
MTLOG_DEBUG("keep timeout[%u], fd %d, close connection", _keep_time, _osfd);
|
||||
ConnectionMgr::Instance()->CloseIdleTcpKeep(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 构造与析构函数
|
||||
*/
|
||||
TcpKeepMgr::TcpKeepMgr()
|
||||
{
|
||||
_keep_hash = new HashList(10000);
|
||||
|
@ -574,10 +491,6 @@ TcpKeepMgr::~TcpKeepMgr()
|
|||
_keep_hash = NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 按IP地址获取TCP的保持连接
|
||||
*/
|
||||
TcpKeepConn* TcpKeepMgr::GetTcpKeepConn(struct sockaddr_in* dst)
|
||||
{
|
||||
TcpKeepConn* conn = NULL;
|
||||
|
@ -606,9 +519,6 @@ TcpKeepConn* TcpKeepMgr::GetTcpKeepConn(struct sockaddr_in* dst)
|
|||
return conn;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 按IP地址缓存TCP的保持连接
|
||||
*/
|
||||
bool TcpKeepMgr::RemoveTcpKeepConn(TcpKeepConn* conn)
|
||||
{
|
||||
struct sockaddr_in* dst = conn->GetDestAddr();
|
||||
|
@ -633,10 +543,6 @@ bool TcpKeepMgr::RemoveTcpKeepConn(TcpKeepConn* conn)
|
|||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 按IP地址缓存TCP的保持连接
|
||||
*/
|
||||
bool TcpKeepMgr::CacheTcpKeepConn(TcpKeepConn* conn)
|
||||
{
|
||||
struct sockaddr_in* dst = conn->GetDestAddr();
|
||||
|
@ -672,9 +578,6 @@ bool TcpKeepMgr::CacheTcpKeepConn(TcpKeepConn* conn)
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 关闭或缓存tcp长连接
|
||||
*/
|
||||
void TcpKeepMgr::FreeTcpKeepConn(TcpKeepConn* conn, bool force_free)
|
||||
{
|
||||
if (force_free)
|
||||
|
@ -693,16 +596,9 @@ void TcpKeepMgr::FreeTcpKeepConn(TcpKeepConn* conn, bool force_free)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief 连接的socket建立, 依赖连接的协议类型等
|
||||
* @return >0 -成功, 返回系统fd, < 0 失败
|
||||
*/
|
||||
int UdpSessionConn::CreateSocket()
|
||||
{
|
||||
// 1. session连接类, 由通知对象创建管理fd
|
||||
if (!_action || !_ntfy_obj) {
|
||||
MTLOG_ERROR("conn not set action %p, or _ntfy_obj %p, error", _action, _ntfy_obj);
|
||||
return -100;
|
||||
|
@ -718,7 +614,6 @@ int UdpSessionConn::CreateSocket()
|
|||
return -300;
|
||||
}
|
||||
|
||||
// 2. 委派创建, 更新句柄信息
|
||||
int osfd = real_ntfy->GetOsfd();
|
||||
if (osfd <= 0)
|
||||
{
|
||||
|
@ -733,19 +628,11 @@ int UdpSessionConn::CreateSocket()
|
|||
return osfd;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 关闭系统socket, 重置一些状态
|
||||
*/
|
||||
int UdpSessionConn::CloseSocket()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 尝试发送数据, 仅发送一次
|
||||
* @return 0 发送被中断, 需重试. <0 系统失败. >0 本次发送成功
|
||||
*/
|
||||
int UdpSessionConn::SendData()
|
||||
{
|
||||
if (!_action || !_msg_buff || !_ntfy_obj) {
|
||||
|
@ -776,11 +663,6 @@ int UdpSessionConn::SendData()
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 尝试接收数据, 仅接收一次
|
||||
* @param buff 接收缓冲区指针
|
||||
* @return 0 -继续等待接收; >0 接收成功; < 0 失败
|
||||
*/
|
||||
int UdpSessionConn::RecvData()
|
||||
{
|
||||
if (!_ntfy_obj || !_msg_buff) {
|
||||
|
@ -793,7 +675,6 @@ int UdpSessionConn::RecvData()
|
|||
return 0;
|
||||
}
|
||||
|
||||
// UDP Session 通知会替换msg buff, 通过type判定
|
||||
int msg_len = _msg_buff->GetMsgLen();
|
||||
if (BUFF_RECV == _msg_buff->GetBuffType())
|
||||
{
|
||||
|
@ -806,11 +687,6 @@ int UdpSessionConn::RecvData()
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief session全局管理句柄
|
||||
* @return 全局句柄指针
|
||||
*/
|
||||
ConnectionMgr* ConnectionMgr::_instance = NULL;
|
||||
ConnectionMgr* ConnectionMgr::Instance (void)
|
||||
{
|
||||
|
@ -822,9 +698,6 @@ ConnectionMgr* ConnectionMgr::Instance (void)
|
|||
return _instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief session管理全局的销毁接口
|
||||
*/
|
||||
void ConnectionMgr::Destroy()
|
||||
{
|
||||
if( _instance != NULL )
|
||||
|
@ -834,23 +707,14 @@ void ConnectionMgr::Destroy()
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 消息buff的构造函数
|
||||
*/
|
||||
ConnectionMgr::ConnectionMgr()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 析构函数, 不持有资源, 并不负责清理
|
||||
*/
|
||||
ConnectionMgr::~ConnectionMgr()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 获取接口
|
||||
*/
|
||||
IMtConnection* ConnectionMgr::GetConnection(CONN_OBJ_TYPE type, struct sockaddr_in* dst)
|
||||
{
|
||||
switch (type)
|
||||
|
@ -874,9 +738,6 @@ IMtConnection* ConnectionMgr::GetConnection(CONN_OBJ_TYPE type, struct sockaddr_
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 回收接口
|
||||
*/
|
||||
void ConnectionMgr::FreeConnection(IMtConnection* conn, bool force_free)
|
||||
{
|
||||
if (!conn) {
|
||||
|
@ -908,14 +769,8 @@ void ConnectionMgr::FreeConnection(IMtConnection* conn, bool force_free)
|
|||
return;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 关闭idle的tcp长连接
|
||||
*/
|
||||
void ConnectionMgr::CloseIdleTcpKeep(TcpKeepConn* conn)
|
||||
{
|
||||
_tcp_keep_mgr.RemoveTcpKeepConn(conn);
|
||||
_tcp_keep_mgr.FreeTcpKeepConn(conn, true);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
|
||||
/**
|
||||
* @file mt_connection.h
|
||||
* @info 微线程连接管理定义部分
|
||||
* @time 20130924
|
||||
**/
|
||||
|
||||
|
@ -36,140 +35,75 @@ namespace NS_MICRO_THREAD {
|
|||
|
||||
using std::queue;
|
||||
|
||||
/**
|
||||
* @brief 连接对象类型
|
||||
*/
|
||||
enum CONN_OBJ_TYPE
|
||||
{
|
||||
OBJ_CONN_UNDEF = 0, ///< 未定义的连接对象
|
||||
OBJ_SHORT_CONN = 1, ///< 短连接对象, fd关联会话, 每次用完CLOSE
|
||||
OBJ_TCP_KEEP = 2, ///< TCP的复用模型, 每次每连接使用该fd, 用完可复用
|
||||
OBJ_UDP_SESSION = 3, ///< UDP的session模型, 每连接可供任意线程使用
|
||||
OBJ_CONN_UNDEF = 0,
|
||||
OBJ_SHORT_CONN = 1,
|
||||
OBJ_TCP_KEEP = 2,
|
||||
OBJ_UDP_SESSION = 3,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 微线程一个后端请求, 映射一个连接对象
|
||||
*/
|
||||
class IMtConnection
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief 微线程连接基类构造与析构
|
||||
*/
|
||||
IMtConnection();
|
||||
virtual ~IMtConnection();
|
||||
|
||||
/**
|
||||
* @brief 连接回收复用清理操作
|
||||
*/
|
||||
virtual void Reset();
|
||||
|
||||
/**
|
||||
* @brief 获取连接对象的类型信息
|
||||
*/
|
||||
|
||||
CONN_OBJ_TYPE GetConnType() {
|
||||
return _type;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 设置内部ACTION指针
|
||||
* @return IMtConn指针
|
||||
*/
|
||||
|
||||
void SetIMtActon(IMtAction* action ) {
|
||||
_action = action;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 获取内部ACTION指针
|
||||
* @return IMtConn指针
|
||||
*/
|
||||
IMtAction* GetIMtActon() {
|
||||
return _action;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 设置内部ACTION指针
|
||||
* @return IMtConn指针
|
||||
*/
|
||||
void SetNtfyObj(KqueuerObj* obj ) {
|
||||
_ntfy_obj = obj;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 获取内部ACTION指针
|
||||
* @return IMtConn指针
|
||||
*/
|
||||
KqueuerObj* GetNtfyObj() {
|
||||
return _ntfy_obj;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 设置内部msgbuff指针
|
||||
* @return IMtConn指针
|
||||
*/
|
||||
void SetMtMsgBuff(MtMsgBuf* msg_buf) {
|
||||
_msg_buff = msg_buf;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 获取内部msgbuff指针
|
||||
* @return IMtConn指针
|
||||
*/
|
||||
MtMsgBuf* GetMtMsgBuff() {
|
||||
return _msg_buff;
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief 连接的socket建立, 依赖连接的协议类型等
|
||||
* @return >0 -成功, 返回系统fd, < 0 失败
|
||||
*/
|
||||
|
||||
virtual int CreateSocket() {return 0;};
|
||||
|
||||
/**
|
||||
* @brief 连接打开与远端会话通道, 如TCP的connect等
|
||||
* @return 0 -成功, < 0 失败
|
||||
*/
|
||||
|
||||
virtual int OpenCnnect() {return 0;};
|
||||
|
||||
/**
|
||||
* @brief 连接发送数据
|
||||
* @return >0 -成功, 返回实际发送长度, < 0 失败
|
||||
*/
|
||||
virtual int SendData() {return 0;};
|
||||
|
||||
/**
|
||||
* @brief 连接接收数据
|
||||
* @return >0 -成功, 返回本次接收长度, < 0 失败(-1 对端关闭; -2 接收错误)
|
||||
*/
|
||||
virtual int RecvData() {return 0;};
|
||||
|
||||
/**
|
||||
* @brief 关闭socket端口
|
||||
* @return >0 -成功, 返回系统fd, < 0 失败
|
||||
*/
|
||||
virtual int CloseSocket() {return 0;};
|
||||
|
||||
protected:
|
||||
|
||||
CONN_OBJ_TYPE _type; // 预置的type, 可按type做工厂管理
|
||||
IMtAction* _action; // 关联的action指针, 上级指针, 不关心资源生存期
|
||||
KqueuerObj* _ntfy_obj; // EPOLL通知对象, 下级指针, 关心生存期
|
||||
MtMsgBuf* _msg_buff; // 动态管理的buff字段, 下级指针, 关心生存期
|
||||
CONN_OBJ_TYPE _type;
|
||||
IMtAction* _action;
|
||||
KqueuerObj* _ntfy_obj;
|
||||
MtMsgBuf* _msg_buff;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 基于sock的短连接类型
|
||||
*/
|
||||
class UdpShortConn : public IMtConnection
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief 基于socket的短连接的构造与析构
|
||||
*/
|
||||
UdpShortConn() {
|
||||
_osfd = -1;
|
||||
_type = OBJ_SHORT_CONN;
|
||||
|
@ -178,37 +112,18 @@ public:
|
|||
CloseSocket();
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 连接回收复用清理操作
|
||||
*/
|
||||
virtual void Reset();
|
||||
|
||||
/**
|
||||
* @brief 连接的socket建立, 依赖连接的协议类型等
|
||||
* @return >0 -成功, 返回系统fd, < 0 失败
|
||||
*/
|
||||
virtual int CreateSocket();
|
||||
|
||||
/**
|
||||
* @brief 连接发送数据
|
||||
* @return >0 -成功, 返回实际发送长度, < 0 失败
|
||||
*/
|
||||
virtual int SendData();
|
||||
|
||||
/**
|
||||
* @brief 连接接收数据
|
||||
* @return >0 -成功, 返回本次接收长度, < 0 失败(-1 对端关闭; -2 接收错误)
|
||||
*/
|
||||
virtual int RecvData();
|
||||
|
||||
/**
|
||||
* @brief 关闭socket端口
|
||||
* @return >0 -成功, 返回系统fd, < 0 失败
|
||||
*/
|
||||
virtual int CloseSocket();
|
||||
|
||||
protected:
|
||||
int _osfd; // 每次连接单独创建socket
|
||||
int _osfd;
|
||||
};
|
||||
|
||||
|
||||
|
@ -218,64 +133,36 @@ enum TcpKeepFlag
|
|||
TCP_KEEP_IN_KQUEUE = 0x2,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 基于session的UDP复用连接
|
||||
*/
|
||||
class UdpSessionConn : public IMtConnection
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief 基于socket的短连接的构造与析构
|
||||
*/
|
||||
UdpSessionConn() {
|
||||
_type = OBJ_UDP_SESSION;
|
||||
};
|
||||
virtual ~UdpSessionConn() { };
|
||||
|
||||
/**
|
||||
* @brief 连接的socket建立, 依赖连接的协议类型等
|
||||
* @return >0 -成功, 返回系统fd, < 0 失败
|
||||
*/
|
||||
virtual int CreateSocket();
|
||||
|
||||
/**
|
||||
* @brief 连接发送数据
|
||||
* @return >0 -成功, 返回实际发送长度, < 0 失败
|
||||
*/
|
||||
virtual int SendData();
|
||||
|
||||
/**
|
||||
* @brief 连接接收数据
|
||||
* @return >0 -成功, 返回本次接收长度, < 0 失败(-1 对端关闭; -2 接收错误)
|
||||
*/
|
||||
virtual int RecvData();
|
||||
|
||||
/**
|
||||
* @brief 关闭socket端口
|
||||
* @return >0 -成功, 返回系统fd, < 0 失败
|
||||
*/
|
||||
virtual int CloseSocket();
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 基于sock的TCP复用连接
|
||||
*/
|
||||
typedef TAILQ_ENTRY(TcpKeepConn) KeepConnLink;
|
||||
typedef TAILQ_HEAD(__KeepConnTailq, TcpKeepConn) KeepConnList;
|
||||
class TcpKeepConn : public IMtConnection, public CTimerNotify
|
||||
{
|
||||
public:
|
||||
|
||||
int _keep_flag; // 队列状态标记
|
||||
KeepConnLink _keep_entry; // 队列管理入口
|
||||
int _keep_flag;
|
||||
KeepConnLink _keep_entry;
|
||||
|
||||
/**
|
||||
* @brief 基于socket的短连接的构造与析构
|
||||
*/
|
||||
TcpKeepConn() {
|
||||
_osfd = -1;
|
||||
_keep_time = 10*60*1000; // 默认10分钟, 可以按需调整
|
||||
_keep_time = 10*60*1000;
|
||||
_keep_flag = 0;
|
||||
_type = OBJ_TCP_KEEP;
|
||||
_keep_ntfy.SetKeepNtfyObj(this);
|
||||
|
@ -284,102 +171,51 @@ public:
|
|||
CloseSocket();
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 连接回收复用清理操作
|
||||
*/
|
||||
virtual void Reset();
|
||||
|
||||
/**
|
||||
* @brief 连接打开与远端会话通道, 如TCP的connect等
|
||||
* @return 0 -成功, < 0 失败
|
||||
*/
|
||||
|
||||
virtual int OpenCnnect();
|
||||
|
||||
/**
|
||||
* @brief 连接的socket建立, 依赖连接的协议类型等
|
||||
* @return >0 -成功, 返回系统fd, < 0 失败
|
||||
*/
|
||||
virtual int CreateSocket();
|
||||
|
||||
/**
|
||||
* @brief 连接发送数据
|
||||
* @return >0 -成功, 返回实际发送长度, < 0 失败
|
||||
*/
|
||||
virtual int SendData();
|
||||
|
||||
/**
|
||||
* @brief 连接接收数据
|
||||
* @return >0 -成功, 返回本次接收长度, < 0 失败(-1 对端关闭; -2 接收错误)
|
||||
*/
|
||||
virtual int RecvData();
|
||||
|
||||
/**
|
||||
* @brief 关闭socket端口
|
||||
* @return >0 -成功, 返回系统fd, < 0 失败
|
||||
*/
|
||||
virtual int CloseSocket();
|
||||
|
||||
/**
|
||||
* @brief 连接保持复用
|
||||
*/
|
||||
void ConnReuseClean();
|
||||
|
||||
/**
|
||||
* @brief Idle缓存处理, epoll 侦听远端关闭等
|
||||
*/
|
||||
bool IdleAttach();
|
||||
|
||||
/**
|
||||
* @brief Idle取消缓存处理, 不再由空闲线程侦听远端关闭
|
||||
*/
|
||||
bool IdleDetach();
|
||||
|
||||
/**
|
||||
* @brief 存储目的地址信息, 用于复用
|
||||
*/
|
||||
void SetDestAddr(struct sockaddr_in* dst) {
|
||||
memcpy(&_dst_addr, dst, sizeof(_dst_addr));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 获取目的地址信息
|
||||
*/
|
||||
struct sockaddr_in* GetDestAddr() {
|
||||
return &_dst_addr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 超时通知函数, 子类实现逻辑
|
||||
*/
|
||||
|
||||
virtual void timer_notify();
|
||||
|
||||
/**
|
||||
* @brief 设置超时时间, 毫秒单位
|
||||
*/
|
||||
void SetKeepTime(unsigned int time) {
|
||||
_keep_time = time;
|
||||
};
|
||||
|
||||
protected:
|
||||
int _osfd; // 每次连接单独创建socket
|
||||
unsigned int _keep_time; // 设置保活的时间
|
||||
TcpKeepNtfy _keep_ntfy; // 关联一个保活连接对象
|
||||
struct sockaddr_in _dst_addr; // 远端地址信息
|
||||
int _osfd;
|
||||
unsigned int _keep_time;
|
||||
TcpKeepNtfy _keep_ntfy;
|
||||
struct sockaddr_in _dst_addr;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief 按地址hash缓存长连接
|
||||
*/
|
||||
class TcpKeepKey : public HashKey
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief 构造与析构函数
|
||||
*/
|
||||
TcpKeepKey() {
|
||||
_addr_ipv4 = 0;
|
||||
_net_port = 0;
|
||||
|
@ -394,25 +230,14 @@ public:
|
|||
this->SetDataPtr(this);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 这里暂不清理conn
|
||||
*/
|
||||
~TcpKeepKey() {
|
||||
TAILQ_INIT(&_keep_list);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 节点元素的hash算法, 获取key的hash值
|
||||
* @return 节点元素的hash值
|
||||
*/
|
||||
virtual uint32_t HashValue(){
|
||||
return _addr_ipv4 ^ ((_net_port << 16) | _net_port);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 节点元素的cmp方法, 同一桶ID下, 按key比较
|
||||
* @return 节点元素的hash值
|
||||
*/
|
||||
virtual int HashCmp(HashKey* rhs){
|
||||
TcpKeepKey* data = dynamic_cast<TcpKeepKey*>(rhs);
|
||||
if (!data) {
|
||||
|
@ -427,10 +252,6 @@ public:
|
|||
return 0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief 连接对象管理
|
||||
*/
|
||||
void InsertConn(TcpKeepConn* conn) {
|
||||
if (conn->_keep_flag & TCP_KEEP_IN_LIST) {
|
||||
return;
|
||||
|
@ -452,60 +273,36 @@ public:
|
|||
};
|
||||
|
||||
private:
|
||||
uint32_t _addr_ipv4; ///< ip地址
|
||||
uint16_t _net_port; ///< port 网络序列
|
||||
KeepConnList _keep_list; ///< 实际的空闲队列
|
||||
uint32_t _addr_ipv4;
|
||||
uint16_t _net_port;
|
||||
KeepConnList _keep_list;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief TCP长连接的连接对象管理与内存cache
|
||||
*/
|
||||
class TcpKeepMgr
|
||||
{
|
||||
public:
|
||||
|
||||
typedef CPtrPool<TcpKeepConn> TcpKeepQueue; ///< 内存缓冲池
|
||||
typedef CPtrPool<TcpKeepConn> TcpKeepQueue;
|
||||
|
||||
/**
|
||||
* @brief 构造与析构函数
|
||||
*/
|
||||
TcpKeepMgr();
|
||||
|
||||
~TcpKeepMgr();
|
||||
|
||||
|
||||
/**
|
||||
* @brief 按IP地址获取TCP的保持连接
|
||||
*/
|
||||
TcpKeepConn* GetTcpKeepConn(struct sockaddr_in* dst);
|
||||
|
||||
/**
|
||||
* @brief 按IP地址缓存TCP的保持连接
|
||||
*/
|
||||
|
||||
bool CacheTcpKeepConn(TcpKeepConn* conn);
|
||||
|
||||
/**
|
||||
* @brief 按IP地址缓存TCP的保持连接, 去除CACHE
|
||||
*/
|
||||
bool RemoveTcpKeepConn(TcpKeepConn* conn);
|
||||
|
||||
/**
|
||||
* @brief 关闭或缓存tcp长连接
|
||||
*/
|
||||
void FreeTcpKeepConn(TcpKeepConn* conn, bool force_free);
|
||||
|
||||
private:
|
||||
|
||||
HashList* _keep_hash; ///< hash表, 存储按IP索引的连接队列
|
||||
TcpKeepQueue _mem_queue; ///< mem队列, 管理conn内存块
|
||||
HashList* _keep_hash;
|
||||
TcpKeepQueue _mem_queue;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief 连接管理工厂模型
|
||||
*/
|
||||
class ConnectionMgr
|
||||
{
|
||||
public:
|
||||
|
@ -513,48 +310,26 @@ public:
|
|||
typedef CPtrPool<UdpShortConn> UdpShortQueue;
|
||||
typedef CPtrPool<UdpSessionConn> UdpSessionQueue;
|
||||
|
||||
/**
|
||||
* @brief 消息buff的全局管理句柄接口
|
||||
* @return 全局句柄指针
|
||||
*/
|
||||
static ConnectionMgr* Instance (void);
|
||||
|
||||
/**
|
||||
* @brief 消息清理接口
|
||||
*/
|
||||
static void Destroy(void);
|
||||
|
||||
/**
|
||||
* @brief 获取接口
|
||||
*/
|
||||
IMtConnection* GetConnection(CONN_OBJ_TYPE type, struct sockaddr_in* dst);
|
||||
|
||||
/**
|
||||
* @brief 回收接口
|
||||
*/
|
||||
|
||||
void FreeConnection(IMtConnection* conn, bool force_free);
|
||||
|
||||
/**
|
||||
* @brief 关闭idle的tcp长连接
|
||||
*/
|
||||
void CloseIdleTcpKeep(TcpKeepConn* conn);
|
||||
|
||||
/**
|
||||
* @brief 消息buff的析构函数
|
||||
*/
|
||||
~ConnectionMgr();
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief 消息buff的构造函数
|
||||
*/
|
||||
ConnectionMgr();
|
||||
|
||||
static ConnectionMgr * _instance; ///< 单例类句柄
|
||||
static ConnectionMgr * _instance;
|
||||
|
||||
UdpShortQueue _udp_short_queue; ///< 短连接的队列池
|
||||
UdpSessionQueue _udp_session_queue; ///< udp session 连接池
|
||||
TcpKeepMgr _tcp_keep_mgr; ///< tcp keep 管理器
|
||||
UdpShortQueue _udp_short_queue;
|
||||
UdpSessionQueue _udp_session_queue;
|
||||
TcpKeepMgr _tcp_keep_mgr;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
|
||||
/**
|
||||
* @file mt_incl.h
|
||||
* @info 微线程提供给spp_plugin的头文件
|
||||
* @time 20130924
|
||||
*/
|
||||
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
|
||||
/**
|
||||
* @file mt_mbuf_pool.cpp
|
||||
* @info 微线程消息buf池管理实现
|
||||
* @time 20130924
|
||||
**/
|
||||
|
||||
|
@ -29,11 +28,6 @@
|
|||
using namespace std;
|
||||
using namespace NS_MICRO_THREAD;
|
||||
|
||||
|
||||
/**
|
||||
* @brief 连接管理全局访问接口
|
||||
* @return 全局句柄指针
|
||||
*/
|
||||
MsgBuffPool* MsgBuffPool::_instance = NULL;
|
||||
MsgBuffPool* MsgBuffPool::Instance (void)
|
||||
{
|
||||
|
@ -45,9 +39,6 @@ MsgBuffPool* MsgBuffPool::Instance (void)
|
|||
return _instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 连接管理全局的销毁接口
|
||||
*/
|
||||
void MsgBuffPool::Destroy()
|
||||
{
|
||||
if( _instance != NULL )
|
||||
|
@ -57,19 +48,12 @@ void MsgBuffPool::Destroy()
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 消息buff的构造函数
|
||||
*/
|
||||
MsgBuffPool::MsgBuffPool(int max_free)
|
||||
{
|
||||
_max_free = max_free;
|
||||
_hash_map = new HashList(10000);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 消息buff的析构函数
|
||||
*/
|
||||
MsgBuffPool::~MsgBuffPool()
|
||||
{
|
||||
if (!_hash_map) {
|
||||
|
@ -91,10 +75,6 @@ MsgBuffPool::~MsgBuffPool()
|
|||
_hash_map = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 获取消息buff元素
|
||||
* @return msgbuf指针, 失败为NULL
|
||||
*/
|
||||
MtMsgBuf* MsgBuffPool::GetMsgBuf(int max_size)
|
||||
{
|
||||
if (!_hash_map) {
|
||||
|
@ -127,10 +107,6 @@ MtMsgBuf* MsgBuffPool::GetMsgBuf(int max_size)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 获取消息buff元素
|
||||
* @return msgbuf指针, 失败为NULL
|
||||
*/
|
||||
void MsgBuffPool::FreeMsgBuf(MtMsgBuf* msg_buf)
|
||||
{
|
||||
if (!_hash_map || !msg_buf) {
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
|
||||
/**
|
||||
* @file mt_mbuf_pool.h
|
||||
* @info 微线程同步消息buf池
|
||||
**/
|
||||
|
||||
#ifndef __MT_MBUF_POOL_H__
|
||||
|
@ -35,33 +34,27 @@ using std::queue;
|
|||
|
||||
enum BUFF_TYPE
|
||||
{
|
||||
BUFF_UNDEF = 0, ///< 未定义类型
|
||||
BUFF_RECV = 1, ///< 接收buff
|
||||
BUFF_SEND = 2, ///< 发送buff
|
||||
BUFF_UNDEF = 0,
|
||||
BUFF_RECV = 1,
|
||||
BUFF_SEND = 2,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 消息投递的buffer类
|
||||
*/
|
||||
typedef TAILQ_ENTRY(MtMsgBuf) MsgBufLink;
|
||||
typedef TAILQ_HEAD(__MtbuffTailq, MtMsgBuf) MsgBufQueue;
|
||||
class MtMsgBuf
|
||||
{
|
||||
private:
|
||||
int _max_len; // 最大的空间长度
|
||||
int _msg_len; // 实际的消息长度
|
||||
int _buf_type; // buff是发送还是接收
|
||||
int _recv_len; // 已接收的消息长度
|
||||
int _send_len; // 已发送的消息长度
|
||||
void* _msg_buff; // buffer 实际头指针
|
||||
int _max_len;
|
||||
int _msg_len;
|
||||
int _buf_type;
|
||||
int _recv_len;
|
||||
int _send_len;
|
||||
void* _msg_buff;
|
||||
|
||||
public:
|
||||
|
||||
MsgBufLink _entry;
|
||||
|
||||
/**
|
||||
* @brief 构造函数, 指定最大buff长度
|
||||
*/
|
||||
MtMsgBuf(int max_len) {
|
||||
_max_len = max_len;
|
||||
_msg_len = 0;
|
||||
|
@ -78,9 +71,6 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 消息类型的设置与读取
|
||||
*/
|
||||
void SetBuffType(BUFF_TYPE type) {
|
||||
_buf_type = (int)type;
|
||||
};
|
||||
|
@ -88,9 +78,6 @@ public:
|
|||
return (BUFF_TYPE)_buf_type;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 复用接口, 恢复初始状态
|
||||
*/
|
||||
void Reset() {
|
||||
_msg_len = 0;
|
||||
_recv_len = 0;
|
||||
|
@ -98,9 +85,6 @@ public:
|
|||
_buf_type = BUFF_UNDEF;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 消息长度的设置与读取
|
||||
*/
|
||||
void SetMsgLen(int msg_len) {
|
||||
_msg_len = msg_len;
|
||||
};
|
||||
|
@ -108,9 +92,6 @@ public:
|
|||
return _msg_len;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 最大长度与buffer指针获取
|
||||
*/
|
||||
int GetMaxLen() {
|
||||
return _max_len;
|
||||
};
|
||||
|
@ -118,9 +99,6 @@ public:
|
|||
return _msg_buff;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 中间状态获取与更新
|
||||
*/
|
||||
int GetHaveSndLen() {
|
||||
return _send_len;
|
||||
};
|
||||
|
@ -128,9 +106,7 @@ public:
|
|||
_send_len = snd_len;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 中间状态获取与更新
|
||||
*/
|
||||
|
||||
int GetHaveRcvLen() {
|
||||
return _recv_len;
|
||||
};
|
||||
|
@ -139,18 +115,10 @@ public:
|
|||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 指定大小的buffer, 按最大长度映射成空闲队列
|
||||
*/
|
||||
class MsgBufMap : public HashKey
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief 消息buff管理的构造
|
||||
* @param buff_size 该map元素上的所有buff, 其最大buff空间大小值
|
||||
* @param max_free 该队列管理元素, 最大保持的free数目
|
||||
*/
|
||||
MsgBufMap(int buff_size, int max_free) {
|
||||
_max_buf_size = buff_size;
|
||||
_max_free = max_free;
|
||||
|
@ -159,18 +127,11 @@ public:
|
|||
TAILQ_INIT(&_msg_queue);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 消息buff管理的构造, 简单构造, 仅设置key信息
|
||||
* @param buff_size 该map元素上的所有buff, 其最大buff空间大小值
|
||||
*/
|
||||
explicit MsgBufMap(int buff_size) {
|
||||
_max_buf_size = buff_size;
|
||||
TAILQ_INIT(&_msg_queue);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 消息buff管理的析构清理
|
||||
*/
|
||||
~MsgBufMap() {
|
||||
MtMsgBuf* ptr = NULL;
|
||||
MtMsgBuf* tmp = NULL;
|
||||
|
@ -183,11 +144,7 @@ public:
|
|||
|
||||
TAILQ_INIT(&_msg_queue);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 获取消息buff元素
|
||||
* @return msgbuf指针, 失败为NULL
|
||||
*/
|
||||
|
||||
MtMsgBuf* GetMsgBuf(){
|
||||
MtMsgBuf* ptr = NULL;
|
||||
if (!TAILQ_EMPTY(&_msg_queue)) {
|
||||
|
@ -201,10 +158,6 @@ public:
|
|||
return ptr;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 释放消息buff元素
|
||||
* @param msgbuf指针
|
||||
*/
|
||||
void FreeMsgBuf(MtMsgBuf* ptr){
|
||||
if (_queue_num >= _max_free) {
|
||||
delete ptr;
|
||||
|
@ -215,88 +168,49 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 节点元素的hash算法, 获取key的hash值
|
||||
* @return 节点元素的hash值
|
||||
*/
|
||||
virtual uint32_t HashValue(){
|
||||
return _max_buf_size;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 节点元素的cmp方法, 同一桶ID下, 按key比较
|
||||
* @return 节点元素的hash值
|
||||
*/
|
||||
virtual int HashCmp(HashKey* rhs){
|
||||
return this->_max_buf_size - (int)rhs->HashValue();
|
||||
};
|
||||
|
||||
private:
|
||||
int _max_free; ///< 最大空闲保留个数
|
||||
int _max_buf_size; ///< 本队列最大的buffsize
|
||||
int _queue_num; ///< 空闲队列个数
|
||||
MsgBufQueue _msg_queue; ///< 实际的空闲队列
|
||||
int _max_free;
|
||||
int _max_buf_size;
|
||||
int _queue_num;
|
||||
MsgBufQueue _msg_queue;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief 全局的buffer池对象, 统一分配与回收buffer
|
||||
*/
|
||||
class MsgBuffPool
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief 消息buff的全局管理句柄接口
|
||||
* @return 全局句柄指针
|
||||
*/
|
||||
static MsgBuffPool* Instance (void);
|
||||
|
||||
/**
|
||||
* @brief 消息清理接口
|
||||
*/
|
||||
static void Destroy(void);
|
||||
|
||||
/**
|
||||
* @brief 消息buff的全局管理设置默认最大的空闲个数
|
||||
* @param max_free 最大空闲保留数目, 需要在分配元素前设置
|
||||
*/
|
||||
void SetMaxFreeNum(int max_free) {
|
||||
_max_free = max_free;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 获取消息buff元素
|
||||
* @return msgbuf指针, 失败为NULL
|
||||
*/
|
||||
MtMsgBuf* GetMsgBuf(int max_size);
|
||||
|
||||
/**
|
||||
* @brief 释放消息buff元素
|
||||
* @param msgbuf指针
|
||||
*/
|
||||
void FreeMsgBuf(MtMsgBuf* msg_buf);
|
||||
|
||||
/**
|
||||
* @brief 消息buff的全局类析构函数
|
||||
*/
|
||||
~MsgBuffPool();
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* @brief 消息buff的构造函数
|
||||
*/
|
||||
explicit MsgBuffPool(int max_free = 300);
|
||||
|
||||
static MsgBuffPool * _instance; ///< 单例类句柄
|
||||
int _max_free; ///< 最大保留空闲数目
|
||||
HashList* _hash_map; ///< 按size hashmap 保存空闲队列
|
||||
static MsgBuffPool * _instance;
|
||||
int _max_free;
|
||||
HashList* _hash_map;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
|
||||
/**
|
||||
* @file mt_msg.h
|
||||
* @info 微线程同步消息的基类
|
||||
**/
|
||||
|
||||
#ifndef __MT_MSG_H__
|
||||
|
@ -27,22 +26,12 @@
|
|||
|
||||
namespace NS_MICRO_THREAD {
|
||||
|
||||
/**
|
||||
* @brief 微线程消息处理基类
|
||||
*/
|
||||
class IMtMsg
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief 微线程消息类的处理流程入口函数
|
||||
* @return 0 -成功, < 0 失败
|
||||
*/
|
||||
virtual int HandleProcess() { return -1; };
|
||||
|
||||
/**
|
||||
* @brief 微线程消息基类构造与析构
|
||||
*/
|
||||
|
||||
IMtMsg() {};
|
||||
virtual ~IMtMsg() {};
|
||||
};
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -19,7 +19,6 @@
|
|||
|
||||
/**
|
||||
* @file mt_net.h
|
||||
* @info 微线程封装的网络接口类
|
||||
**/
|
||||
|
||||
#ifndef __MT_NET_H__
|
||||
|
@ -33,41 +32,28 @@
|
|||
|
||||
namespace NS_MICRO_THREAD {
|
||||
|
||||
/**
|
||||
* @brief 连接类型定义
|
||||
*/
|
||||
enum MT_CONN_TYPE
|
||||
{
|
||||
TYPE_CONN_UNKNOWN = 0,
|
||||
TYPE_CONN_SHORT = 0x1, ///< 短连接, 一次交互后关闭
|
||||
TYPE_CONN_POOL = 0x2, ///< 长连接,每次使用后, 可回收重复使用
|
||||
TYPE_CONN_SESSION = 0x4, ///< 长连接,按session id 复用, 防串包
|
||||
TYPE_CONN_SENDONLY = 0x8, ///< 只发不收
|
||||
TYPE_CONN_SHORT = 0x1,
|
||||
TYPE_CONN_POOL = 0x2,
|
||||
TYPE_CONN_SESSION = 0x4,
|
||||
TYPE_CONN_SENDONLY = 0x8,
|
||||
};
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
/* 内部实现部分 */
|
||||
/******************************************************************************/
|
||||
class CSockLink;
|
||||
|
||||
/**
|
||||
* @brief 定时回收的对象池模板实现
|
||||
* @info List必须是tailq, Type 需要有reset函数, releasetime, linkentry字段
|
||||
*/
|
||||
template <typename List, typename Type>
|
||||
class CRecyclePool
|
||||
{
|
||||
public:
|
||||
|
||||
// 构造函数, 默认60s超时
|
||||
CRecyclePool() {
|
||||
_expired = 60 * 1000;
|
||||
_count = 0;
|
||||
TAILQ_INIT(&_free_list);
|
||||
};
|
||||
|
||||
// 析构函数, 删除池中元素
|
||||
~CRecyclePool() {
|
||||
Type* item = NULL;
|
||||
Type* tmp = NULL;
|
||||
|
@ -79,7 +65,6 @@ public:
|
|||
_count = 0;
|
||||
};
|
||||
|
||||
// 复用或新创建对象
|
||||
Type* AllocItem() {
|
||||
Type* item = TAILQ_FIRST(&_free_list);
|
||||
if (item != NULL)
|
||||
|
@ -98,16 +83,13 @@ public:
|
|||
return item;
|
||||
};
|
||||
|
||||
// 释放管理对象
|
||||
void FreeItem(Type* obj) {
|
||||
//obj->Reset();
|
||||
TAILQ_INSERT_TAIL(&_free_list, obj, _link_entry);
|
||||
obj->_release_time = mt_time_ms();
|
||||
_count++;
|
||||
};
|
||||
|
||||
|
||||
// 回收句柄
|
||||
void RecycleItem(uint64_t now) {
|
||||
Type* item = NULL;
|
||||
Type* tmp = NULL;
|
||||
|
@ -123,28 +105,21 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
// 设置自定义的超时时间
|
||||
void SetExpiredTime(uint64_t expired) {
|
||||
_expired = expired;
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
List _free_list; ///< 空闲链表
|
||||
uint64_t _expired; ///< 超时时间
|
||||
uint32_t _count; ///< 元素计数
|
||||
List _free_list;
|
||||
uint64_t _expired;
|
||||
uint32_t _count;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief 每次IO关联一个句柄对象
|
||||
*/
|
||||
class CNetHandler : public HashKey
|
||||
{
|
||||
public:
|
||||
|
||||
// 句柄状态描述
|
||||
enum {
|
||||
STATE_IN_SESSION = 0x1,
|
||||
STATE_IN_CONNECT = 0x2,
|
||||
|
@ -152,23 +127,13 @@ public:
|
|||
STATE_IN_RECV = 0x8,
|
||||
STATE_IN_IDLE = 0x10,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 节点元素的hash算法, 获取key的hash值
|
||||
* @return 节点元素的hash值
|
||||
*/
|
||||
|
||||
virtual uint32_t HashValue();
|
||||
|
||||
/**
|
||||
* @brief 节点元素的cmp方法, 同一桶ID下, 按key比较
|
||||
* @return 节点元素的hash值
|
||||
*/
|
||||
virtual int HashCmp(HashKey* rhs);
|
||||
|
||||
// 同步收发接口
|
||||
int32_t SendRecv(void* data, uint32_t len, uint32_t timeout);
|
||||
|
||||
// 获取返回buff信息, 有效期直到helper析构
|
||||
void* GetRspBuff() {
|
||||
if (_rsp_buff != NULL) {
|
||||
return _rsp_buff->data;
|
||||
|
@ -177,7 +142,6 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
// 获取返回buff信息, 有效期直到helper析构
|
||||
uint32_t GetRspLen() {
|
||||
if (_rsp_buff != NULL) {
|
||||
return _rsp_buff->data_len;
|
||||
|
@ -185,8 +149,7 @@ public:
|
|||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
// 设置rsp信息
|
||||
|
||||
void SetRespBuff(TSkBuffer* buff) {
|
||||
if (_rsp_buff != NULL) {
|
||||
delete_sk_buffer(_rsp_buff);
|
||||
|
@ -196,34 +159,28 @@ public:
|
|||
_rsp_buff = buff;
|
||||
};
|
||||
|
||||
// 设置协议的类型, 默认UDP
|
||||
void SetProtoType(MT_PROTO_TYPE type) {
|
||||
_proto_type = type;
|
||||
};
|
||||
|
||||
// 设置连接类型, 默认长连接
|
||||
void SetConnType(MT_CONN_TYPE type) {
|
||||
_conn_type = type;
|
||||
};
|
||||
|
||||
// 设置目的IP地址
|
||||
void SetDestAddress(struct sockaddr_in* dst) {
|
||||
if (dst != NULL) {
|
||||
memcpy(&_dest_ipv4, dst, sizeof(*dst));
|
||||
}
|
||||
};
|
||||
|
||||
// 设置session本次session id信息, 必须非0
|
||||
void SetSessionId(uint64_t sid) {
|
||||
_session_id = sid;
|
||||
};
|
||||
|
||||
// 设置session解析回调函数
|
||||
void SetSessionCallback(CHECK_SESSION_CALLBACK function) {
|
||||
_callback = function;
|
||||
};
|
||||
|
||||
// 获取回调函数信息
|
||||
CHECK_SESSION_CALLBACK GetSessionCallback() {
|
||||
return _callback;
|
||||
};
|
||||
|
@ -231,113 +188,86 @@ public:
|
|||
|
||||
public:
|
||||
|
||||
// 关联连接对象
|
||||
void Link(CSockLink* conn);
|
||||
|
||||
// 解耦连接对象
|
||||
void Unlink();
|
||||
|
||||
// 检查必要的参数信息
|
||||
|
||||
int32_t CheckParams();
|
||||
|
||||
// 获取链接, 同时关联到等待连接的队列中
|
||||
int32_t GetConnLink();
|
||||
|
||||
// 检查必要的参数信息
|
||||
int32_t WaitConnect(uint64_t timeout);
|
||||
|
||||
// 检查必要的参数信息
|
||||
int32_t WaitSend(uint64_t timeout);
|
||||
|
||||
// 检查必要的参数信息
|
||||
|
||||
int32_t WaitRecv(uint64_t timeout);
|
||||
|
||||
// 关联在等待连接队列
|
||||
void SwitchToConn();
|
||||
|
||||
// 切换到发送队列
|
||||
void SwitchToSend();
|
||||
|
||||
// 切换到接收队列
|
||||
void SwitchToRecv();
|
||||
|
||||
// 切换到空闲状态
|
||||
|
||||
void SwitchToIdle();
|
||||
|
||||
// 解耦连接对象
|
||||
void DetachConn();
|
||||
|
||||
// 注册session管理
|
||||
|
||||
bool RegistSession();
|
||||
|
||||
// 取消注册session
|
||||
void UnRegistSession();
|
||||
|
||||
// 跳过发送的请求长度
|
||||
uint32_t SkipSendPos(uint32_t len);
|
||||
|
||||
// 设置返回码
|
||||
void SetErrNo(int32_t err) {
|
||||
_err_no = err;
|
||||
};
|
||||
|
||||
// 获取关联的线程信息
|
||||
MicroThread* GetThread() {
|
||||
return _thread;
|
||||
};
|
||||
|
||||
// 获取待发送的指针与数据长度
|
||||
void GetSendData(void*& data, uint32_t& len) {
|
||||
data = _req_data;
|
||||
len = _req_len;
|
||||
};
|
||||
|
||||
// 复用接口
|
||||
|
||||
void Reset();
|
||||
|
||||
// 构造与析构
|
||||
CNetHandler();
|
||||
~CNetHandler();
|
||||
|
||||
// 队列快捷访问的宏定义
|
||||
TAILQ_ENTRY(CNetHandler) _link_entry;
|
||||
uint64_t _release_time;
|
||||
|
||||
protected:
|
||||
|
||||
MicroThread* _thread; ///< 关联线程指针对象
|
||||
MT_PROTO_TYPE _proto_type; ///< 协议类型
|
||||
MT_CONN_TYPE _conn_type; ///< 连接类型
|
||||
struct sockaddr_in _dest_ipv4; ///< ipv4目的地址
|
||||
uint64_t _session_id; ///< 会话ID
|
||||
CHECK_SESSION_CALLBACK _callback; ///< 会话提取回调函数
|
||||
uint32_t _state_flags; ///< 内部状态字段
|
||||
int32_t _err_no; ///< 返回码信息
|
||||
void* _conn_ptr; ///< socket 链路指针
|
||||
uint32_t _send_pos; ///< 已发送的pos位置
|
||||
uint32_t _req_len; ///< 请求包长度
|
||||
void* _req_data; ///< 请求包指针
|
||||
TSkBuffer* _rsp_buff; ///< 应答buff信息
|
||||
MicroThread* _thread;
|
||||
MT_PROTO_TYPE _proto_type;
|
||||
MT_CONN_TYPE _conn_type;
|
||||
struct sockaddr_in _dest_ipv4;
|
||||
uint64_t _session_id;
|
||||
CHECK_SESSION_CALLBACK _callback;
|
||||
uint32_t _state_flags;
|
||||
int32_t _err_no;
|
||||
void* _conn_ptr;
|
||||
uint32_t _send_pos;
|
||||
uint32_t _req_len;
|
||||
void* _req_data;
|
||||
TSkBuffer* _rsp_buff;
|
||||
|
||||
};
|
||||
typedef TAILQ_HEAD(__NetHandlerList, CNetHandler) TNetItemList; ///< 高效的双链管理
|
||||
typedef CRecyclePool<TNetItemList, CNetHandler> TNetItemPool; ///< 定时回收的对象池
|
||||
typedef TAILQ_HEAD(__NetHandlerList, CNetHandler) TNetItemList;
|
||||
typedef CRecyclePool<TNetItemList, CNetHandler> TNetItemPool;
|
||||
|
||||
|
||||
/**
|
||||
* @brief 长连接链路对象
|
||||
*/
|
||||
class CSockLink : public KqueuerObj
|
||||
{
|
||||
public:
|
||||
|
||||
// 句柄状态描述
|
||||
enum {
|
||||
LINK_CONNECTING = 0x1,
|
||||
LINK_CONNECTED = 0x2,
|
||||
};
|
||||
|
||||
// 状态队列定义
|
||||
enum {
|
||||
LINK_IDLE_LIST = 1,
|
||||
LINK_CONN_LIST = 2,
|
||||
|
@ -345,115 +275,74 @@ public:
|
|||
LINK_RECV_LIST = 4,
|
||||
};
|
||||
|
||||
// 检查或创建socket句柄
|
||||
int32_t CreateSock();
|
||||
|
||||
// 关闭链路的句柄
|
||||
void Close();
|
||||
|
||||
// 发起连接过程
|
||||
bool Connect();
|
||||
bool Connected() {
|
||||
return (_state & LINK_CONNECTED);
|
||||
}
|
||||
|
||||
// 异常终止的处理函数
|
||||
void Destroy();
|
||||
|
||||
// 获取管理链表
|
||||
TNetItemList* GetItemList(int32_t type);
|
||||
|
||||
// 管理句柄信息
|
||||
void AppendToList(int32_t type, CNetHandler* item);
|
||||
|
||||
// 管理句柄信息
|
||||
void RemoveFromList(int32_t type, CNetHandler* item);
|
||||
|
||||
// 获取目标ip信息
|
||||
struct sockaddr_in* GetDestAddr(struct sockaddr_in* addr);
|
||||
|
||||
// 发起连接过程
|
||||
int32_t SendData(void* data, uint32_t len);
|
||||
|
||||
// udp发送数据
|
||||
int32_t SendCacheUdp(void* data, uint32_t len);
|
||||
|
||||
// tcp发送数据
|
||||
int32_t SendCacheTcp(void* data, uint32_t len);
|
||||
|
||||
// 尝试接收更多的数据到临时buff
|
||||
void ExtendRecvRsp();
|
||||
|
||||
// 数据分发处理过程
|
||||
int32_t RecvDispath();
|
||||
|
||||
// 或者回调函数, 优先从排队等待中获取, 备份从父节点获取
|
||||
CHECK_SESSION_CALLBACK GetSessionCallback();
|
||||
|
||||
// TCP接收数据流处理与分发
|
||||
int32_t DispathTcp();
|
||||
|
||||
// UDP接收数据流处理与分发
|
||||
int32_t DispathUdp();
|
||||
|
||||
// 查询本地sessionid关联的session信息
|
||||
CNetHandler* FindSession(uint64_t sid);
|
||||
|
||||
/**
|
||||
* @brief 可读事件通知接口, 考虑通知处理可能会破坏环境, 可用返回值区分
|
||||
* @return 0 该fd可继续处理其它事件; !=0 该fd需跳出回调处理
|
||||
*/
|
||||
virtual int InputNotify();
|
||||
|
||||
/**
|
||||
* @brief 可写事件通知接口, 考虑通知处理可能会破坏环境, 可用返回值区分
|
||||
* @return 0 该fd可继续处理其它事件; !=0 该fd需跳出回调处理
|
||||
*/
|
||||
virtual int OutputNotify();
|
||||
|
||||
/**
|
||||
* @brief 异常通知接口
|
||||
* @return 忽略返回值, 跳过其它事件处理
|
||||
*/
|
||||
|
||||
virtual int HangupNotify();
|
||||
|
||||
|
||||
// 构造与析构函数
|
||||
CSockLink();
|
||||
~CSockLink();
|
||||
|
||||
// 清理置初始化逻辑
|
||||
~CSockLink();
|
||||
|
||||
void Reset();
|
||||
|
||||
// 通知唤醒线程
|
||||
|
||||
void NotifyThread(CNetHandler* item, int32_t result);
|
||||
|
||||
// 通知唤醒线程
|
||||
void NotifyAll(int32_t result);
|
||||
|
||||
// 设置协议类型, 决定buff池的指针
|
||||
void SetProtoType(MT_PROTO_TYPE type);
|
||||
|
||||
// 设置上级指针信息
|
||||
void SetParentsPtr(void* ptr) {
|
||||
_parents = ptr;
|
||||
};
|
||||
|
||||
// 获取上级节点指针
|
||||
void* GetParentsPtr() {
|
||||
return _parents;
|
||||
};
|
||||
|
||||
// 获取上次的访问时间
|
||||
uint64_t GetLastAccess() {
|
||||
return _last_access;
|
||||
};
|
||||
|
||||
|
||||
|
||||
public:
|
||||
|
||||
// 队列快捷访问的宏定义
|
||||
TAILQ_ENTRY(CSockLink) _link_entry;
|
||||
uint64_t _release_time;
|
||||
|
||||
|
@ -471,44 +360,32 @@ private:
|
|||
TSkBuffer* _rsp_buff;
|
||||
void* _parents;
|
||||
};
|
||||
typedef TAILQ_HEAD(__SocklinkList, CSockLink) TLinkList; ///< 高效的双链管理
|
||||
typedef CRecyclePool<TLinkList, CSockLink> TLinkPool; ///< 定时回收的对象池
|
||||
|
||||
typedef TAILQ_HEAD(__SocklinkList, CSockLink) TLinkList;
|
||||
typedef CRecyclePool<TLinkList, CSockLink> TLinkPool;
|
||||
|
||||
class CDestLinks : public CTimerNotify, public HashKey
|
||||
{
|
||||
public:
|
||||
|
||||
// 构造函数
|
||||
CDestLinks();
|
||||
|
||||
// 析构函数
|
||||
~CDestLinks();
|
||||
|
||||
// 重置复用的接口函数
|
||||
void Reset();
|
||||
|
||||
// 启动定时器
|
||||
void StartTimer();
|
||||
|
||||
// 获取一个连接link, 暂时按轮询
|
||||
CSockLink* GetSockLink();
|
||||
|
||||
// 释放一个连接link
|
||||
void FreeSockLink(CSockLink* sock);
|
||||
|
||||
// 获取协议类型
|
||||
MT_PROTO_TYPE GetProtoType() {
|
||||
return _proto_type;
|
||||
};
|
||||
|
||||
// 获取连接类型
|
||||
MT_CONN_TYPE GetConnType() {
|
||||
return _conn_type;
|
||||
};
|
||||
|
||||
|
||||
// 设置关键信息
|
||||
void SetKeyInfo(uint32_t ipv4, uint16_t port, MT_PROTO_TYPE proto, MT_CONN_TYPE conn) {
|
||||
_addr_ipv4 = ipv4;
|
||||
_net_port = port;
|
||||
|
@ -516,37 +393,24 @@ public:
|
|||
_conn_type = conn;
|
||||
};
|
||||
|
||||
// 拷贝KEY信息
|
||||
void CopyKeyInfo(CDestLinks* key) {
|
||||
_addr_ipv4 = key->_addr_ipv4;
|
||||
_net_port = key->_net_port;
|
||||
_proto_type = key->_proto_type;
|
||||
_conn_type = key->_conn_type;
|
||||
};
|
||||
|
||||
// 获取IP port信息
|
||||
|
||||
void GetDestIP(uint32_t& ip, uint16_t& port) {
|
||||
ip = _addr_ipv4;
|
||||
port = _net_port;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 超时通知函数, 检查空闲链路, 检查配置链路个数
|
||||
*/
|
||||
virtual void timer_notify();
|
||||
|
||||
/**
|
||||
* @brief 节点元素的hash算法, 获取key的hash值
|
||||
* @return 节点元素的hash值
|
||||
*/
|
||||
|
||||
virtual uint32_t HashValue() {
|
||||
return _addr_ipv4 ^ (((uint32_t)_net_port << 16) | (_proto_type << 8) | _conn_type);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 节点元素的cmp方法, 同一桶ID下, 按key比较
|
||||
* @return 节点元素的hash值
|
||||
*/
|
||||
virtual int HashCmp(HashKey* rhs) {
|
||||
CDestLinks* data = (CDestLinks*)(rhs);
|
||||
if (!data) {
|
||||
|
@ -568,120 +432,86 @@ public:
|
|||
return 0;
|
||||
};
|
||||
|
||||
// 设置session解析回调函数
|
||||
void SetDefaultCallback(CHECK_SESSION_CALLBACK function) {
|
||||
_dflt_callback = function;
|
||||
};
|
||||
|
||||
// 获取回调函数信息
|
||||
CHECK_SESSION_CALLBACK GetDefaultCallback() {
|
||||
return _dflt_callback;
|
||||
};
|
||||
|
||||
// 队列快捷访问的宏定义
|
||||
TAILQ_ENTRY(CDestLinks) _link_entry;
|
||||
uint64_t _release_time;
|
||||
|
||||
private:
|
||||
|
||||
uint32_t _timeout; ///< idle的超时时间
|
||||
uint32_t _addr_ipv4; ///< ip地址
|
||||
uint16_t _net_port; ///< port 网络序列
|
||||
MT_PROTO_TYPE _proto_type; ///< 协议类型
|
||||
MT_CONN_TYPE _conn_type; ///< 连接类型
|
||||
uint32_t _timeout;
|
||||
uint32_t _addr_ipv4;
|
||||
uint16_t _net_port;
|
||||
MT_PROTO_TYPE _proto_type;
|
||||
MT_CONN_TYPE _conn_type;
|
||||
|
||||
uint32_t _max_links; ///< 最大连接数
|
||||
uint32_t _curr_link; ///< 当前连接数
|
||||
TLinkList _sock_list; ///< 连接链表
|
||||
CHECK_SESSION_CALLBACK _dflt_callback; ///< 默认的check函数
|
||||
uint32_t _max_links;
|
||||
uint32_t _curr_link;
|
||||
TLinkList _sock_list;
|
||||
CHECK_SESSION_CALLBACK _dflt_callback;
|
||||
|
||||
};
|
||||
typedef TAILQ_HEAD(__DestlinkList, CDestLinks) TDestList; ///< 高效的双链管理
|
||||
typedef CRecyclePool<TDestList, CDestLinks> TDestPool; ///< 定时回收的对象池
|
||||
typedef TAILQ_HEAD(__DestlinkList, CDestLinks) TDestList;
|
||||
typedef CRecyclePool<TDestList, CDestLinks> TDestPool;
|
||||
|
||||
/**
|
||||
* @brief 连接管理工厂模型
|
||||
*/
|
||||
class CNetMgr
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief 消息buff的全局管理句柄接口
|
||||
* @return 全局句柄指针
|
||||
*/
|
||||
static CNetMgr* Instance (void);
|
||||
|
||||
/**
|
||||
* @brief 消息清理接口
|
||||
*/
|
||||
static void Destroy(void);
|
||||
|
||||
// 查询是否已经存在同一个sid的对象
|
||||
CNetHandler* FindNetItem(CNetHandler* key);
|
||||
|
||||
// 注册一个item, 先查询后插入, 保证无冲突
|
||||
void InsertNetItem(CNetHandler* item);
|
||||
|
||||
// 移除一个item对象
|
||||
void RemoveNetItem(CNetHandler* item);
|
||||
|
||||
// 查询或创建一个目标ip的links节点
|
||||
CDestLinks* FindCreateDest(CDestLinks* key);
|
||||
|
||||
// 删除掉已有的目标链路信息
|
||||
void DeleteDestLink(CDestLinks* dst);
|
||||
|
||||
// 查询是否已经存在同一个sid的对象
|
||||
|
||||
CDestLinks* FindDestLink(CDestLinks* key);
|
||||
|
||||
// 注册一个item, 先查询后插入, 保证无冲突
|
||||
void InsertDestLink(CDestLinks* item);
|
||||
|
||||
// 移除一个item对象
|
||||
|
||||
void RemoveDestLink(CDestLinks* item);
|
||||
|
||||
/**
|
||||
* @brief 消息buff的析构函数
|
||||
*/
|
||||
~CNetMgr();
|
||||
|
||||
/**
|
||||
* @brief 回收资源信息
|
||||
*/
|
||||
void RecycleObjs(uint64_t now);
|
||||
|
||||
// 分配一个网络管理句柄
|
||||
CNetHandler* AllocNetItem() {
|
||||
return _net_item_pool.AllocItem();
|
||||
};
|
||||
|
||||
// 释放一个网络管理句柄
|
||||
void FreeNetItem(CNetHandler* item) {
|
||||
return _net_item_pool.FreeItem(item);
|
||||
};
|
||||
|
||||
// 分配一个SOCK连接链路
|
||||
CSockLink* AllocSockLink() {
|
||||
return _sock_link_pool.AllocItem();
|
||||
};
|
||||
|
||||
// 释放一个SOCK连接链路
|
||||
void FreeSockLink(CSockLink* item) {
|
||||
return _sock_link_pool.FreeItem(item);
|
||||
};
|
||||
|
||||
// 分配一个SOCK连接链路
|
||||
CDestLinks* AllocDestLink() {
|
||||
return _dest_ip_pool.AllocItem();
|
||||
};
|
||||
|
||||
// 释放一个SOCK连接链路
|
||||
void FreeDestLink(CDestLinks* item) {
|
||||
return _dest_ip_pool.FreeItem(item);
|
||||
};
|
||||
|
||||
// 获取udp的buff池信息
|
||||
TSkBuffMng* GetSkBuffMng(MT_PROTO_TYPE type) {
|
||||
if (type == NET_PROTO_TCP) {
|
||||
return &_tcp_pool;
|
||||
|
@ -692,25 +522,18 @@ public:
|
|||
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief 消息buff的构造函数
|
||||
*/
|
||||
CNetMgr();
|
||||
|
||||
static CNetMgr * _instance; ///< 单例类句柄
|
||||
HashList* _ip_hash; ///< 目的地址hash
|
||||
HashList* _session_hash; ///< session id的hash
|
||||
TSkBuffMng _udp_pool; ///< udp pool, 64K
|
||||
TSkBuffMng _tcp_pool; ///< tcp pool, 4K
|
||||
TDestPool _dest_ip_pool; ///< 目的ip对象池
|
||||
TLinkPool _sock_link_pool; ///< socket pool
|
||||
TNetItemPool _net_item_pool; ///< net handle pool
|
||||
static CNetMgr * _instance;
|
||||
HashList* _ip_hash;
|
||||
HashList* _session_hash;
|
||||
TSkBuffMng _udp_pool;
|
||||
TSkBuffMng _tcp_pool;
|
||||
TDestPool _dest_ip_pool;
|
||||
TLinkPool _sock_link_pool;
|
||||
TNetItemPool _net_item_pool;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
|
||||
/**
|
||||
* @file mt_net_api.h
|
||||
* @info 微线程封装的网络接口类
|
||||
**/
|
||||
|
||||
#ifndef __MT_NET_API_H__
|
||||
|
@ -29,90 +28,60 @@
|
|||
|
||||
namespace NS_MICRO_THREAD {
|
||||
|
||||
/**
|
||||
* @brief 协议类型定义
|
||||
*/
|
||||
enum MT_PROTO_TYPE
|
||||
{
|
||||
NET_PROTO_UNDEF = 0,
|
||||
NET_PROTO_UDP = 0x1, ///< 连接类型 UDP
|
||||
NET_PROTO_TCP = 0x2 ///< 连接类型 TCP
|
||||
NET_PROTO_UDP = 0x1,
|
||||
NET_PROTO_TCP = 0x2
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 返回类型定义
|
||||
*/
|
||||
enum MT_RC_TYPE
|
||||
{
|
||||
RC_SUCCESS = 0,
|
||||
RC_ERR_SOCKET = -1, ///< 创建socket失败
|
||||
RC_SEND_FAIL = -2, ///< 发送失败
|
||||
RC_RECV_FAIL = -3, ///< 接收失败
|
||||
RC_CONNECT_FAIL = -4, ///< 连接失败
|
||||
RC_CHECK_PKG_FAIL = -5, ///< 报文检测失败
|
||||
RC_NO_MORE_BUFF = -6, ///< 空间超过限制
|
||||
RC_REMOTE_CLOSED = -7, ///< 后端关闭连接
|
||||
RC_ERR_SOCKET = -1,
|
||||
RC_SEND_FAIL = -2,
|
||||
RC_RECV_FAIL = -3,
|
||||
RC_CONNECT_FAIL = -4,
|
||||
RC_CHECK_PKG_FAIL = -5,
|
||||
RC_NO_MORE_BUFF = -6,
|
||||
RC_REMOTE_CLOSED = -7,
|
||||
|
||||
RC_INVALID_PARAM = -10, ///< 无效参数
|
||||
RC_INVALID_HANDLER = -11, ///< 无效的句柄
|
||||
RC_MEM_ERROR = -12, ///< 内存异常
|
||||
RC_CONFLICT_SID = -13, ///< SESSION ID冲突
|
||||
RC_KQUEUE_ERROR = -14, ///< rst信号等
|
||||
RC_INVALID_PARAM = -10,
|
||||
RC_INVALID_HANDLER = -11,
|
||||
RC_MEM_ERROR = -12,
|
||||
RC_CONFLICT_SID = -13,
|
||||
RC_KQUEUE_ERROR = -14,
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief 检查报文是否完整, 并获取session的回调函数
|
||||
* @info 提供need_len参数的原因, 对于无法确认报文长度时, 可以每次扩展希望长度
|
||||
* 如果依赖返回值的隐含规则, 将无法处理这种情况
|
||||
* @param data -实际接收的数据指针
|
||||
* @param len -已经接收或准备的长度
|
||||
* @param session_id -成功解析的sessionid信息
|
||||
* @param need_len -希望扩展一下buff, 目前最大100M
|
||||
* @return >0 成功解析返回实际的包长度; =0 报文不完整, 期望接收更多数据; <0 解析失败
|
||||
*/
|
||||
typedef int32_t (*CHECK_SESSION_CALLBACK)(const void* data, uint32_t len,
|
||||
uint64_t* session_id, uint32_t* need_len);
|
||||
|
||||
|
||||
/**
|
||||
* @brief 网络接口类定义
|
||||
*/
|
||||
class CNetHelper
|
||||
{
|
||||
public:
|
||||
|
||||
// 转发返回码信息, 按需获取
|
||||
static char* GetErrMsg(int32_t result);
|
||||
|
||||
// 同步收发接口
|
||||
int32_t SendRecv(void* data, uint32_t len, uint32_t timeout);
|
||||
|
||||
// 获取返回buff信息, 有效期直到helper析构
|
||||
void* GetRspBuff();
|
||||
|
||||
// 获取返回包的长度
|
||||
uint32_t GetRspLen();
|
||||
|
||||
// 设置协议的类型, 默认UDP
|
||||
void SetProtoType(MT_PROTO_TYPE type);
|
||||
|
||||
// 设置目的IP地址
|
||||
void SetDestAddress(struct sockaddr_in* dst);
|
||||
void SetDestAddress(struct sockaddr_in* dst);
|
||||
|
||||
// 设置session本次session id信息, 必须非0
|
||||
void SetSessionId(uint64_t sid);
|
||||
void SetSessionId(uint64_t sid);
|
||||
|
||||
// 设置session解析回调函数
|
||||
void SetSessionCallback(CHECK_SESSION_CALLBACK function);
|
||||
|
||||
// 构造与虚构
|
||||
CNetHelper();
|
||||
~CNetHelper();
|
||||
|
||||
private:
|
||||
|
||||
void* handler; // 私有句柄, 利于扩展
|
||||
void* handler;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
|
||||
/**
|
||||
* @file mt_notify.cpp
|
||||
* @info 微线程调度注册对象管理实现
|
||||
* @time 20130924
|
||||
**/
|
||||
#include <fcntl.h>
|
||||
|
@ -39,11 +38,6 @@
|
|||
using namespace std;
|
||||
using namespace NS_MICRO_THREAD;
|
||||
|
||||
|
||||
/**
|
||||
* @brief 通知代理进入等待状态, 挂入等待队列中
|
||||
* @param proxy 代理的session模型
|
||||
*/
|
||||
void ISessionNtfy::InsertWriteWait(SessionProxy* proxy)
|
||||
{
|
||||
if (!proxy->_flag) {
|
||||
|
@ -52,10 +46,6 @@ void ISessionNtfy::InsertWriteWait(SessionProxy* proxy)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 通知代理移除等待状态
|
||||
* @param proxy 代理的session模型
|
||||
*/
|
||||
void ISessionNtfy::RemoveWriteWait(SessionProxy* proxy)
|
||||
{
|
||||
if (proxy->_flag) {
|
||||
|
@ -64,10 +54,6 @@ void ISessionNtfy::RemoveWriteWait(SessionProxy* proxy)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 观察者模式, 通知写等待线程
|
||||
* @info UDP可以通知每个线程执行写操作, TCP需要排队写
|
||||
*/
|
||||
void UdpSessionNtfy::NotifyWriteWait()
|
||||
{
|
||||
MtFrame* frame = MtFrame::Instance();
|
||||
|
@ -86,21 +72,15 @@ void UdpSessionNtfy::NotifyWriteWait()
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 创建socket, 监听可读事件
|
||||
* @return fd的句柄, <0 失败
|
||||
*/
|
||||
int UdpSessionNtfy::CreateSocket()
|
||||
{
|
||||
// 1. UDP短连接, 每次新创SOCKET
|
||||
int osfd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (osfd < 0)
|
||||
{
|
||||
MTLOG_ERROR("socket create failed, errno %d(%s)", errno, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 2. 非阻塞设置
|
||||
|
||||
int flags = 1;
|
||||
if (ioctl(osfd, FIONBIO, &flags) < 0)
|
||||
{
|
||||
|
@ -110,7 +90,6 @@ int UdpSessionNtfy::CreateSocket()
|
|||
return -2;
|
||||
}
|
||||
|
||||
// 可选bind执行, 设置本地port后执行
|
||||
if (_local_addr.sin_port != 0)
|
||||
{
|
||||
int ret = bind(osfd, (struct sockaddr *)&_local_addr, sizeof(_local_addr));
|
||||
|
@ -124,7 +103,6 @@ int UdpSessionNtfy::CreateSocket()
|
|||
}
|
||||
}
|
||||
|
||||
// 3. 更新管理信息, 默认udp session 侦听 epollin
|
||||
this->SetOsfd(osfd);
|
||||
this->EnableInput();
|
||||
MtFrame* frame = MtFrame::Instance();
|
||||
|
@ -134,10 +112,6 @@ int UdpSessionNtfy::CreateSocket()
|
|||
return osfd;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 关闭socket, 停止监听可读事件
|
||||
*/
|
||||
void UdpSessionNtfy::CloseSocket()
|
||||
{
|
||||
int osfd = this->GetOsfd();
|
||||
|
@ -152,11 +126,6 @@ void UdpSessionNtfy::CloseSocket()
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 可读事件通知接口, 考虑通知处理可能会破坏环境, 可用返回值区分
|
||||
* @return 0 该fd可继续处理其它事件; !=0 该fd需跳出回调处理
|
||||
*/
|
||||
int UdpSessionNtfy::InputNotify()
|
||||
{
|
||||
while (1)
|
||||
|
@ -164,7 +133,6 @@ int UdpSessionNtfy::InputNotify()
|
|||
int ret = 0;
|
||||
int have_rcv_len = 0;
|
||||
|
||||
// 1. 获取收包缓冲区, 优先选择未处理完的链接buff
|
||||
if (!_msg_buff) {
|
||||
_msg_buff = MsgBuffPool::Instance()->GetMsgBuf(this->GetMsgBuffSize());
|
||||
if (NULL == _msg_buff) {
|
||||
|
@ -175,7 +143,6 @@ int UdpSessionNtfy::InputNotify()
|
|||
}
|
||||
char* buff = (char*)_msg_buff->GetMsgBuff();
|
||||
|
||||
// 2. 获取socket, 收包处理
|
||||
int osfd = this->GetOsfd();
|
||||
struct sockaddr_in from;
|
||||
socklen_t fromlen = sizeof(from);
|
||||
|
@ -191,13 +158,13 @@ int UdpSessionNtfy::InputNotify()
|
|||
else
|
||||
{
|
||||
MTLOG_ERROR("recv error, fd %d", osfd);
|
||||
return 0; // 系统错误, UDP 暂不关闭
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else if (ret == 0)
|
||||
{
|
||||
MTLOG_DEBUG("remote close connection, fd %d", osfd);
|
||||
return 0; // 对端关闭, UDP 暂不关闭
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -206,7 +173,6 @@ int UdpSessionNtfy::InputNotify()
|
|||
_msg_buff->SetMsgLen(have_rcv_len);
|
||||
}
|
||||
|
||||
// 3. 检查消息的完整性, 提取sessionid
|
||||
int sessionid = 0;
|
||||
ret = this->GetSessionId(buff, have_rcv_len, sessionid);
|
||||
if (ret <= 0)
|
||||
|
@ -218,18 +184,16 @@ int UdpSessionNtfy::InputNotify()
|
|||
return 0;
|
||||
}
|
||||
|
||||
// 4. 映射查询thread句柄, 连接handle句柄, 设置读事件来临, 挂接msgbuff
|
||||
ISession* session = SessionMgr::Instance()->FindSession(sessionid);
|
||||
if (NULL == session)
|
||||
{
|
||||
MT_ATTR_API(350403, 1); // session 到达已超时
|
||||
MT_ATTR_API(350403, 1);
|
||||
MTLOG_DEBUG("session %d, not find, maybe timeout, drop pkg", sessionid);
|
||||
MsgBuffPool::Instance()->FreeMsgBuf(_msg_buff);
|
||||
_msg_buff = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 5. 挂接recvbuff, 唤醒线程
|
||||
IMtConnection* conn = session->GetSessionConn();
|
||||
MicroThread* thread = session->GetOwnerThread();
|
||||
if (!thread || !conn || !conn->GetNtfyObj())
|
||||
|
@ -259,43 +223,26 @@ int UdpSessionNtfy::InputNotify()
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 可写事件通知接口, 考虑通知处理可能会破坏环境, 可用返回值区分
|
||||
* @return 0 该fd可继续处理其它事件; !=0 该fd需跳出回调处理
|
||||
*/
|
||||
int UdpSessionNtfy::OutputNotify()
|
||||
{
|
||||
NotifyWriteWait();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 异常通知接口, 关闭fd侦听, thread等待处理超时
|
||||
* @return 忽略返回值, 跳过其它事件处理
|
||||
*/
|
||||
int UdpSessionNtfy::HangupNotify()
|
||||
{
|
||||
// 1. 清理epoll ctl监听事件
|
||||
MtFrame* frame = MtFrame::Instance();
|
||||
frame->KqueueCtrlDel(this->GetOsfd(), this->GetEvents());
|
||||
|
||||
MTLOG_ERROR("sesson obj %p, recv error event. fd %d", this, this->GetOsfd());
|
||||
|
||||
// 2. 重新打开socket
|
||||
|
||||
CloseSocket();
|
||||
|
||||
// 3. 重加入epoll listen
|
||||
CreateSocket();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 调整epoll侦听事件的回调接口, 长连接始终EPOLLIN, 偶尔EPOLLOUT
|
||||
* @param args fd引用对象的指针
|
||||
* @return 0 成功, < 0 失败, 要求事务回滚到操作前状态
|
||||
* @info 默认是监听可读事件的, 这里只处理可写事件的监听删除
|
||||
*/
|
||||
int UdpSessionNtfy::KqueueCtlAdd(void* args)
|
||||
{
|
||||
MtFrame* frame = MtFrame::Instance();
|
||||
|
@ -304,7 +251,6 @@ int UdpSessionNtfy::KqueueCtlAdd(void* args)
|
|||
|
||||
int osfd = this->GetOsfd();
|
||||
|
||||
// 通知对象需要更新, FD通知对象理论上不会复用, 这里做冲突检查, 异常log记录
|
||||
KqueuerObj* old_obj = fd_ref->GetNotifyObj();
|
||||
if ((old_obj != NULL) && (old_obj != this))
|
||||
{
|
||||
|
@ -312,7 +258,6 @@ int UdpSessionNtfy::KqueueCtlAdd(void* args)
|
|||
return -1;
|
||||
}
|
||||
|
||||
// 调用框架的epoll ctl接口, 屏蔽epoll ctrl细节
|
||||
if (!frame->KqueueCtrlAdd(osfd, KQ_EVENT_WRITE))
|
||||
{
|
||||
MTLOG_ERROR("epfd ref add failed, log");
|
||||
|
@ -323,11 +268,6 @@ int UdpSessionNtfy::KqueueCtlAdd(void* args)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 调整epoll侦听事件的回调接口, 长连接始终EPOLLIN, 偶尔EPOLLOUT
|
||||
* @param args fd引用对象的指针
|
||||
* @return 0 成功, < 0 失败, 要求事务回滚到操作前状态
|
||||
*/
|
||||
int UdpSessionNtfy::KqueueCtlDel(void* args)
|
||||
{
|
||||
MtFrame* frame = MtFrame::Instance();
|
||||
|
@ -335,8 +275,7 @@ int UdpSessionNtfy::KqueueCtlDel(void* args)
|
|||
//ASSERT(fd_ref != NULL);
|
||||
|
||||
int osfd = this->GetOsfd();
|
||||
|
||||
// 通知对象需要更新, FD通知对象理论上不会复用, 这里做冲突检查, 异常log记录
|
||||
|
||||
KqueuerObj* old_obj = fd_ref->GetNotifyObj();
|
||||
if (old_obj != this)
|
||||
{
|
||||
|
@ -344,7 +283,6 @@ int UdpSessionNtfy::KqueueCtlDel(void* args)
|
|||
return -1;
|
||||
}
|
||||
|
||||
// 调用框架的epoll ctl接口, 屏蔽epoll ctrl细节
|
||||
if (!frame->KqueueCtrlDel(osfd, KQ_EVENT_WRITE))
|
||||
{
|
||||
MTLOG_ERROR("epfd ref del failed, log");
|
||||
|
@ -356,41 +294,24 @@ int UdpSessionNtfy::KqueueCtlDel(void* args)
|
|||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 可读事件通知接口, 考虑通知处理可能会破坏环境, 可用返回值区分
|
||||
* @return 0 该fd可继续处理其它事件; !=0 该fd需跳出回调处理
|
||||
*/
|
||||
int TcpKeepNtfy::InputNotify()
|
||||
{
|
||||
KeepaliveClose();
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 可写事件通知接口, 考虑通知处理可能会破坏环境, 可用返回值区分
|
||||
* @return 0 该fd可继续处理其它事件; !=0 该fd需跳出回调处理
|
||||
*/
|
||||
|
||||
int TcpKeepNtfy::OutputNotify()
|
||||
{
|
||||
KeepaliveClose();
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 异常通知接口
|
||||
* @return 忽略返回值, 跳过其它事件处理
|
||||
*/
|
||||
|
||||
int TcpKeepNtfy::HangupNotify()
|
||||
{
|
||||
KeepaliveClose();
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 触发实际连接关闭操作
|
||||
*/
|
||||
void TcpKeepNtfy::KeepaliveClose()
|
||||
{
|
||||
if (_keep_conn) {
|
||||
|
@ -400,12 +321,7 @@ void TcpKeepNtfy::KeepaliveClose()
|
|||
MTLOG_ERROR("_keep_conn ptr null, error");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief session全局管理句柄
|
||||
* @return 全局句柄指针
|
||||
*/
|
||||
NtfyObjMgr* NtfyObjMgr::_instance = NULL;
|
||||
NtfyObjMgr* NtfyObjMgr::Instance (void)
|
||||
{
|
||||
|
@ -417,9 +333,6 @@ NtfyObjMgr* NtfyObjMgr::Instance (void)
|
|||
return _instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief session管理全局的销毁接口
|
||||
*/
|
||||
void NtfyObjMgr::Destroy()
|
||||
{
|
||||
if( _instance != NULL )
|
||||
|
@ -429,26 +342,14 @@ void NtfyObjMgr::Destroy()
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 消息buff的构造函数
|
||||
*/
|
||||
NtfyObjMgr::NtfyObjMgr()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 析构函数, 不持有资源, 并不负责清理
|
||||
*/
|
||||
NtfyObjMgr::~NtfyObjMgr()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 注册长连接session信息
|
||||
* @param session_name 长连接的标识, 每个连接处理一类session封装格式
|
||||
* @param session 长连接对象指针, 定义连接属性
|
||||
* @return 0 成功, < 0 失败
|
||||
*/
|
||||
int NtfyObjMgr::RegisterSession(int session_name, ISessionNtfy* session)
|
||||
{
|
||||
if (session_name <= 0 || NULL == session) {
|
||||
|
@ -468,11 +369,6 @@ int NtfyObjMgr::RegisterSession(int session_name, ISessionNtfy* session)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 获取注册长连接session信息
|
||||
* @param session_name 长连接的标识, 每个连接处理一类session封装格式
|
||||
* @return 长连接指针, 失败为NULL
|
||||
*/
|
||||
ISessionNtfy* NtfyObjMgr::GetNameSession(int session_name)
|
||||
{
|
||||
SessionMap::iterator it = _session_map.find(session_name);
|
||||
|
@ -486,12 +382,6 @@ ISessionNtfy* NtfyObjMgr::GetNameSession(int session_name)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 获取通用通知对象, 如线程通知对象与session通知代理对象
|
||||
* @param type 类型, 线程通知类型,UDP/TCP SESSION通知等
|
||||
* @param session_name proxy模型,一并获取session对象
|
||||
* @return 通知对象的指针, 失败为NULL
|
||||
*/
|
||||
KqueuerObj* NtfyObjMgr::GetNtfyObj(int type, int session_name)
|
||||
{
|
||||
KqueuerObj* obj = NULL;
|
||||
|
@ -515,7 +405,6 @@ KqueuerObj* NtfyObjMgr::GetNtfyObj(int type, int session_name)
|
|||
break;
|
||||
}
|
||||
|
||||
// 获取底层的长连接对象, 关联代理与实际的通知对象
|
||||
if (proxy) {
|
||||
ISessionNtfy* ntfy = this->GetNameSession(session_name);
|
||||
if (!ntfy) {
|
||||
|
@ -531,10 +420,6 @@ KqueuerObj* NtfyObjMgr::GetNtfyObj(int type, int session_name)
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 释放通知对象指针
|
||||
* @param obj 通知对象
|
||||
*/
|
||||
void NtfyObjMgr::FreeNtfyObj(KqueuerObj* obj)
|
||||
{
|
||||
SessionProxy* proxy = NULL;
|
||||
|
@ -566,6 +451,3 @@ void NtfyObjMgr::FreeNtfyObj(KqueuerObj* obj)
|
|||
delete obj;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
|
||||
/**
|
||||
* @file mt_notify.h
|
||||
* @info 微线程注册的通知对象定义与管理
|
||||
* @time 20130926
|
||||
**/
|
||||
|
||||
|
@ -39,91 +38,43 @@ using std::map;
|
|||
class SessionProxy;
|
||||
class TcpKeepConn;
|
||||
|
||||
/**
|
||||
* @brief 通知对象类型
|
||||
*/
|
||||
enum NTFY_OBJ_TYPE
|
||||
{
|
||||
NTFY_OBJ_UNDEF = 0, ///< 未定义的连接对象
|
||||
NTFY_OBJ_THREAD = 1, ///< 短连接对象, 一个fd对应一个thread
|
||||
NTFY_OBJ_KEEPALIVE = 2, ///< TCP心跳保持的notify对象, 不关联 thread
|
||||
NTFY_OBJ_SESSION = 3, ///< UDP的session模型, 代理的长连接对象
|
||||
NTFY_OBJ_UNDEF = 0,
|
||||
NTFY_OBJ_THREAD = 1,
|
||||
NTFY_OBJ_KEEPALIVE = 2,
|
||||
NTFY_OBJ_SESSION = 3,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 协议类型定义
|
||||
*/
|
||||
enum MULTI_PROTO
|
||||
{
|
||||
MT_UNKNOWN = 0,
|
||||
MT_UDP = 0x1, ///< 连接类型 UDP
|
||||
MT_TCP = 0x2 ///< 连接类型 TCP
|
||||
MT_UDP = 0x1,
|
||||
MT_TCP = 0x2
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 长连接session模型, 批量收发调度管理接口
|
||||
*/
|
||||
typedef TAILQ_ENTRY(SessionProxy) NtfyEntry;
|
||||
typedef TAILQ_HEAD(__NtfyList, SessionProxy) NtfyList;
|
||||
class ISessionNtfy : public KqueuerObj
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief 检查报文完整性, 同时提取sessionid信息
|
||||
* @param pkg 报文指针
|
||||
* @param len 报文已接收长度
|
||||
* @param session 解析的sessionid, 输出参数
|
||||
* @return <=0 失败, >0 实际报文长度
|
||||
*/
|
||||
virtual int GetSessionId(void* pkg, int len, int& session) { return 0;};
|
||||
|
||||
/**
|
||||
* @brief 创建socket, 监听可读事件
|
||||
* @return fd的句柄, <0 失败
|
||||
*/
|
||||
virtual int CreateSocket(){return -1;};
|
||||
|
||||
/**
|
||||
* @brief 关闭socket, 停止监听可读事件
|
||||
*/
|
||||
virtual void CloseSocket(){};
|
||||
|
||||
/**
|
||||
* @brief 可读事件通知接口, 考虑通知处理可能会破坏环境, 可用返回值区分
|
||||
* @return 0 该fd可继续处理其它事件; !=0 该fd需跳出回调处理
|
||||
*/
|
||||
virtual int InputNotify(){return 0;};
|
||||
|
||||
/**
|
||||
* @brief 可写事件通知接口, 考虑通知处理可能会破坏环境, 可用返回值区分
|
||||
* @return 0 该fd可继续处理其它事件; !=0 该fd需跳出回调处理
|
||||
*/
|
||||
virtual int OutputNotify(){return 0;};
|
||||
|
||||
/**
|
||||
* @brief 异常通知接口
|
||||
* @return 忽略返回值, 跳过其它事件处理
|
||||
*/
|
||||
|
||||
virtual int HangupNotify(){return 0;};
|
||||
|
||||
/**
|
||||
* @brief 调整epoll侦听事件的回调接口, 长连接始终EPOLLIN, 偶尔EPOLLOUT
|
||||
* @param args fd引用对象的指针
|
||||
* @return 0 成功, < 0 失败, 要求事务回滚到操作前状态
|
||||
*/
|
||||
virtual int KqueueCtlAdd(void* args){return 0;};
|
||||
|
||||
/**
|
||||
* @brief 调整epoll侦听事件的回调接口, 长连接始终EPOLLIN, 偶尔EPOLLOUT
|
||||
* @param args fd引用对象的指针
|
||||
* @return 0 成功, < 0 失败, 要求事务回滚到操作前状态
|
||||
*/
|
||||
virtual int KqueueCtlDel(void* args){return 0;};
|
||||
|
||||
/**
|
||||
* @brief 构造函数析构函数
|
||||
*/
|
||||
ISessionNtfy(): KqueuerObj(0) {
|
||||
_proto = MT_UDP;
|
||||
_buff_size = 0;
|
||||
|
@ -132,85 +83,46 @@ public:
|
|||
}
|
||||
virtual ~ISessionNtfy() { };
|
||||
|
||||
/**
|
||||
* @brief 设置本次处理的proto信息
|
||||
*/
|
||||
void SetProtoType(MULTI_PROTO proto) {
|
||||
_proto = proto;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 获取本次处理的proto信息
|
||||
* @return proto type
|
||||
*/
|
||||
MULTI_PROTO GetProtoType() {
|
||||
return _proto;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 设置buff大小, 决定实际使用的msgbuff队列
|
||||
* @return 0成功
|
||||
*/
|
||||
|
||||
void SetMsgBuffSize(int buff_size) {
|
||||
_buff_size = buff_size;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 获取预置的buff大小, 如无设置, 返回65535
|
||||
* @return 框架申请的消息buff最大长度
|
||||
*/
|
||||
int GetMsgBuffSize() {
|
||||
return (_buff_size > 0) ? _buff_size : 65535;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 通知代理进入等待状态
|
||||
*/
|
||||
void InsertWriteWait(SessionProxy* proxy);
|
||||
|
||||
/**
|
||||
* @brief 通知代理取消等待状态
|
||||
*/
|
||||
void RemoveWriteWait(SessionProxy* proxy);
|
||||
|
||||
/**
|
||||
* @brief 观察者模式, 通知写等待线程
|
||||
* @info UDP可以通知每个线程执行写操作, TCP需要排队写
|
||||
*/
|
||||
|
||||
virtual void NotifyWriteWait(){};
|
||||
|
||||
protected:
|
||||
MULTI_PROTO _proto; // 协议类型 UDP/TCP
|
||||
int _buff_size; // 最大消息长度
|
||||
NtfyList _write_list; // 可写等待队列
|
||||
MtMsgBuf* _msg_buff; // 临时收包存放缓冲区
|
||||
MULTI_PROTO _proto;
|
||||
int _buff_size;
|
||||
NtfyList _write_list;
|
||||
MtMsgBuf* _msg_buff;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief UDP长连接session模型的基类接口
|
||||
* @info 业务session需要继承该接口, 设置属性, 实现获取GetSessionId函数
|
||||
* @info 保留扩展, 如指定本地端口等
|
||||
*/
|
||||
class UdpSessionNtfy : public ISessionNtfy
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief 检查报文完整性, 同时提取sessionid信息, 由继承类实现它
|
||||
* @param pkg 报文指针
|
||||
* @param len 报文已接收长度
|
||||
* @param session 解析的sessionid, 输出参数
|
||||
* @return <=0 失败, >0 实际报文长度
|
||||
*/
|
||||
|
||||
virtual int GetSessionId(void* pkg, int len, int& session) { return 0;};
|
||||
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief 构造与析构函数
|
||||
*/
|
||||
UdpSessionNtfy() : ISessionNtfy(){
|
||||
ISessionNtfy::SetProtoType(MT_UDP);
|
||||
|
||||
|
@ -220,61 +132,24 @@ public:
|
|||
}
|
||||
virtual ~UdpSessionNtfy() { };
|
||||
|
||||
/**
|
||||
* @brief 观察者模式, 通知写等待线程
|
||||
* @info UDP可以通知每个线程执行写操作, TCP需要排队写
|
||||
*/
|
||||
virtual void NotifyWriteWait();
|
||||
|
||||
/**
|
||||
* @brief 创建socket, 监听可读事件
|
||||
* @return fd的句柄, <0 失败
|
||||
*/
|
||||
virtual int CreateSocket();
|
||||
|
||||
/**
|
||||
* @brief 关闭socket, 停止监听可读事件
|
||||
*/
|
||||
virtual void CloseSocket();
|
||||
|
||||
/**
|
||||
* @brief 可读事件通知接口, 考虑通知处理可能会破坏环境, 可用返回值区分
|
||||
* @return 0 该fd可继续处理其它事件; !=0 该fd需跳出回调处理
|
||||
*/
|
||||
virtual int InputNotify();
|
||||
|
||||
/**
|
||||
* @brief 可写事件通知接口, 考虑通知处理可能会破坏环境, 可用返回值区分
|
||||
* @return 0 该fd可继续处理其它事件; !=0 该fd需跳出回调处理
|
||||
*/
|
||||
|
||||
virtual int OutputNotify();
|
||||
|
||||
/**
|
||||
* @brief 异常通知接口
|
||||
* @return 忽略返回值, 跳过其它事件处理
|
||||
*/
|
||||
|
||||
virtual int HangupNotify();
|
||||
|
||||
/**
|
||||
* @brief 调整epoll侦听事件的回调接口, 长连接始终EPOLLIN, 偶尔EPOLLOUT
|
||||
* @param args fd引用对象的指针
|
||||
* @return 0 成功, < 0 失败, 要求事务回滚到操作前状态
|
||||
*/
|
||||
virtual int KqueueCtlAdd(void* args);
|
||||
|
||||
/**
|
||||
* @brief 调整epoll侦听事件的回调接口, 长连接始终EPOLLIN, 偶尔EPOLLOUT
|
||||
* @param args fd引用对象的指针
|
||||
* @return 0 成功, < 0 失败, 要求事务回滚到操作前状态
|
||||
*/
|
||||
virtual int KqueueCtlDel(void* args);
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief 设置udp本地的本地bind地址, 多进程bind会冲突, 暂时停用
|
||||
* 后续开放, 能保证每进程唯一port可使用
|
||||
*/
|
||||
void SetLocalAddr(struct sockaddr_in* local_addr) {
|
||||
memcpy(&_local_addr, local_addr, sizeof(_local_addr));
|
||||
};
|
||||
|
@ -285,47 +160,28 @@ protected:
|
|||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief UDP模式session模型的代理通知对象, 多个代理映射到某一个session notify
|
||||
* @info session proxy 本身不在epoll注册, 不会有事件通知, 但需要关心超时等
|
||||
*/
|
||||
class SessionProxy : public KqueuerObj
|
||||
{
|
||||
public:
|
||||
int _flag; ///< 0-不在队列中, 1-在等待队列
|
||||
NtfyEntry _write_entry; ///< 关联可写等待队列的管理入口
|
||||
int _flag;
|
||||
NtfyEntry _write_entry;
|
||||
|
||||
/**
|
||||
* @brief 设置代理对象, 关联代理的fd句柄
|
||||
*/
|
||||
void SetRealNtfyObj(ISessionNtfy* obj) {
|
||||
_real_ntfy = obj;
|
||||
this->SetOsfd(obj->GetOsfd());
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 获取代理对象指针
|
||||
*/
|
||||
|
||||
ISessionNtfy* GetRealNtfyObj() {
|
||||
return _real_ntfy;
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief 回收处理, 设置清理动作
|
||||
*/
|
||||
virtual void Reset() {
|
||||
_real_ntfy = NULL;
|
||||
this->KqueuerObj::Reset();
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 调整epoll侦听事件的回调接口, 长连接始终EPOLLIN, 偶尔EPOLLOUT
|
||||
* @param args fd引用对象的指针
|
||||
* @return 0 成功, < 0 失败, 要求事务回滚到操作前状态
|
||||
*/
|
||||
virtual int KqueueCtlAdd(void* args) {
|
||||
if (!_real_ntfy) {
|
||||
return -1;
|
||||
|
@ -344,11 +200,6 @@ public:
|
|||
return 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 调整epoll侦听事件的回调接口, 长连接始终EPOLLIN, 偶尔EPOLLOUT
|
||||
* @param args fd引用对象的指针
|
||||
* @return 0 成功, < 0 失败, 要求事务回滚到操作前状态
|
||||
*/
|
||||
virtual int KqueueCtlDel(void* args) {
|
||||
if (!_real_ntfy) {
|
||||
return -1;
|
||||
|
@ -364,86 +215,48 @@ public:
|
|||
};
|
||||
|
||||
private:
|
||||
ISessionNtfy* _real_ntfy; // 实际的执行者
|
||||
ISessionNtfy* _real_ntfy;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief TCP模式的keepalive通知对象, 仅仅关心可读事件, 确认是否对端关闭
|
||||
*/
|
||||
class TcpKeepNtfy: public KqueuerObj
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief 构造函数
|
||||
*/
|
||||
TcpKeepNtfy() : _keep_conn(NULL){};
|
||||
|
||||
/**
|
||||
* @brief 可读事件通知接口, 考虑通知处理可能会破坏环境, 可用返回值区分
|
||||
* @return 0 该fd可继续处理其它事件; !=0 该fd需跳出回调处理
|
||||
*/
|
||||
virtual int InputNotify();
|
||||
|
||||
/**
|
||||
* @brief 可写事件通知接口, 考虑通知处理可能会破坏环境, 可用返回值区分
|
||||
* @return 0 该fd可继续处理其它事件; !=0 该fd需跳出回调处理
|
||||
*/
|
||||
|
||||
virtual int OutputNotify();
|
||||
|
||||
/**
|
||||
* @brief 异常通知接口
|
||||
* @return 忽略返回值, 跳过其它事件处理
|
||||
*/
|
||||
|
||||
virtual int HangupNotify();
|
||||
|
||||
/**
|
||||
* @brief 设置代理对象
|
||||
*/
|
||||
void SetKeepNtfyObj(TcpKeepConn* obj) {
|
||||
_keep_conn = obj;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 获取代理对象指针
|
||||
*/
|
||||
TcpKeepConn* GetKeepNtfyObj() {
|
||||
return _keep_conn;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 触发实际连接关闭操作
|
||||
*/
|
||||
|
||||
void KeepaliveClose();
|
||||
|
||||
|
||||
private:
|
||||
TcpKeepConn* _keep_conn; // 实际的连接器对象
|
||||
TcpKeepConn* _keep_conn;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief 动态内存池模板类, 对于反复new/delete的对象操作, 可一定程度上提高性能
|
||||
*/
|
||||
template<typename ValueType>
|
||||
class CPtrPool
|
||||
{
|
||||
public:
|
||||
typedef typename std::queue<ValueType*> PtrQueue; ///< 内存指针队列
|
||||
typedef typename std::queue<ValueType*> PtrQueue;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief 动态内存池构造函数
|
||||
* @param max 最大空闲队列保存的指针元素, 默认500
|
||||
*/
|
||||
explicit CPtrPool(int max = 500) : _max_free(max), _total(0){};
|
||||
|
||||
/**
|
||||
* @brief 动态内存池析构函数, 仅仅清理掉freelist
|
||||
*/
|
||||
|
||||
~CPtrPool() {
|
||||
ValueType* ptr = NULL;
|
||||
while (!_ptr_list.empty()) {
|
||||
|
@ -453,10 +266,6 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 分配内存指针, 优先从缓存获取, 无空闲可用则动态 new 申请
|
||||
* @return 模板类型的指针元素, 空表示内存申请失败
|
||||
*/
|
||||
ValueType* AllocPtr() {
|
||||
ValueType* ptr = NULL;
|
||||
if (!_ptr_list.empty()) {
|
||||
|
@ -470,9 +279,6 @@ public:
|
|||
return ptr;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 释放内存指针, 若空闲队列超过配额, 则直接释放, 否则队列缓存
|
||||
*/
|
||||
void FreePtr(ValueType* ptr) {
|
||||
if ((int)_ptr_list.size() >= _max_free) {
|
||||
delete ptr;
|
||||
|
@ -483,15 +289,11 @@ public:
|
|||
};
|
||||
|
||||
protected:
|
||||
PtrQueue _ptr_list; ///< 空闲队列
|
||||
int _max_free; ///< 最大空闲元素
|
||||
int _total; ///< 所有new的对象个数统计
|
||||
PtrQueue _ptr_list;
|
||||
int _max_free;
|
||||
int _total;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief 通知对象全局管理器
|
||||
*/
|
||||
class NtfyObjMgr
|
||||
{
|
||||
public:
|
||||
|
@ -499,70 +301,31 @@ public:
|
|||
typedef std::map<int, ISessionNtfy*> SessionMap;
|
||||
typedef CPtrPool<KqueuerObj> NtfyThreadQueue;
|
||||
typedef CPtrPool<SessionProxy> NtfySessionQueue;
|
||||
|
||||
/**
|
||||
* @brief 会话上下文的全局管理句柄接口
|
||||
* @return 全局句柄指针
|
||||
*/
|
||||
|
||||
static NtfyObjMgr* Instance (void);
|
||||
|
||||
/**
|
||||
* @brief 清理接口
|
||||
*/
|
||||
static void Destroy(void);
|
||||
|
||||
/**
|
||||
* @brief 注册长连接session信息
|
||||
* @param session_name 长连接的标识, 每个连接处理一类session封装格式
|
||||
* @param session 长连接对象指针, 定义连接属性
|
||||
* @return 0 成功, < 0 失败
|
||||
*/
|
||||
int RegisterSession(int session_name, ISessionNtfy* session);
|
||||
|
||||
/**
|
||||
* @brief 获取注册长连接session信息
|
||||
* @param session_name 长连接的标识, 每个连接处理一类session封装格式
|
||||
* @return 长连接指针, 失败为NULL
|
||||
*/
|
||||
ISessionNtfy* GetNameSession(int session_name);
|
||||
|
||||
/**
|
||||
* @brief 获取通用通知对象, 如线程通知对象与session通知代理对象
|
||||
* @param type 类型, 线程通知类型,UDP/TCP SESSION通知等
|
||||
* @param session_name proxy模型,一并获取session对象
|
||||
* @return 通知对象的指针, 失败为NULL
|
||||
*/
|
||||
KqueuerObj* GetNtfyObj(int type, int session_name = 0);
|
||||
|
||||
|
||||
/**
|
||||
* @brief 释放通知对象指针
|
||||
* @param obj 通知对象
|
||||
*/
|
||||
void FreeNtfyObj(KqueuerObj* obj);
|
||||
|
||||
/**
|
||||
* @brief 析构函数
|
||||
*/
|
||||
~NtfyObjMgr();
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* @brief 消息buff的构造函数
|
||||
*/
|
||||
NtfyObjMgr();
|
||||
|
||||
static NtfyObjMgr * _instance; ///< 单例类句柄
|
||||
SessionMap _session_map; ///< 全局的注册session管理
|
||||
NtfyThreadQueue _fd_ntfy_pool; ///< fd通知对象
|
||||
NtfySessionQueue _udp_proxy_pool; ///< fd通知对象
|
||||
static NtfyObjMgr * _instance;
|
||||
SessionMap _session_map;
|
||||
NtfyThreadQueue _fd_ntfy_pool;
|
||||
NtfySessionQueue _udp_proxy_pool;
|
||||
};
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
|
|
@ -1,251 +0,0 @@
|
|||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "mt_incl.h"
|
||||
#include "micro_thread.h"
|
||||
|
||||
using namespace NS_MICRO_THREAD;
|
||||
|
||||
static bool run = true;
|
||||
|
||||
static struct sockaddr_in addr;
|
||||
|
||||
int mt_tcp_create_sock(void)
|
||||
{
|
||||
int fd;
|
||||
//int flag;
|
||||
|
||||
// ´´½¨socket
|
||||
fd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (fd < 0)
|
||||
{
|
||||
printf("create tcp socket failed, error: %m\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// ÉèÖÃsocket·Ç×èÈû
|
||||
|
||||
/*
|
||||
flag = fcntl(fd, F_GETFL, 0);
|
||||
if (flag == -1)
|
||||
{
|
||||
::close(fd);
|
||||
printf("get fd flags failed, error: %m\n");
|
||||
return -2;
|
||||
}
|
||||
|
||||
if (flag & O_NONBLOCK)
|
||||
return fd;
|
||||
|
||||
if (fcntl(fd, F_SETFL, flag | O_NONBLOCK | O_NDELAY) == -1)
|
||||
{
|
||||
::close(fd);
|
||||
printf("set fd flags failed, error: %m\n");
|
||||
return -3;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
int nb = 1;
|
||||
ioctl(fd, FIONBIO, &nb);
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
void echo(void* arg)
|
||||
{
|
||||
char buf[1024];
|
||||
int ret = 0;
|
||||
int *p = (int *)arg;
|
||||
int clt_fd = *p;
|
||||
printf("start to echo with client: %d\n", clt_fd);
|
||||
while (1) {
|
||||
ret = mt_recv(clt_fd, (void*)buf,1024,0,-1);
|
||||
if(ret<0)
|
||||
{
|
||||
printf("recv client data failed[%m]\n");
|
||||
mt_sleep(1);
|
||||
break;
|
||||
}
|
||||
|
||||
ret = mt_send(clt_fd, (void*)buf, ret, 0, 1000);
|
||||
if (ret < 0) {
|
||||
printf("send client data failed[%m]\n");
|
||||
mt_sleep(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(clt_fd>0) close(clt_fd);
|
||||
delete p;
|
||||
}
|
||||
|
||||
void server(void* arg)
|
||||
{
|
||||
int fd = mt_tcp_create_sock();
|
||||
if(fd<0)
|
||||
{
|
||||
run = false;
|
||||
printf("create listen socket failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
int optval = 1;
|
||||
unsigned optlen = sizeof(optval);
|
||||
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, optlen);
|
||||
|
||||
if (bind(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0)
|
||||
{
|
||||
close(fd);
|
||||
printf("bind failed [%m]\n");
|
||||
return ;
|
||||
}
|
||||
|
||||
if (listen(fd, 1024) < 0)
|
||||
{
|
||||
close(fd);
|
||||
printf("listen failed[%m]\n");
|
||||
return ;
|
||||
}
|
||||
|
||||
int clt_fd = 0;
|
||||
int *p;
|
||||
while(run)
|
||||
{
|
||||
struct sockaddr_in client_addr;
|
||||
int addr_len = sizeof(client_addr);;
|
||||
|
||||
clt_fd = mt_accept(fd, (struct sockaddr*)&client_addr, (socklen_t*)&addr_len, -1);
|
||||
if(clt_fd<0)
|
||||
{
|
||||
mt_sleep(1);
|
||||
continue;
|
||||
}
|
||||
int nb = 1;
|
||||
ioctl(clt_fd, FIONBIO, &nb);
|
||||
p = new int(clt_fd);
|
||||
printf("start a new micro thread to echo with client: %d\n", clt_fd);
|
||||
mt_start_thread((void*)echo, (void *)p);
|
||||
mt_sleep(1);
|
||||
}
|
||||
printf("server exit\n");
|
||||
|
||||
|
||||
}
|
||||
|
||||
struct MsgCtx
|
||||
{
|
||||
int check_count;
|
||||
int msg_id;
|
||||
};
|
||||
|
||||
int TcpMsgChecker(void* buf, int len, bool closed, void* msg_ctx, bool& msg_len_detected)
|
||||
{
|
||||
|
||||
struct MsgCtx* ctx = (struct MsgCtx*)msg_ctx;
|
||||
|
||||
ctx->check_count++;
|
||||
printf("#%d msg check msg times #%d, buf=%p, len=%d, closed=%d\n", ctx->msg_id, ctx->check_count, buf,len,closed);
|
||||
|
||||
if(len<4)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int r_len=ntohl(*(uint32_t*)buf);
|
||||
//if(r_len!=len)
|
||||
// {
|
||||
// return 0;
|
||||
//}
|
||||
msg_len_detected = true;
|
||||
|
||||
return r_len;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
void client(void* arg)
|
||||
{
|
||||
//char buf[1024];
|
||||
|
||||
struct MsgCtx ctx;
|
||||
void* rcv_buf = NULL;
|
||||
int rcv_len = 0;
|
||||
bool keep_rcv_buf = true;
|
||||
int ret = 0;
|
||||
char snd_ch = 1;
|
||||
int count=0;
|
||||
while(true)
|
||||
{
|
||||
rcv_buf = NULL;
|
||||
rcv_len = 1;
|
||||
keep_rcv_buf = (((++count)%2) == 0);
|
||||
ctx.check_count = 0;
|
||||
ctx.msg_id = count;
|
||||
ret = mt_tcpsendrcv_ex((struct sockaddr_in*)&addr, (void*)&snd_ch, 1, rcv_buf, rcv_len,20000, &TcpMsgChecker, (void*)&ctx, MT_TCP_SHORT,keep_rcv_buf);
|
||||
if(ret<0)
|
||||
{
|
||||
printf("client send rcv failed[%m]\n");
|
||||
continue;
|
||||
}
|
||||
printf("#%d client tcp finished: rcv_len=%d, rcv_buf=%p, keep_rcv_buf=%d\n",count, rcv_len, rcv_buf,keep_rcv_buf);
|
||||
|
||||
if(keep_rcv_buf)
|
||||
{
|
||||
if(rcv_buf==NULL)
|
||||
{
|
||||
printf("client should hold rcvbuf, something wrong\n");
|
||||
continue;
|
||||
}
|
||||
free(rcv_buf);
|
||||
}
|
||||
}
|
||||
|
||||
printf("client exit!");
|
||||
}
|
||||
*/
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
|
||||
memset((void*)&addr,0,sizeof(addr));
|
||||
addr.sin_family=AF_INET;
|
||||
addr.sin_addr.s_addr = inet_addr("112.90.143.29");
|
||||
addr.sin_port = htons(19999);
|
||||
|
||||
mt_init_frame(argc, argv);
|
||||
|
||||
mt_start_thread((void*)server,NULL);
|
||||
|
||||
while (run) {
|
||||
mt_sleep(10);
|
||||
}
|
||||
|
||||
printf("main exit");
|
||||
}
|
|
@ -19,7 +19,6 @@
|
|||
|
||||
/**
|
||||
* @file mt_session.cpp
|
||||
* @info 微线程后端连接会话管理实现部分
|
||||
* @time 20130924
|
||||
**/
|
||||
|
||||
|
@ -29,23 +28,15 @@
|
|||
using namespace std;
|
||||
using namespace NS_MICRO_THREAD;
|
||||
|
||||
/**
|
||||
* @brief session接口资源自回收处理
|
||||
*/
|
||||
ISession::~ISession()
|
||||
{
|
||||
if (_session_flg) {
|
||||
SessionMgr* sessionmgr = SessionMgr::Instance();
|
||||
sessionmgr->RemoveSession(_session_id);
|
||||
_session_flg = (int)SESSION_IDLE; // 额外处理, 在remove函数内处理会加大开销
|
||||
_session_flg = (int)SESSION_IDLE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief session全局管理句柄
|
||||
* @return 全局句柄指针
|
||||
*/
|
||||
SessionMgr* SessionMgr::_instance = NULL;
|
||||
SessionMgr* SessionMgr::Instance (void)
|
||||
{
|
||||
|
@ -57,9 +48,6 @@ SessionMgr* SessionMgr::Instance (void)
|
|||
return _instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief session管理全局的销毁接口
|
||||
*/
|
||||
void SessionMgr::Destroy()
|
||||
{
|
||||
if( _instance != NULL )
|
||||
|
@ -69,18 +57,12 @@ void SessionMgr::Destroy()
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 消息buff的构造函数
|
||||
*/
|
||||
SessionMgr::SessionMgr()
|
||||
{
|
||||
_curr_session = 0;
|
||||
_hash_map = new HashList(100000);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 析构函数, 不持有资源, 并不负责清理
|
||||
*/
|
||||
SessionMgr::~SessionMgr()
|
||||
{
|
||||
if (_hash_map) {
|
||||
|
@ -89,9 +71,6 @@ SessionMgr::~SessionMgr()
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Session数据存储
|
||||
*/
|
||||
int SessionMgr::InsertSession(ISession* session)
|
||||
{
|
||||
if (!_hash_map || !session) {
|
||||
|
@ -109,9 +88,6 @@ int SessionMgr::InsertSession(ISession* session)
|
|||
return _hash_map->HashInsert(session);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 查询session数据
|
||||
*/
|
||||
ISession* SessionMgr::FindSession(int session_id)
|
||||
{
|
||||
if (!_hash_map) {
|
||||
|
@ -124,9 +100,6 @@ ISession* SessionMgr::FindSession(int session_id)
|
|||
return dynamic_cast<ISession*>(_hash_map->HashFind(&key));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 删除session数据
|
||||
*/
|
||||
void SessionMgr::RemoveSession(int session_id)
|
||||
{
|
||||
if (!_hash_map) {
|
||||
|
@ -138,5 +111,3 @@ void SessionMgr::RemoveSession(int session_id)
|
|||
key.SetSessionId(session_id);
|
||||
return _hash_map->HashRemove(&key);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
|
||||
/**
|
||||
* @file mt_session.h
|
||||
* @info 微线程的事件会话管理部分, 每个后端连接关联一session信息
|
||||
* @time 20130924
|
||||
**/
|
||||
|
||||
|
@ -35,28 +34,19 @@ class IMtConnection;
|
|||
|
||||
enum SESSION_FLAG
|
||||
{
|
||||
SESSION_IDLE = 0, ///< SESSION 未加入hash管理
|
||||
SESSION_INUSE = 1, ///< SESSION 进入管理状态
|
||||
SESSION_IDLE = 0,
|
||||
SESSION_INUSE = 1,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 并发请求session接口定义, 根据session可映射出thread,action等
|
||||
*/
|
||||
class ISession : public HashKey
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief 构造与析构函数
|
||||
*/
|
||||
ISession() : _session_id(0), _session_flg(0), _thread(NULL), _connection(NULL) {};
|
||||
virtual ~ISession();
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief 会话ID的设置与获取
|
||||
*/
|
||||
void SetSessionId(int id) {
|
||||
_session_id = id;
|
||||
};
|
||||
|
@ -64,9 +54,6 @@ public:
|
|||
return _session_id;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 关联线程的设置与获取
|
||||
*/
|
||||
MicroThread* GetOwnerThread(){
|
||||
return _thread;
|
||||
};
|
||||
|
@ -74,9 +61,6 @@ public:
|
|||
_thread = thread;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 关联连接的设置与获取
|
||||
*/
|
||||
IMtConnection* GetSessionConn(){
|
||||
return _connection;
|
||||
};
|
||||
|
@ -84,9 +68,6 @@ public:
|
|||
_connection = conn;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 会话flag的设置与获取
|
||||
*/
|
||||
void SetSessionFlag(int flag) {
|
||||
_session_flg = flag;
|
||||
};
|
||||
|
@ -94,52 +75,30 @@ public:
|
|||
return _session_flg;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 节点元素的hash算法, 获取key的hash值
|
||||
* @return 节点元素的hash值
|
||||
*/
|
||||
virtual uint32_t HashValue(){
|
||||
return _session_id;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 节点元素的cmp方法, 同一桶ID下, 按key比较
|
||||
* @return 节点元素的hash值
|
||||
*/
|
||||
virtual int HashCmp(HashKey* rhs){
|
||||
return this->_session_id - (int)rhs->HashValue();
|
||||
};
|
||||
|
||||
protected:
|
||||
|
||||
int _session_id; // 会话id信息
|
||||
int _session_flg; // 记录session状态 0 -不在hash中, 1 -hash管理中
|
||||
MicroThread* _thread; // 会话所属的session
|
||||
IMtConnection* _connection; // 会话关联的连接
|
||||
int _session_id;
|
||||
int _session_flg;
|
||||
MicroThread* _thread;
|
||||
IMtConnection* _connection;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 全局的session管理结构
|
||||
*/
|
||||
class SessionMgr
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief 会话上下文的全局管理句柄接口
|
||||
* @return 全局句柄指针
|
||||
*/
|
||||
static SessionMgr* Instance (void);
|
||||
|
||||
/**
|
||||
* @brief 全局的删除接口
|
||||
*/
|
||||
static void Destroy();
|
||||
|
||||
/**
|
||||
* @brief 获取sessionid
|
||||
* @return 全局句柄指针
|
||||
*/
|
||||
int GetSessionId(void) {
|
||||
_curr_session++;
|
||||
if (!_curr_session) {
|
||||
|
@ -148,40 +107,23 @@ public:
|
|||
return _curr_session;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Session数据存储
|
||||
*/
|
||||
int InsertSession(ISession* session);
|
||||
|
||||
/**
|
||||
* @brief 查询session数据
|
||||
*/
|
||||
ISession* FindSession(int session_id);
|
||||
|
||||
/**
|
||||
* @brief 删除session数据
|
||||
*/
|
||||
void RemoveSession(int session_id);
|
||||
|
||||
/**
|
||||
* @brief 析构函数
|
||||
*/
|
||||
~SessionMgr();
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* @brief 消息buff的构造函数
|
||||
*/
|
||||
SessionMgr();
|
||||
|
||||
static SessionMgr * _instance; ///< 单例类句柄
|
||||
int _curr_session; ///< session种子
|
||||
HashList* _hash_map; ///< 按sessionid hash存储
|
||||
static SessionMgr * _instance;
|
||||
int _curr_session;
|
||||
HashList* _hash_map;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
|
|
@ -19,8 +19,6 @@
|
|||
|
||||
/**
|
||||
* @filename mt_sys_hook.cpp
|
||||
* @info 微线程hook系统api, 以不用额外编译的优势, 转同步为异步库
|
||||
* 只hook socket相关的API, HOOK 部分, 参考pth与libco实现
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
@ -44,25 +42,18 @@ using namespace NS_MICRO_THREAD;
|
|||
#define MT_FD_FLG_INUSE 0x1
|
||||
#define MT_FD_FLG_UNBLOCK 0x2
|
||||
|
||||
|
||||
/**
|
||||
* @brief 每sockt分配一个管理结构, 标记是否需要HOOK, 超时时间等
|
||||
*/
|
||||
typedef struct socket_hook_info
|
||||
{
|
||||
int sock_flag; // 是否使用HOOK, 是否用户设置UNBLOCK
|
||||
int read_timeout; // socket读取超时时间, ms单位
|
||||
int write_timeout; // socket写入超时时间, ms单位
|
||||
int sock_flag;
|
||||
int read_timeout;
|
||||
int write_timeout;
|
||||
}MtHookFd;
|
||||
|
||||
MtSyscallFuncTab g_mt_syscall_tab; // 全局符号表
|
||||
int g_mt_hook_flag; // 全局控制标记
|
||||
int g_ff_hook_flag; // 全局控制标记
|
||||
static MtHookFd g_mt_hook_fd_tab[MT_HOOK_MAX_FD]; // 全局fd管理
|
||||
MtSyscallFuncTab g_mt_syscall_tab;
|
||||
int g_mt_hook_flag;
|
||||
int g_ff_hook_flag;
|
||||
static MtHookFd g_mt_hook_fd_tab[MT_HOOK_MAX_FD];
|
||||
|
||||
/**
|
||||
* @brief 内部接口, 获取hook fd相关的信息, socket 默认hook, open 默认no hook
|
||||
*/
|
||||
MtHookFd* mt_hook_find_fd(int fd)
|
||||
{
|
||||
if ((fd < 0) || (fd >= MT_HOOK_MAX_FD)) {
|
||||
|
@ -77,9 +68,6 @@ MtHookFd* mt_hook_find_fd(int fd)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 内部接口, 创建socket设置hook, 只处理socket, 不处理文件IO
|
||||
*/
|
||||
void mt_hook_new_fd(int fd)
|
||||
{
|
||||
if ((fd < 0) || (fd >= MT_HOOK_MAX_FD)) {
|
||||
|
@ -92,9 +80,6 @@ void mt_hook_new_fd(int fd)
|
|||
fd_info->write_timeout = 500;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 内部接口, 关闭hook socket
|
||||
*/
|
||||
void mt_hook_free_fd(int fd)
|
||||
{
|
||||
if ((fd < 0) || (fd >= MT_HOOK_MAX_FD)) {
|
||||
|
@ -107,9 +92,6 @@ void mt_hook_free_fd(int fd)
|
|||
fd_info->write_timeout = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief HOOK接口, 初始化mt库后, 接管系统api, 截获用户设置的非阻塞标记
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
@ -135,17 +117,14 @@ int ioctl(int fd, unsigned long cmd, ...)
|
|||
}
|
||||
}
|
||||
|
||||
return ff_hook_ioctl(fd, cmd, arg);
|
||||
return ff_hook_ioctl(fd, cmd, arg);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief HOOK接口, 初始化mt库后, 接管系统api, 默认设置unblock
|
||||
*/
|
||||
int socket(int domain, int type, int protocol)
|
||||
{
|
||||
mt_hook_syscall(socket);
|
||||
|
||||
if (!ff_hook_active())
|
||||
|
||||
if (!ff_hook_active())
|
||||
{
|
||||
return mt_real_func(socket)(domain, type, protocol);
|
||||
}
|
||||
|
@ -159,36 +138,29 @@ int socket(int domain, int type, int protocol)
|
|||
mt_hook_new_fd(fd);
|
||||
|
||||
mt_hook_syscall(ioctl);
|
||||
int nb = 1;
|
||||
ff_hook_ioctl(fd, FIONBIO, &nb);
|
||||
int nb = 1;
|
||||
ff_hook_ioctl(fd, FIONBIO, &nb);
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief HOOK接口, 初始化mt库后, 接管系统api
|
||||
*/
|
||||
int close(int fd)
|
||||
{
|
||||
mt_hook_syscall(close);
|
||||
if (!ff_hook_active())
|
||||
if (!ff_hook_active())
|
||||
{
|
||||
return mt_real_func(close)(fd);
|
||||
}
|
||||
|
||||
mt_hook_free_fd(fd);
|
||||
return ff_hook_close(fd);
|
||||
return ff_hook_close(fd);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief HOOK接口, 初始化mt库后, 接管系统api
|
||||
*/
|
||||
int connect(int fd, const struct sockaddr *address, socklen_t address_len)
|
||||
{
|
||||
mt_hook_syscall(connect);
|
||||
MtHookFd* hook_fd = mt_hook_find_fd(fd);
|
||||
if (!mt_hook_active() || !hook_fd || !ff_hook_active())
|
||||
if (!mt_hook_active() || !hook_fd || !ff_hook_active())
|
||||
{
|
||||
return mt_real_func(connect)(fd, address, address_len);
|
||||
}
|
||||
|
@ -201,9 +173,6 @@ int connect(int fd, const struct sockaddr *address, socklen_t address_len)
|
|||
return MtFrame::connect(fd, address, (int)address_len, hook_fd->write_timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief HOOK接口, 初始化mt库后, 接管系统api, 用户已经设置unblock, 跳过
|
||||
*/
|
||||
ssize_t read(int fd, void *buf, size_t nbyte)
|
||||
{
|
||||
mt_hook_syscall(read);
|
||||
|
@ -221,9 +190,6 @@ ssize_t read(int fd, void *buf, size_t nbyte)
|
|||
return MtFrame::read(fd, buf, nbyte, hook_fd->read_timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief HOOK接口, 初始化mt库后, 接管系统api, 用户已经设置unblock, 跳过
|
||||
*/
|
||||
ssize_t write(int fd, const void *buf, size_t nbyte)
|
||||
{
|
||||
mt_hook_syscall(write);
|
||||
|
@ -241,9 +207,6 @@ ssize_t write(int fd, const void *buf, size_t nbyte)
|
|||
return MtFrame::write(fd, buf, nbyte, hook_fd->write_timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief HOOK接口, 初始化mt库后, 接管系统api, 用户已经设置unblock, 跳过
|
||||
*/
|
||||
ssize_t sendto(int fd, const void *message, size_t length, int flags,
|
||||
const struct sockaddr *dest_addr, socklen_t dest_len)
|
||||
{
|
||||
|
@ -263,9 +226,6 @@ ssize_t sendto(int fd, const void *message, size_t length, int flags,
|
|||
dest_addr, dest_len, hook_fd->write_timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief HOOK接口, 初始化mt库后, 接管系统api, 用户已经设置unblock, 跳过
|
||||
*/
|
||||
ssize_t recvfrom(int fd, void *buffer, size_t length, int flags,
|
||||
struct sockaddr *address, socklen_t *address_len)
|
||||
{
|
||||
|
@ -285,9 +245,6 @@ ssize_t recvfrom(int fd, void *buffer, size_t length, int flags,
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief HOOK接口, 初始化mt库后, 接管系统api, 用户已经设置unblock, 跳过
|
||||
*/
|
||||
ssize_t recv(int fd, void *buffer, size_t length, int flags)
|
||||
{
|
||||
mt_hook_syscall(recv);
|
||||
|
@ -305,9 +262,6 @@ ssize_t recv(int fd, void *buffer, size_t length, int flags)
|
|||
return MtFrame::recv(fd, buffer, length, flags, hook_fd->read_timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief HOOK接口, 初始化mt库后, 接管系统api, 用户已经设置unblock, 跳过
|
||||
*/
|
||||
ssize_t send(int fd, const void *buf, size_t nbyte, int flags)
|
||||
{
|
||||
mt_hook_syscall(send);
|
||||
|
@ -325,10 +279,6 @@ ssize_t send(int fd, const void *buf, size_t nbyte, int flags)
|
|||
return MtFrame::send(fd, buf, nbyte, flags, hook_fd->write_timeout);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief HOOK接口, 初始化mt库后, 接管系统api, 截获用户设置的超时时间信息
|
||||
*/
|
||||
int setsockopt(int fd, int level, int option_name, const void *option_value, socklen_t option_len)
|
||||
{
|
||||
mt_hook_syscall(setsockopt);
|
||||
|
@ -351,14 +301,9 @@ int setsockopt(int fd, int level, int option_name, const void *option_value, soc
|
|||
}
|
||||
}
|
||||
|
||||
return ff_hook_setsockopt(fd, level, option_name, option_value, option_len);
|
||||
return ff_hook_setsockopt(fd, level, option_name, option_value, option_len);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief HOOK接口, 初始化mt库后, 接管系统api, 截获用户设置的非阻塞标记
|
||||
*/
|
||||
int fcntl(int fd, int cmd, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
@ -388,7 +333,6 @@ int fcntl(int fd, int cmd, ...)
|
|||
return ff_hook_fcntl(fd, cmd, arg);
|
||||
}
|
||||
|
||||
|
||||
int listen(int sockfd, int backlog)
|
||||
{
|
||||
mt_hook_syscall(listen);
|
||||
|
@ -397,7 +341,7 @@ int listen(int sockfd, int backlog)
|
|||
return mt_real_func(listen)(sockfd, backlog);
|
||||
}
|
||||
|
||||
return ff_hook_listen(sockfd, backlog);
|
||||
return ff_hook_listen(sockfd, backlog);
|
||||
}
|
||||
|
||||
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
|
||||
|
@ -408,7 +352,7 @@ int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
|
|||
return mt_real_func(bind)(sockfd, addr, addrlen);
|
||||
}
|
||||
|
||||
return ff_hook_bind(sockfd, addr, addrlen);
|
||||
return ff_hook_bind(sockfd, addr, addrlen);
|
||||
}
|
||||
|
||||
int accept(int fd, struct sockaddr *addr, socklen_t *addrlen)
|
||||
|
@ -419,7 +363,7 @@ int accept(int fd, struct sockaddr *addr, socklen_t *addrlen)
|
|||
return mt_real_func(accept)(fd, addr, addrlen);
|
||||
}
|
||||
|
||||
return ff_hook_accept(fd, addr, addrlen);
|
||||
return ff_hook_accept(fd, addr, addrlen);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -19,8 +19,6 @@
|
|||
|
||||
/**
|
||||
* @filename mt_sys_hook.h
|
||||
* @info 微线程hook系统api, 以不用额外编译的优势, 转同步为异步库
|
||||
* HOOK 部分, 参考pth与libco实现
|
||||
*/
|
||||
|
||||
#ifndef _MT_SYS_HOOK___
|
||||
|
@ -35,10 +33,6 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
/******************************************************************************/
|
||||
/* 1. HOOK 的函数定义部分 */
|
||||
/******************************************************************************/
|
||||
|
||||
typedef int (*func_socket)(int domain, int type, int protocol);
|
||||
typedef int (*func_bind)(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
|
||||
typedef int (*func_listen)(int sockfd, int backlog);
|
||||
|
@ -63,14 +57,6 @@ typedef int (*func_fcntl)(int fd, int cmd, ...);
|
|||
|
||||
typedef unsigned int (*func_sleep)(unsigned int seconds);
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
/* 2. 全局的hook函数结构 */
|
||||
/******************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief Hook的原始函数集中管理定义, 支持动态新增处理
|
||||
*/
|
||||
typedef struct mt_syscall_func_tab
|
||||
{
|
||||
func_socket real_socket;
|
||||
|
@ -88,25 +74,21 @@ typedef struct mt_syscall_func_tab
|
|||
func_fcntl real_fcntl;
|
||||
func_ioctl real_ioctl;
|
||||
|
||||
func_sleep real_sleep; // 暂不支持,因为没有与fd关联, 防止滥用
|
||||
func_select real_select; // 暂不支持, 1024限制问题
|
||||
func_poll real_poll; // 暂不支持, 确认需求后实施
|
||||
func_sleep real_sleep;
|
||||
func_select real_select;
|
||||
func_poll real_poll;
|
||||
|
||||
func_accept real_accept;
|
||||
}MtSyscallFuncTab;
|
||||
} MtSyscallFuncTab;
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
/* 3. 直接调用原始系统api的接口 */
|
||||
/******************************************************************************/
|
||||
extern MtSyscallFuncTab g_mt_syscall_tab; // 全局符号表
|
||||
extern int g_mt_hook_flag; // 全局控制标记
|
||||
extern int g_ff_hook_flag; // 全局控制标记
|
||||
extern MtSyscallFuncTab g_mt_syscall_tab;
|
||||
extern int g_mt_hook_flag;
|
||||
extern int g_ff_hook_flag;
|
||||
|
||||
#define mt_hook_syscall(name) \
|
||||
do { \
|
||||
if (!g_mt_syscall_tab.real_##name) { \
|
||||
g_mt_syscall_tab.real_##name = (func_##name)dlsym(RTLD_NEXT, #name);\
|
||||
g_mt_syscall_tab.real_##name = (func_##name)dlsym(RTLD_NEXT, #name);\
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
|
|
@ -17,17 +17,6 @@
|
|||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @file mt_version.h
|
||||
* @info 微线程版本更新与记录信息文件
|
||||
* @time 20131018
|
||||
* ------------------------------------------------------------------------
|
||||
* @brief v0.2.0 - 支持UDP按session模式映射上下文
|
||||
* v0.2.1 - 支持TCP的sendrcv接口
|
||||
* v0.2.3 - 实时时间戳
|
||||
* v0.2.4 - 支持TCP的sendrcv接口动态扩展接收buf
|
||||
*/
|
||||
|
||||
#ifndef _MT_VERSION_EX__
|
||||
#define _MT_VERSION_EX__
|
||||
|
||||
|
|
Loading…
Reference in New Issue