muduo网络库TcpConnection对象生存期管理

为什么释放一个TcpConnection会如此复杂?

  首先要知道客户端关闭连接,在服务端TcpConnection对象所属的Channel对象返回的是可读事件。

  因此从TcpServer的map<string, shared_ptr<TcpConnection>>中移除这个TcpConnection对象都是在TcpConnectoin所属的Channel对象的Channel::handleEvent()函数内进行的。

  如果在这个TcpConnection对象的函数执行过程中释放了这个对象,那么就会造成不可预计的后果。(大概率就是coredump)

  因此待释放的TcpConnection对象的生命期一定要长于Channel::handleEvent()函数。

 

如何做到正确释放一个TcpConnection对象的?

最重要的是在每一个TcpConnection建立的时候将他的shared_ptr赋值给了他所属的Channel对象的weak_ptr。

void TcpConnection::connectEstablished()
{
  loop_->assertInLoopThread();
  assert(state_ == kConnecting);
  setState(kConnected);
  channel_->tie(shared_from_this());
  channel_->enableReading();
  connectionCallback_(shared_from_this());
}

这样当有TcpConnection所属的Channel有事件到来的时候就可以对TcpConnection的引用计数+1:此时TcpServer的map中有一个智能指针指向TcpConnection

void Channel::handleEvent(Timestamp receiveTime)
{
  std::shared_ptr<void> guard;
  if (tied_)
  {
    guard = tie_.lock();
    if (guard)
    {
      handleEventWithGuard(receiveTime);
    }
  }
  else
  {
    handleEventWithGuard(receiveTime);
  }
}

整一个流程为:

 

简略的函数压栈情况:

 

posted @ 2020-03-29 21:18  只取一瓢饮  阅读(292)  评论(0编辑  收藏  举报