主要是do_io(文件描述符的操作)注释,有些函数简写了
//实现socket操作函数的hook封装
template<typename OriginFun,typename ... Args>
ssize_t do_io(int fd, OriginFun cb, const char* hook_fun_name, uint32_t event, int timeout_so, Args&&... args) {
if (!is_hook_flag) {
return cb(fd, std::forward<Args>(args)...);
}
//Dlib::Fdctx::ptr ctx= //通过Fdmanager获得fdctx
Fdctx::ptr ctx;
if (!ctx) {
return cb(fd, std::forward<Args>(args)...);
}
if (ctx->isClose()) {
errno = EBADF; //出错
return -1;
}
if (!ctx->isSocket() || ctx->getUserNonblock()) { //不是socket或设置了非阻塞
return cb(fd, std::forward<Args>(args)...);
}
uint64_t to = ctx->getTimeout(timeout_so); //超时时间
std::shared_ptr<timer_info> tinfo(new timer_info); //超时的条件
retry:
size_t n = cb(fd, std::forward<Args>(args)...); //执行原始方法,因为是非阻塞的,所以马上返回结果
while (n==-1&&errno==EINTR) //如果是被系统中断,程序执行
{
size_t n = cb(fd, std::forward<Args>(args)...);
}
if (n == -1 && errno == EAGAIN) { //阻塞状态,阻塞的等待资源上,就手动
auto Io = Mainf->m_poll;
Timer::ptr timer;
std::weak_ptr<timer_info> winfo(timer_info);
if (to != (uint64_t)-1) {//如果有超时时间,添加条件的超时定时器(拿这个条件唤醒以下,如果条件没错(已经超时了)设置成错误,并取消事件)
timer = Io->add; //添加定时器{
//这是定时器的回调函数
auto t = winfo.lock();
if (!t || t->cancelled) { //说明没有触发定时器
return;
}
t->cancelled = ETIMEDOUT;
io->cancel();//取消事件,将他唤醒
}
//添加事件
int c = 0; //计数器,计算重试了多少次,
uint64_t now = 0;
//添加一个事件
int rt = io->addEvent;
if (rt) { //加事件失败
if (timer) { //取消定时器
timer->cancel;
}
return -1;
}
else { //加事件成功,yield出去
yiedl();
//唤醒了,因为我的协程上下文此时保存在这,所以resume的时候,从这开始执行(从这开始唤醒)
//有两个唤醒时机:一个是定时器返回,一个是需要的资源来到
if (timer) { //如果timer还存在
timer->cancel();
}
if (timer_info->canceled) { //说明定时任务把他唤醒了
errno = timer_info->cancelled;
return -1;
}
//有Io事件回来了,要重新尝试一次执行函数
goto retry;
}
}
return n;
}