在使用时间循环驱动时,往往在类外面启动了一个EventLoop,来驱动事件的处理。 依托该EventLoop的类在析构时,有时候需要进行一些善后处理,这些处理往往就将任务放入到了EventLoop队列中。 注意:在丢进EventLoop丢列的任务,一定不要使用正在析构类的函数对象,一定要确保丢入的函数对象在运行时是合法的。
下面以muduo中TcpClient源代码进行说明
namespace muduo
{
namespace net
{
namespace detail
{
void removeConnection(EventLoop* loop, const TcpConnectionPtr& conn)
{
loop->queueInLoop(std::bind(&TcpConnection::connectDestroyed, conn));
}
void removeConnector(const ConnectorPtr& connector)
{
//connector->
}
} // namespace detail
} // namespace net
} // namespace muduo
TcpClient::~TcpClient()
{
LOG_INFO << "TcpClient::~TcpClient[" << name_
<< "] - connector " << get_pointer(connector_);
TcpConnectionPtr conn;
bool unique = false;
{
MutexLockGuard lock(mutex_);
unique = connection_.unique();
conn = connection_;
}
if (conn)
{
assert(loop_ == conn->getLoop());
// FIXME: not 100% safe, if we are in different thread
CloseCallback cb = std::bind(&detail::removeConnection, loop_, _1);
loop_->runInLoop(
std::bind(&TcpConnection::setCloseCallback, conn, cb));
if (unique)
{
conn->forceClose();
}
}
else
{
connector_->stop();
// FIXME: HACK
loop_->runAfter(1, std::bind(&detail::removeConnector, connector_));
}
}
1、CloseCallback cb = std::bind(&detail::removeConnection, loop_, _1); 放入的是全局函数对象 2、std::bind(&TcpConnection::setCloseCallback, conn, cb) 放入的是函数对象是shared_ptr,只要有对对象的引用,就能保证对象不能被释放
|