EventLoop,TcpClient,TcpServer 中的生命周期

时间:2022-07-26
本文章向大家介绍EventLoop,TcpClient,TcpServer 中的生命周期,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

muduo 中,大量是用 smart point 省掉自己管理内存.下面开着源码参看。

question 1:EventLoop 的生命周期

answer 1: 建立在栈中,离开范围以后,自动释放。

void EventLoopThread::threadFunc()
{
  EventLoop loop;//这里声明了本地epoller,也就是线程当地的epoller

  if (callback_)
  {
    callback_(&loop);
  }

  {
    MutexLockGuard lock(mutex_);
    // 一般情况是EventLoopThread对象先析构,析构函数调用loop_->quit() 使得loop.loop() 退出循环
    // 这样threadFunc 退出,loop栈上对象析构,loop_ 指针失效,但此时已经不会再通过loop_ 访问loop,
    // 故不会有问题。
    loop_ = &loop;
    cond_.notify();
  }

  loop.loop();
  //assert(exiting_);
  loop_ = NULL;
}

question 2:EventLoop 有什么含指针类成员?

answer 2: (1) vector< Channel *> attiveChannels_; 只是存放,不管理里面的 Channel 死活.

    (2) scoped_ptr<Poller> poller_; => 自动析构

     (3) scoped_ptr<TimerQueue> timeQueue; => 自动析构

      (4) scoped_ptr<Channel> wakeripChannel_; 自动析构

得:EventLoop 掌管着 2,3,4 的生命

question 3: TcpClient 的生命周期?

answer 3:一般在栈上,跟程序差不多。

question 4: TcpClient 有什么含指针的成员?

answer 4: (1) shared_ptr<Connector> ConnectorPtr connector_; =>自动析构

     (2) shared_ptr<TcpConnection> TcpConnectionPtr connection_; =>自动析构

TcpClient::~TcpClient()
{
  LOG_INFO << "TcpClient::~TcpClient[" << name_
           << "] - connector " << get_pointer(connector_);
  TcpConnectionPtr conn;
  {
    MutexLockGuard lock(mutex_);
    conn = connection_;
  }
  // 你这里什么情况下 conn 会为空啊,未连接的时候
  if (conn)
  {
    // FIXME: not 100% safe, if we are in different thread
    CloseCallback cb = boost::bind(&detail::removeConnection, loop_, _1);
    loop_->runInLoop(
        boost::bind(&TcpConnection::setCloseCallback, conn, cb));
  }
  else
  {
    connector_->stop();//关闭连接器
    // FIXME: HACK
    loop_->runAfter(1, boost::bind(&detail::removeConnector, connector_));//connector会自己在Tcpclient之后析构
  }
}

question 5: TcpConnection 的生命周期

answer 5:两种情况,(1)对方断开连接;(2)自己退出;

     (1)当遇到别人断开连接 => channel_->handleEvent() -> connection_->handleClose();

handleClose(){ 设置状态为非链接 => 清空事件

        => 新建一个 TcpConnectionPtr 对象,预防被析构。

       => 调用 connectionCallback() 告诉用户

       => 调用 closeCallback() => removeConnection()

       }

removeConnection{ 将 TcpClient 中的 connectoin_ 置空,假如 handleClose() 不新建,这里就析构了

          ,然后后面调用 TcpConnection::connectDestroyed 就会失败

          }

connectiDestroyed{ 将 channel_ 从 poller_ 中删除 }

最后,回到 handleClose() ,TcpConnectionPtr 析构掉,带有的 Socket, Channel 也就析构掉了。

(2) 当自己退出的话,就直接从connectDestory()开始执行.

详情,参照源码看。

然后,TcpServer 的话,跟 TcpClient 比,多了个map<string,TcpConnectionPtr> connections_;

处理断开的话,就多了一个,从 map 中去除。