Muduo阅读

创建了EventLoop对象的线程是IO线程,其主要功能是运行事件循环EventLoop::loop(), one loop per thread
事件循环必须在IO线程中运行

Reactor关键结构

Channel

  • 每个Channel对象自始至终只属于一个EventLoop, 只负责一个fd的IO事件分发(如ReadCallback, WriteCallback),但它并不拥有这个fd, 也不会在析构时关闭这个fd
  • 成员函数都只在IO线程中使用,因此更新数据成员不用加锁

Poller

  • IO复用的封装,Poller并不拥有Channel,Channel在析构之前必须先unregister(EventLoop::removeChannel),避免空悬指针
  • 目前供EventLoop调用的有poll和updateChannel
  • poll函数:进行IO复用,并调用fillActiveChannel函数, 填充activeChannels, 返回return的时刻
  • fillActiveChannel函数:监听pollfds数组,将在活跃的fd对应的channel中设置该fd对应活跃的事件,并将这个channel加入activeChannels中来进行后续的事件分发,只负责IO复用,不负责IO分发,一方面防止分发事件改变Channel, 另一方面简化Poller职责,方便替换为其他高效的IO机制(如epoll)
  • updateChannel函数:更新并pollfds数组(可以增加一个新的fd,或者更改原有的pollfd),输入为channel,更新时也要更新Channel
  • channel中有个idx记录了其在pollfds的位置,方便更新

EventLoop

  • 拥有activeChannels,poller
  • EventLoop:loop()调用poller::poll()获得当前活动事件的Channel列表,然后调用每个Channel的handleEvent函数

TimerQueue定时器

传统的是通过select和poll的等待时间来实现定时的,现在可以使用timefd以与IO事件相同的方式来处理定时,
TimerQueue需要高效组织目前尚未到期的Timer,能够快速找到已经到期的Timer, 还要高效删除增加Timer
muduo采用map<Timestamp, *Timer>,但不是直接使用,因为这样无法处理Timestamp到期时间相同的情况,可以用multimap, muduo采用区分key的方法,将<Timestamp, *Timer>作为一个key存储为一个Set

TCP网络库

Acceptor

用于接受新的TCP连接,并通知回调给使用者,供TcpServer使用,生命期由后者控制
数据成员有Socket和Channel, Socket是一个RAII handle, 封装的socket是一个listening socket(server socket),用于观察此socket上的readable事件

TcpServer

管理accept(2)获得的TcpConnection, 供用户使用,生命周期由用户控制,用户只需要设置好callback, 再调用start()即可
新连接到达时,Acceptor会回调newConnection(), 创建TcpConnection并将其加入到ConnectionMap中,设置callback
TcpServer内部使用Acceptor来获得fd, start时让Acceptor去runInLoop

TcpConnection

TcpConnection是最核心也是最复杂的类,也是muduo中唯一默认使用shared_ptr来管理的class, 并且唯一继承enable_shared_from_this,因为其生命周期模糊
TcpConnection表示的是一次TCP连接,断开了就没用了,自己处理可写事件,可读事件通过MessageCallback传达给客户(也就是用户提供MessageCallback)

原文地址:https://www.cnblogs.com/qbits/p/11101678.html