#EventLoop Class
源码阅读
这部分有点复杂,欢迎大家交流
事件循环,服务器代码main
函数最后的while
循环。负责调用Poller
监听触发的事件,调用Channel::handleEvent
处理就绪的事件。
数据成员
bool looping_
是否正在进行事件循环,在构造函数中初始化为
false
,在EventLoop::loop()
中初始化为true
。
bool std::atomic<bool> quit_;
原子型变量,初始化为
false
,EventLoop::loop()
根据quit_
决定是否停止循环。
bool eventHandling_
是否正在处理就绪事件
bool callingPendingFunctors_
是否正在运行
functors
中的函数
int64_t iteration_
EventLoop::loop()
循环次数
const pid_t threadId_
当前
EventLoop
对象所处线程,当前线程即为 I / O 线 程 I/O线程 I/O线程。
Timestamp pollReturnTime_
应该是一个用于计时变量
std::unique_ptr<Poller> poller_;
本
EventLoop
所绑定的 多 路 复 用 多路复用 多路复用对象,为什么要采用这种方式,采用unique_ptr
有什么特别的意义吗?
int wakeupFd_
用于线程间通信的文件描述符,非
EventLoop
所在线程通过写该描述符通知 I / O 线 程 I/O线程 I/O线程有事发生。
std::unique_ptr<Channel> wakeupChannel_
监视
wakeupFd_
的Channel
对象。
std::unique_ptr<TimerQueue> timerQueue_;
一组计时器
boost::any context_
这是干嘛的?存储对
EventLoop
对象的解释吗
std::vector<Channel*> activeChannels_
发生就绪事件的文件表
Channel* currentActiveChannel_
当前正在处理的事件
mutable MutexLock mutex_; std::vector<Functor> pendingFunctors_ GUARDED_BY(mutex_);
需要处理的函数和保护他的互斥锁。
函数成员
EventLoop();
构造函数,初始化相关变量,为
wakeupFd_
初始化描述符、绑定Channel
、设置读监视和处理函数,检查当前线程是否有别的EventLoop
对象。
void loop();
事件循环,调用
Poller::poll
等待就绪事件,对就绪事件调用Channel::handleEvent
进行处理,在事件循环的最后执行pendingFunctors_
中的函数(doPendingFunctors()
)
void quit();
设置
quit_
为true,如果当前线程不是 I / O 线 程 I/O线程 I/O线程,就再向wakeupFd_
写个 1 1 1(void wakeup()
)。
问题(吴悠大佬):如果线程A刚刚设置quit_
为true
,接着 I / O 线 程 I/O线程 I/O线程就运行到判断quit_
,然后析构自身。接着线程A继续运行EventLoop::isInLoopThread()
,访问了无效的对象。
解决措施:1 在使用的时候,使用shared_ptr
来封装EventLoop Class
:在出现上述问题时,EventLoop::quit()
停止循环, I / O 线 程 I/O线程 I/O线程停止,该shared_ptr
计数减一,但线程A的shared_ptr
还在,不至于析构。
void runInLoop(Functor cb)
如果当前线程是 I / O 线 程 I/O线程 I/O线程,则直接执行
cb
,否则将cb
保存到pendingFunctors_
中,并发 1 1 1给 I / O 线 程 I/O线程 I/O线程
void doPendingFunctors()
执行
pendingFunctors_
中的函数。
TimerId runAt(Timestamp time,TimerCallback cb)
注册一个计时器,在
time
时刻执行cb
TimerId runAfter(double delay,TimerCallback cb)
注册一个计时器,在
delay
时刻后执行cb
TimerId runEvery(double interval,TimerCallback cb)
注册一个计时器,每隔
interval
执行cb