muduo中eventloop、channel、fd解析

最近在研究muduo源代码,因为之前的项目内部的逻辑与muduo类似,不过使用的是libevent完成内核的构造,muduo使用了自己写的poll和epoll方式完成内部的io复用。之前的项目与muduo使用的策略一致,使用了主线程专门用于接收tcp连接,连接后的connection发送到多个子线程中来支持高并发。

eventloop.h

这个类是muduo的核心,头文件如下(已做注释):

///
/// Reactor, at most one per thread.
///
/// This is an interface class, so don't expose too much details.
class EventLoop : noncopyable
{
 public:
  typedef std::function<void()> Functor;

  EventLoop();
  ~EventLoop();  // force out-line dtor, for std::unique_ptr members.

  ///
  /// Loops forever.
  /// 
  /// Must be called in the same thread as creation of the object.
  /// 只能在创建当前实例的线程执行loop函数
  void loop();

  /// Quits loop.
  /// 使用共享指针的loop实例调用可能不安全
  /// This is not 100% thread safe, if you call through a raw pointer,
  /// better to call through shared_ptr<EventLoop> for 100% safety.
  void quit();

  ///
  /// Time when poll returns, usually means data arrival.
  ///
  Timestamp pollReturnTime() const { return pollReturnTime_; }

  int64_t iteration() const { return iteration_; }

  /// Runs callback immediately in the loop thread.
  /// It wakes up the loop, and run the cb.
  /// If in the same loop thread, cb is run within the function.
  /// Safe to call from other threads.
  /// 在 loop 中执行函数,线程安全
  void runInLoop(Functor cb);

  /// Queues callback in the loop thread.
  /// Runs after finish pooling.
  /// Safe to call from other threads.
  /// 将回调函数存入任务队列中,线程安全
  void queueInLoop(Functor cb);

  /// 返回任务队列长度
  size_t queueSize() const;

  // timers

  ///
  /// Runs callback at 'time'.
  /// Safe to call from other threads.
  /// 在指定的事件戳运行时间回调函数
  TimerId runAt(Timestamp time, TimerCallback cb);
  ///
  /// Runs callback after @c delay seconds.
  /// Safe to call from other threads.
  /// 经过delay的延时后调用回调函数
  TimerId runAfter(double delay, TimerCallback cb);
  ///
  /// Runs callback every @c interval seconds.
  /// Safe to call from other threads.
  /// 每过interval时间后调用回调函数
  TimerId runEvery(double interval, TimerCallback cb);
  ///
  /// Cancels the timer.
  /// Safe to call from other threads.
  /// 取消时间器的回调函数
  void cancel(TimerId timerId);

  // internal usage
  void wakeup();
  void updateChannel(Channel* channel);
  void removeChannel(Channel* channel);
  bool hasChannel(Channel* channel);

  // pid_t threadId() const { return threadId_; }
  void assertInLoopThread()
  {
    if (!isInLoopThread())
    {
      abortNotInLoopThread();
    }
  }
  bool isInLoopThread() const { return threadId_ == CurrentThread::tid(); }
  // bool callingPendingFunctors() const { return callingPendingFunctors_; }
  bool eventHandling() const { return eventHandling_; }

  // 设置context
  void setContext(const boost::any& context)
  { context_ = context; }
  // 获得context
  const boost::any& getContext() const
  { return context_; }
  // 获得非常量的context
  boost::any* getMutableContext()
  { return &context_; }

  // 获得当前线程的eventloop
  static EventLoop* getEventLoopOfCurrentThread();

 private:
  void abortNotInLoopThread();      // 退出程序
  void handleRead();  // waked up
  void doPendingFunctors();

  void printActiveChannels() const; // DEBUG

  typedef std::vector<Channel*> ChannelList;      // 用于存储channel

  bool looping_; /* atomic */
  std::atomic<bool> quit_;                      // 判断是否离开loop
  bool eventHandling_; /* atomic */
  bool callingPendingFunctors_; /* atomic */
  int64_t iteration_;                           // 记录 loop 循环的次数
  const pid_t threadId_;
  Timestamp pollReturnTime_;                    // poll返回时间戳
  std::unique_ptr<Poller> poller_;
  std::unique_ptr<TimerQueue> timerQueue_;      // 时间队列
  int wakeupFd_;                                // 唤醒fd,使用 eventfd() 创建
  // unlike in TimerQueue, which is an internal class,
  // we don't expose Channel to client.
  std::unique_ptr<Channel> wakeupChannel_;      // 唤醒fd 的 channel
  boost::any context_;

  // scratch variables
  ChannelList activeChannels_;                  // 激活的 channel
  Channel* currentActiveChannel_;               // 当前的活动 channel

  mutable MutexLock mutex_;
  std::vector<Functor> pendingFunctors_ GUARDED_BY(mutex_);   // 挂起的 函数体
};

成员变量std::unique_ptr poller_

它的实现有两个分别是poll和epoll,类关系如下图:
在这里插入图片描述
其中poller_使用了唯一智能指针创建,因为一个EventLoop只能使用一种Poller内核。Poller使用的函数如下:
pollReturnTime_ = poller_->poll(kPollTimeMs, &activeChannels_);
poller_->updateChannel(channel);
poller_->removeChannel(channel);
poller_->hasChannel(channel);

成员变量wakeupFd_

int wakeupFd_;
std::unique_ptr wakeupChannel_;
以上两个变量完成了对于EventLoop的唤醒操作。
当需要唤醒EventLoop时只需要写入wakeupFd_即可。
在构造函数中使用
wakeupFd_(createEventfd()), // 创建唤醒 fd
wakeupChannel_(new Channel(this, wakeupFd_)),
创建。
wakeupChannel_为wakeupFd_绑定了读取回调函数,在EventLoop函数的析构函数中,关闭了所有的监听事件并close(wakeupFd_)

成员变量 ChannelList

typedef std::vector<Channel*> ChannelList;
ChannelList activeChannels_; // 激活的 channel 链表
该vector用来存储 poller_ io复用后激活的所有事件。

总体流程图

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值