Muduo Network Library Source Code Analysis (vi) the lifetime management of Tcpconnection

Source: Internet
Author: User

Tcpconnection is a class that is managed by using shared_ptr because its life cycle is blurred. Tcpconnection represents a connection that has been established or is being established, After the connection is established, the user only needs to set the handler function for the connection arrival and message arrival in the upper class such as TCPServer, and then callback the Setconnectioncallback and Setmessagecallback functions in the tcpconnection. Implements the handling of events. The events that the user needs to care about are limited, and the others are responsible for the network library.

The InputBuffer and OutputBuffer are encapsulated in tcpconnection to represent the buffer of the application layer. When sending data, if the data in buffer cannot be sent at one time, it will continue to focus on the writable event in the channel, which is sent again when SOCKFD is writable.

earlier mentions Tcpconnection's lifetime blur, The main reason is that we cannot erase the Tcpconnection object directly in the TCPServer, because it is possible that the handleevent in the channel is still executing, and if the Tcpconnection object is being refactored, then his members Channel_ will also be refactored, leading to core dump. which means we need tcpconnection. The object lifetime is longer than the handleevent () function, and will not be refactored until connectdestroyed () is executed.

disconnect:  
tcpconnection disconnection is passive mode, that is, the other side first close the connection, local read (2) return 0, the order of the call is as follows:  


Specifically, we look at the following connections to close the timing diagram:



When the connection arrives, a Tcpconnection object is created, immediately managed with shared_ptr, the reference count is 1, a weak_ptr (Tie_) is maintained in the channel, the Shared_ptr object is assigned to _tie, and the reference count is still 1. When the connection is closed, in Handleevent, the tie_ is lifted, and a Shard_ptr object is obtained, and the reference count becomes 2. When the count of shared_ptr is not 0 o'clock, Tcpconnection will not be destroyed.


TcpConnection.h

Class tcpconnection:boost::noncopyable, Public boost::enable_shared_from_this<tcpconnection>{  Public:///Constructs a tcpconnection with a connected SOCKFD////User should not create this object. Tcpconnection (eventloop* loop, const string& name, int sockfd, const Inet  address& localaddr, const inetaddress& PEERADDR);  ~tcpconnection ();  eventloop* Getloop () const {return loop_;}  Const string& Name () const {return name_;}  Const inetaddress& localaddress () {return localaddr_;}  Const inetaddress& peeraddress () {return peeraddr_;}  BOOL Connected () const {return state_ = = kconnected;}  void Setconnectioncallback (const connectioncallback& cb) {connectioncallback_ = cb;}  void Setmessagecallback (const messagecallback& cb) {messagecallback_ = cb;}  Internal use only. void Setclosecallback (const closecallback& cb) {closecallback_ = CB;}//Called when TCPServer accepts a new connection void connectestablished ();  Should is called only once//called when tcpserver have removed me from its map void connectdestroyed ();  Should is called only once Private:enum statee {kdisconnected, kconnecting, kconnected, kdisconnecting};  void Handleread (Timestamp receivetime);  void Handleclose ();  void HandleError ();  void SetState (Statee s) {state_ = s;}  eventloop* loop_;//belongs to EventLoop string name_;//connection name Statee State_;  Fixme:use Atomic variable//We don ' t expose those classes to client.  Boost::scoped_ptr<socket> socket_;  Boost::scoped_ptr<channel> Channel_;  InetAddress localaddr_;  InetAddress peeraddr_;  Connectioncallback Connectioncallback_;  Messagecallback Messagecallback_; Closecallback Closecallback_;}; typedef boost::shared_ptr<tcpconnection> TCPCONNECTIONPTR;}


tcpconnection.cc

Tcpconnection::tcpconnection (eventloop* loop, const string& Namearg, int SOCKFD, const inetaddress& LOCALADDR, const INETADD ress& peeraddr): Loop_ (Check_notnull (Loop)), Name_ (Namearg), State_ (kconnecting), socket_ (new socket (SOCKFD ), Channel_ (new channel (Loop, SOCKFD)), Localaddr_ (LOCALADDR), Peeraddr_ (PEERADDR)/*, Highwatermark_ (64*1024* 1024) when the */{//channel-readable event arrives, the callback tcpconnection::handleread,_1 is the time of the event Channel_->setreadcallback (Boost::bind (&tcpco  Nnection::handleread, this, _1)); Connection closed, callback Tcpconnection::handleclose Channel_->setclosecallback (Boost::bind (&tcpconnection::handleclose,  This)); Error occurred, callback Tcpconnection::handleerror Channel_->seterrorcallback (Boost::bind (&tcpconnection::handleerror,  This));            Log_debug << "tcpconnection::ctor[" << name_ << "] at" << this<< "fd=" << sockfd; Socket_->setkeepalive (TRUE);}             Tcpconnection::~tcpconnection () {log_debug << ' tcpconnection::d tor[' << name_ << '] at ' << this << "fd=" << channel_->fd ();}  void Tcpconnection::connectestablished () {loop_->assertinloopthread ();  ASSERT (State_ = = kconnecting);  SetState (kconnected);  Log_trace << "[3] usecount=" << shared_from_this (). Use_count ();  Channel_->tie (Shared_from_this ());  Channel_->enablereading ();//tcpconnection The corresponding channel is added to poller attention Connectioncallback_ (Shared_from_this ()); Log_trace << "[4] usecount=" << shared_from_this (). Use_count ();  void Tcpconnection::connectdestroyed () {loop_->assertinloopthread ();    if (State_ = = kconnected) {setState (kdisconnected);    Channel_->disableall ();  Connectioncallback_ (Shared_from_this ()); } channel_->remove ();}  void Tcpconnection::handleread (Timestamp receivetime) {/* Loop_->assertinloopthread (); InchT savederrno = 0;  ssize_t n = inputbuffer_.readfd (CHANNEL_-&GT;FD (), &savederrno);  if (n > 0) {messagecallback_ (Shared_from_this (), &inputbuffer_, receivetime);  } else if (n = = 0) {handleclose ();    } else {errno = Savederrno;    Log_syserr << "Tcpconnection::handleread";  HandleError ();  } */Loop_->assertinloopthread ();  int savederrno = 0;  Char buf[65536];  ssize_t n =:: Read (CHANNEL_-&GT;FD (), buf, sizeof buf);  if (n > 0) {messagecallback_ (Shared_from_this (), buf, N);  } else if (n = = 0) {handleclose ();    } else {errno = Savederrno;    Log_syserr << "Tcpconnection::handleread";  HandleError ();   }


handling of Tie_ in channel:

void Channel::handleevent (Timestamp receivetime) {  boost::shared_ptr<void> guard;  if (tied_)  {    guard = Tie_.lock ();    if (guard)    {      log_trace << "[6] usecount=" << guard.use_count ();      Handleeventwithguard (receivetime);  Log_trace << "[usecount=]" << guard.use_count ();    }  }  else  {    handleeventwithguard (receivetime);  }}



Reference:

"Linux Multithreaded Server Programming"

"Muduo User Manual"




Muduo Network Library Source Code Analysis (vi) tcpconnection lifetime management

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.