boost.asio中的异步async_*函数需要传入回调函数参数,如果回调函数使用lamda表达式,在’capture’列表中传入智能指针,智能指针会生效吗?
在async_connect调用之前,我们创建一个shared_ptr对象,并以值传入的形式放到lamda的’caputer’列表中,最后发现shared_ptr在async_connect的异步回调函数完成后析构了其管理的对象,可见其是生效的。
其实最好还是用uinque_ptr,但lamda中不支持move捕获。
测试代码如下:
class LIBTEST_BOOST_DLL TcpServer
{
public:
typedef boost::asio::ip::tcp::socket tcp_socket_t;
typedef boost::asio::ip::tcp::acceptor tcp_acceptor_t;
typedef boost::asio::ip::tcp::endpoint tcp_endpoint_t;
typedef boost::asio::io_context io_context_t;
TcpServer(io_context_t &io, const tcp_endpoint_t& endpoint);
void Accept();
void ReadHandler(tcp_socket_t *sock);
private:
tcp_acceptor_t acceptor_;
io_context_t *io_;
uint64_t cnt_ = 0;
};
class LIBTEST_BOOST_DLL TcpClient
{
public:
typedef boost::asio::ip::tcp::socket tcp_socket_t;
typedef boost::asio::ip::tcp::endpoint tcp_endpoint_t;
typedef boost::asio::io_context io_context_t;
TcpClient(io_context_t &io);
void Connect(const tcp_endpoint_t& endpoint);
void Write();
private:
tcp_socket_t sock_;
io_context_t *io_;
uint64_t cnt_ = 0;
};
TcpServer::TcpServer(io_context_t &io, const tcp_endpoint_t& endpoint)
:acceptor_(io,endpoint),io_(&io)
{
}
void TcpServer::ReadHandler(tcp_socket_t *sock)
{
char *buf = new char[1024];
sock->async_read_some(boost::asio::buffer(buf,1024), [sock, this,buf](const std::error_code &ec, std::size_t sz) {
delete buf;
if (ec) {
sock->close();
cout << "[threadId=" << this_thread::get_id() << "] " << "async_read_some callback error,msg=" << ec.message()<< endl;
delete sock;
return;
}
//cout << "[" << this_thread::get_id() << "] " << &buf_[0];// << endl;
cnt_++;
cout << "[threadId=" << this_thread::get_id() << "] " << "async_read_some callback cnt=" << cnt_ << ",size=" << sz << endl;
ReadHandler(sock);
sock->close();
sock->close();
sock->close();
});
}
void TcpServer::Accept()
{
//auto sock = make_shared<tcp_socket_t>(*io_);
auto sock = new tcp_socket_t(*io_);
auto acceptHandler = [this,sock](const std::error_code &ec) {
if (ec) {
delete sock;
cout << "[threadId=" << this_thread::get_id() << "] " << "async_accept callback error,msg=" << ec.message() << endl;
return;
}
cout << "[threadId=" << this_thread::get_id() << "]";
cout << " async_accept callback client from: ";
cout << sock->remote_endpoint().address() <<":" << sock->remote_endpoint().port() << endl;
ReadHandler(sock);
Accept();
};
acceptor_.async_accept(*sock, acceptHandler);
}
TcpClient::TcpClient(io_context_t &io)
:sock_(io),io_(&io)
{
}
void TcpClient::Write()
{
auto buf = new char[1024];
memset(buf,'q',1024);
sock_.async_write_some(boost::asio::buffer(buf,1024), [this,buf](const std::error_code &ec, std::size_t sz) {
delete buf;
if (ec) {
cout << "[threadId=" << this_thread::get_id() << "] " << "async_write_some callback error,msg=" << ec.message() << endl;
sock_.close();
return;
}
cnt_++;
cout << "[threadId=" << this_thread::get_id() << "] " << "async_write_some callback cnt=" << cnt_ << ",size=" << sz<< endl;
});
}
class Test {
public:
~Test() { cout << "Test destructor" << endl; }
};
typedef std::shared_ptr<Test> mc_ptr_t;
void GiveMeOwership(mc_ptr_t ptr)
{
cout << "hello,world" << endl;
}
void TcpClient::Connect(const tcp_endpoint_t& endpoint)
{
auto ptr = mc_ptr_t(new Test());
//async func will also increase the `user` of shared_ptr
auto connHandler = [this, endpoint,ptr](const std::error_code &ec) {
if (ec) {
cout << "[threadId=" << this_thread::get_id() << "] " << "async_connect callback error,msg=" << ec.message() << endl;
//Connect(endpoint);
return;
}
cout << "[threadId=" << this_thread::get_id() << "] ";
cout << "async_connect callback to ";
cout << this->sock_.remote_endpoint().address();
cout << " success" << endl;;
std::thread t([this](){
//1000000
for(int i=0;i<1;i++)
Write();
});
t.detach();
};
sock_.async_connect(endpoint, connHandler);
}
int main(int argc, char *argv[])
{
//auto ptr = mc_ptr_t(new Test);
//GiveMeOwership(std::move(ptr));
#if 1
boost::asio::io_context io;
boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::tcp::v4(), 1234);
TcpServer tcp(io,endpoint);
TcpClient client(io);
tcp.Accept();
client.Connect(boost::asio::ip::tcp::endpoint(boost::asio::ip::address::from_string("127.0.0.1"),1234));
boost::asio::io_context::work worker(io);
io.run();
#endif
#ifdef WIN32
system("pause");
#endif
return 0;
}
输出如下: