Channel模块实现概述
Channel模块在高并发服务器中负责封装文件描述符(fd)及其相关事件(如可读、可写、错误等),通常与Reactor模式中的事件分发器(如Epoll)协同工作。以下是Channel模块的核心实现要点。
核心数据结构
Channel模块通常包含以下成员变量:
int fd_:管理的文件描述符。uint32_t events_:关注的事件(如EPOLLIN、EPOLLOUT)。uint32_t revents_:实际触发的事件(由Epoll返回)。std::function<void()> readCallback_:可读事件回调函数。std::function<void()> writeCallback_:可写事件回调函数。std::function<void()> errorCallback_:错误事件回调函数。
class Channel {
public:
using EventCallback = std::function<void()>;
Channel(EventLoop* loop, int fd);
~Channel();
void handleEvent(); // 处理事件回调
void setReadCallback(EventCallback cb);
void setWriteCallback(EventCallback cb);
void setErrorCallback(EventCallback cb);
void enableReading(); // 注册可读事件
void enableWriting(); // 注册可写事件
void disableWriting(); // 取消可写事件
void disableAll(); // 取消所有事件
int fd() const { return fd_; }
uint32_t events() const { return events_; }
void set_revents(uint32_t revents) { revents_ = revents; }
private:
EventLoop* loop_; // 所属EventLoop
int fd_;
uint32_t events_; // 关注的事件
uint32_t revents_; // 触发的事件
EventCallback readCallback_;
EventCallback writeCallback_;
EventCallback errorCallback_;
};
事件处理逻辑
handleEvent()是Channel的核心方法,根据revents_调用对应的回调函数:
void Channel::handleEvent() {
if (revents_ & EPOLLERR) {
if (errorCallback_) errorCallback_();
}
if (revents_ & (EPOLLIN | EPOLLPRI | EPOLLRDHUP)) {
if (readCallback_) readCallback_();
}
if (revents_ & EPOLLOUT) {
if (writeCallback_) writeCallback_();
}
}
与EventLoop的交互
Channel通过EventLoop注册或更新事件到Epoll:
enableReading()调用EventLoop::updateChannel(this)将事件添加到Epoll。disableAll()调用EventLoop::removeChannel(this)从Epoll中移除。
void Channel::enableReading() {
events_ |= EPOLLIN;
loop_->updateChannel(this);
}
void Channel::disableAll() {
events_ = 0;
loop_->removeChannel(this);
}
注意事项
- 线程安全:Channel的方法应在
EventLoop所在的IO线程调用,避免竞态条件。 - 资源管理:Channel不拥有
fd_的生命周期,需由更高层(如TcpConnection)管理。 - 事件优先级:EPOLLERR事件应优先处理,其次是EPOLLIN和EPOLLOUT。
性能优化
- 避免频繁更新Epoll:通过
events_的局部变量判断是否需要调用EventLoop::updateChannel。 - 回调函数空检查:在调用回调前检查是否为空,减少分支预测开销。
608

被折叠的 条评论
为什么被折叠?



