C/C++协程学习笔记丨C/C++实现协程及原理分析视频( 七 )


apTimeout->llStartIdx = 0; // 当前时间轮指针指向数组0
}
// 1. 当前时间不可能小于时间轮的基准时间
// 2. 加入的定时器的超时时间不能小于当前时间
if( allNow < apTimeout->ullStart || apItem->ullExpireTime < allNow )
{
return __LINE__;
}
int diff = apItem->ullExpireTime - apTimeout->ullStart;
if( diff >= apTimeout->iItemSize ) // 添加的事件不能超过时间轮的大小
{
return __LINE__;
【C/C++协程学习笔记丨C/C++实现协程及原理分析视频】 }
// 插入到时间轮盘的指定位置
AddTail( apTimeout->pItems +
(apTimeout->llStartIdx + diff ) % apTimeout->iItemSize, apItem );
return 0;
}
定时器的超时检查在函数 co_eventloop 中执行 。
EPOLL 事件循环main 协程通过调用函数 co_eventloop 来监听 Epoll 事件 , 并在相应的事件触发时切换到指定的协程执行 。 有关 co_eventloop 与 应用协程的交互过程在上一节的流程图中已经比较清楚了 , 下面我们主要介绍一下 co_eventloop 函数的实现:
上文中也提到 , 通过 epoll_wait 返回的事件都保存在 stCoEpoll_t 结构的 co_epoll_res 中 。 因此 co_eventloop 首先为 co_epoll_res 申请空间 , 之后通过一个无限循环来监听所有 coroutine 添加的所有事件:
for(;;)
{
int ret = co_epoll_wait( ctx->iEpollFd,result,stCoEpoll_t::_EPOLL_SIZE, 1 );
...
}
对于每一个触发的事件 , co_eventloop 首先通过指针域 data.ptr 取出保存的 stPollItem_t 结构 , 并将其添加到 pstActiveList 列表中;之后从定时器轮盘中取出所有已经超时的事件 , 也将其全部添加到 pstActiveList 中 , pstActiveList 中的所有事件都作为活跃事件处理 。
对于每一个活跃事件 , co_eventloop 将通过调用对应的 pfnProcess 也就是上图中的OnPollProcessEvent 函数来切换到该事件对应的 coroutine , 将流程跳转到该 coroutine 处执行 。
最后 co_eventloop 在调用时也提供一个额外的参数来供调用者传入一个函数指针 pfn 。 该函数将会在每次循环完成之后执行;当该函数返回 -1 时 , 将会终止整个事件循环 。 用户可以利用该函数来控制 main 协程的终止或者完成一些统计需求 。


推荐阅读