29.muduo学习笔记之net_EventLoop.{h&cc}

1. 说明

  1. 一个EventLoop类,任何一个线程,只要创建并运行了EventLoop,都称之为IO线程(为了方便使用,定义了EventLoopThread类,封装了IO线程)
  2. 使用了Channel,Poller,TimerQueue,Timestamp类
  3. noncopyable

2. 变量

  1. 类型定义

    • Functor
    • ChannelList
  2. looping_; /* atomic */

    • bool类型,表示是否处于loop()函数执行中,它的值变化都在loop()函数中
  3. std::atomic quit_;

    • bool类型,判断是否退出,loop()中循环的结束条件
  4. bool eventHandling_; /* atomic */

    • 表示是否处于处理事件事件中,在loop()中poll()选择需要处理的通道(事件)后,在对这些事件的处理过程中把这个变量置为true
  5. bool callingPendingFunctors_; /* atomic */

    • 是否处于doPendingFunctors()函数中
  6. int64_t iteration_;

    • 在构造函数中赋初值为0,以后只在loop()中有用到,即每次poll()后+1,应该是记录poll()的次数吧
  7. const pid_t threadId_

    • 当前对象所属线程id
  8. Timestamp pollReturnTime_;

    • 调用poll(),返回时间戳
  9. std::unique_ptr poller_;

    • 每个EventLoop都会有一个Poller,
  10. std::unique_ptr timerQueue_;

    • 每个EventLoop都有个TimerQueue,定时器列表,作为定时器
  11. int wakeupFd_;

    • 用于eventfd,在构造函数中用createEventfd()生成eventfd赋值,作为线程唤醒需要使用的fd
    • 进程间通信有几种方式:pipe,socket,eventfd,线程间通信还有条件变量等
  12. std::unique_ptr wakeupChannel_;

    • 该通道将会纳入poller_来管理,用来唤醒当前线程,这是一个内部channel,不会暴露给用户
  13. boost::any context_;

    • boost::any,任意数据类型,C++17也加入C++标准
  14. ChannelList activeChannels_;

    • Poller返回的活动通道
  15. Channel* currentActiveChannel_;

    • 当前正在处理的活动通道
  16. mutable MutexLock mutex_;

    • 锁,没什么说的
  17. std::vector pendingFunctors_ GUARDED_BY(mutex_)

    • Functor的队列,这个就是需要处理的functor队列,在doPendingFunctors()函数中处理完就清空了,要理解需要结合runInLoop(),queueInLoop()等函数

3. 函数

1. 私有

  1. void abortNotInLoopThread();

    • 打印日志并退出,当前线程和此对象线程不一样,在assertInLoopThread()中调用
  2. void handleRead(); // waked up

    • 唤醒处理函数,调用read,里面的内容没有什么意义
  3. void doPendingFunctors();

    • 不是简单的在临界区内依次调用Functor,而是把回调列表swap到functors中,这样一方面减小了临界区的长度(意味着不会阻塞其他线程的queueInLoop()),另一方面也避免了死锁(因为Functor可能再次调用queueInLoop())
    • 把pendingFunctors_交换到新的局部空间,然后逐个调用这些函数
  4. void printActiveChannels() const;

    • 把活动的channel信息打印到日志

