gpt4 book ai didi

c++ - 用 Boost.Asio 链接异步 Lambda?

转载 作者:IT老高 更新时间:2023-10-28 22:14:06 31 4
gpt4 key购买 nike

我发现自己编写的代码基本上是这样的:

using boost::system::error_code;

socket.async_connect(endpoint, [&](error_code Error)
{
if (Error)
{
print_error(Error);
return;
}

// Read header
socket.async_read(socket, somebuffer, [&](error_code Error, std::size_t N)
{
if (Error)
{
print_error(Error);
return;
}

// Read actual data
socket.async_read(socket, somebuffer, [&](error_code Error, std::size_t N)
{
// Same here...
});
});
};

所以基本上我将回调嵌套在回调中的回调中,而逻辑简单且“线性”。

有没有更优雅的写法,让代码既本地又有序?

最佳答案

一个优雅的解决方案是使用协程。 Boost.Asio 支持stackless协程,它引入了一小组伪关键字,以及 stackful协程,使用 Boost.Coroutine .


无堆栈协程

无堆栈协程引入了一组伪关键字预处理器宏,它们使用类似于 Duff's Device 的技术实现 switch 语句. documentation详细介绍了每个关键字。

当使用无堆栈协程实现时,原始问题(连接->读取 header ->读取正文)可能类似于以下内容:

struct session
: boost::asio::coroutine
{
boost::asio::ip::tcp::socket socket_;
std::vector<char> buffer_;
// ...

void operator()(boost::system::error_code ec = boost::system::error_code(),
std::size_t length = 0)
{
// In this example we keep the error handling code in one place by
// hoisting it outside the coroutine. An alternative approach would be to
// check the value of ec after each yield for an asynchronous operation.
if (ec)
{
print_error(ec);
return;
}

// On reentering a coroutine, control jumps to the location of the last
// yield or fork. The argument to the "reenter" pseudo-keyword can be a
// pointer or reference to an object of type coroutine.
reenter (this)
{
// Asynchronously connect. When control resumes at the following line,
// the error and length parameters reflect the result of
// the asynchronous operation.
yield socket_.async_connect(endpoint_, *this);

// Loop until an error or shutdown occurs.
while (!shutdown_)
{
// Read header data. When control resumes at the following line,
// the error and length parameters reflect the result of
// the asynchronous operation.
buffer_.resize(fixed_header_size);
yield socket_.async_read(boost::asio::buffer(buffer_), *this);

// Received data. Extract the size of the body from the header.
std::size_t body_size = parse_header(buffer_, length);

// If there is no body size, then leave coroutine, as an invalid
// header was received.
if (!body_size) return;

// Read body data. When control resumes at the following line,
// the error and length parameters reflect the result of
// the asynchronous operation.
buffer_.resize(body_size);
yield socket_.async_read(boost::asio::buffer(buffer_), *this);

// Invoke the user callback to handle the body.
body_handler_(buffer_, length);
}

// Initiate graceful connection closure.
socket_.shutdown(tcp::socket::shutdown_both, ec);
} // end reenter
}
}

堆栈式协程

堆栈协程是使用 spawn() 创建的。功能。当使用堆栈式协程实现时,最初的问题可能如下所示:

boost::asio::spawn(io_service, [&](boost::asio::yield_context yield)
{
boost::system::error_code ec;
boost::asio::ip::tcp::socket socket(io_service);

// Asynchronously connect and suspend the coroutine. The coroutine will
// be resumed automatically when the operation completes.
socket.async_connect(endpoint, yield[ec]);
if (ec)
{
print_error(ec);
return;
}

// Loop until an error or shutdown occurs.
std::vector<char> buffer;
while (!shutdown)
{
// Read header data.
buffer.resize(fixed_header_size);
std::size_t bytes_transferred = socket.async_read(
boost::asio::buffer(buffer), yield[ec]);

if (ec)
{
print_error(ec);
return;
}

// Extract the size of the body from the header.
std::size_t body_size = parse_header(buffer, bytes_transferred);

// If there is no body size, then leave coroutine, as an invalid header
// was received.
if (!body_size) return;

// Read body data.
buffer.resize(body_size);
bytes_transferred =
socket.async_read(boost::asio::buffer(buffer), yield[ec]);

if (ec)
{
print_error(ec);
return;
}

// Invoke the user callback to handle the body.
body_handler_(buffer, length);
}

// Initiate graceful connection closure.
socket.shutdown(tcp::socket::shutdown_both, ec);
});

关于c++ - 用 Boost.Asio 链接异步 Lambda?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13993402/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com