2. 共有

  1. 构造

    • 变量的初始化,设置当前channel的读回调函数为私有函数handleRead
  2. 析构

    • 释放资源
  3. void loop()

    • 循环调用poller_->poll(),返回需要处理的通道channel,处理这些通道的回调函数
    • 最后doPendingFunctors(),处理其他线程或者当前线程异步增加的需要处理的函数,详见下面的runInLoop()和queueInLoop(),这样让IO线程也能处理一些计算任务
  4. void quit()

    • 把quit_置为true,如果不是由当前IO线程调用的,要先用wakeup()唤醒当前线程
  5. Timestamp pollReturnTime()

    • 返回pollReturnTime_
  6. int64_t iteration()

    • 返回iteration_
  7. void runInLoop(Functor cb)

    • 在IO线程中执行某个回调函数,该函数可以跨线程调用
    • 如果在当前IO线程调用runInLoop.则同步调用cb()回调函数
    • else 如果在其他线程调用runInLoop.则调用queueInLoop(cb)异步地将cb添加到队列
  8. void queueInLoop(Functor cb)

    • 如果调用当前行数的线程不是当前IO线程,则需要唤醒,或者是当前线程,但此时正在调用pendingfunctor,也需要唤醒
  9. size_t queueSize()

    • 返回pendingFunctors_.size()
  10. TimerId runAt(Timestamp time, TimerCallback cb)

    • 就是把cb()加入定时器队列,在time时间执行
  11. TimerId runAfter(double delay, TimerCallback cb)

    • 把cd()加入定时器队列,当前时间+delay后执行
  12. TimerId runEvery(double interval, TimerCallback cb)

    • 把cb()加入定时器队列,每隔interval间隔时间执行一次
  13. void cancel(TimerId timerId)

    • 调用poller_->cancel(timerId),结束这个定时器任务
  14. void wakeup()

    • 唤醒当前对象线程,实际是调用write(),这样loop()函数中的poll()就会选到当前线程,然后执行
  15. void updateChannel(Channel* channel);

    • 断言当前对象线程正在执行,调用poller_->updateChannel(channel);
  16. void removeChannel(Channel* channel);

    • 保证能找到这个channel,调用poller_->removeChannel(channel);移除这个channel
  17. bool hasChannel(Channel* channel)

    • 调用poller_->hasChannel(channel);
  18. void assertInLoopThread()

    • 如果当前线程不是本对象线程,就调用abortNotInLoopThread(),打印日志并退出
  19. bool isInLoopThread()

    • 就是判断threadId_和当前正在运行的线程id是否相同
  20. bool eventHandling()

    • 返回eventHandling_,看是否处于loop()处理事件过程中
  21. void setContext(const boost::any& context)

    • 如名
  22. const boost::any& getContext()

    • 如名
  23. boost::any* getMutableContext()

    • 如名
  24. static EventLoop* getEventLoopOfCurrentThread()

    • 静态函数,返回t_loopInThisThread,即当前EventLoop对象

4. 全局

  1. t_loopInThisThread

    • 线程局部变量,在构造函数中赋值为当前对象
  2. kPollTimeMs

    • 在poll()中当参数传过去
  3. createEventfd()

    • 调用eventfd()生成eventfd返回
  4. IgnoreSigPipe类

    • 构造函数中调用signal()忽略SIGPIPE信号
    • 并且全局已经定义这个类了:initObj变量,也就是已经调用这个signal()了
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
基于微信小程序的家政服务预约系统采用PHP语言和微信小程序技术,数据库采用Mysql,运行软件为微信开发者工具。本系统实现了管理员和客户、员工三个角色的功能。管理员的功能为客户管理、员工管理、家政服务管理、服务预约管理、员工风采管理、客户需求管理、接单管理等。客户的功能为查看家政服务进行预约和发布自己的需求以及管理预约信息和接单信息等。员工可以查看预约信息和进行接单。本系统实现了网上预约家政服务的流程化管理,可以帮助工作人员的管理工作和帮助客户查询家政服务的相关信息,改变了客户找家政服务的方式,提高了预约家政服务的效率。 本系统是针对网上预约家政服务开发的工作管理系统,包括到所有的工作内容。可以使网上预约家政服务的工作合理化和流程化。本系统包括手机端设计和电脑端设计,有界面和数据库。本系统的使用角色分为管理员和客户、员工三个身份。管理员可以管理系统里的所有信息。员工可以发布服务信息和查询客户的需求进行接单。客户可以发布需求和预约家政服务以及管理预约信息、接单信息。 本功能可以实现家政服务信息的查询和删除,管理员添加家政服务信息功能填写正确的信息就可以实现家政服务信息的添加,点击家政服务信息管理功能可以看到基于微信小程序的家政服务预约系统里所有家政服务的信息,在添加家政服务信息的界面里需要填写标题信息,当信息填写不正确就会造成家政服务信息添加失败。员工风采信息可以使客户更好的了解员工。员工风采信息管理的流程为,管理员点击员工风采信息管理功能,查看员工风采信息,点击员工风采信息添加功能,输入员工风采信息然后点击提交按钮就可以完成员工风采信息的添加。客户需求信息关系着客户的家政服务预约,管理员可以查询和修改客户需求信息,还可以查看客户需求的添加时间。接单信息属于本系统里的核心数据,管理员可以对接单的信息进行查询。本功能设计的目的可以使家政服务进行及时的安排。管理员可以查询员工信息,可以进行修改删除。 客户可以查看自己的预约和修改自己的资料并发布需求以及管理接单信息等。 在首页里可以看到管理员添加和管理的信息,客户可以在首页里进行家政服务的预约和公司介绍信息的了解。 员工可以查询客户需求进行接单以及管理家政服务信息和留言信息、收藏信息等。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值