wt., 21 wrz 2021 o 17:22 Дмитрий Архипов via Boost
I haven't tested it, but this should probably work:
class session { public: session(tcp::socket socket) : session(std::make_unique
(std::move(socket))) {} void start() { do_read(); }
private: session(std::unique_ptr
impl) : impl_(std::move(impl)) {} void do_read() { auto& impl = *impl_; impl.socket.async_read_some( boost::asio::buffer(impl.data, max_length), [impl = std::move(impl_)](boost::system::error_code ec, std::size_t length) mutable { if (ec) { return; } session(std::move(impl)).do_write(length); }); }
void do_write(std::size_t length) { ... }
auto constexpr max_length = 1024; struct session_impl { session_impl(tcp::socket socket) : socket_(std::move(socket)) {} tcp::socket socket_; char data_[max_length]; }; };
...
session(std::move(socket)).start();
Thank you for this example. I haven't compiled it yet, but my superficial analysis tells me that it should work. I asked the question, you gave the right answer, so I should only be thankful, I guess. But having seen the answer, I now realize that I asked the wrong question. The question that I really wanted to ask is: do I have to heap-allocate "IO" objects in order to use tem with continuation-passing style completion handlers? My observation about the example code: void do_read() { auto self(shared_from_this()); *socket_ *// <-- socket passed in one place .async_read_some(boost::asio::buffer(data_, max_length), [this, *self*] // <-- socket passed in another place (boost::system::error_code ec, std::size_t length) { if (!ec) { do_write(length); } }); } is that I have to pass my socket in two places in one function invocation. Whereas, at least at high level, I could imagine an interface when I only pass it once (by movig) to function async_read_some, and after the function has made the read it passes (via a move) the socket argument to the handler. Is there something fundamental that makes this impossible? Regards, &rzej;
вт, 21 сент. 2021 г. в 18:02, Andrzej Krzemienski via Boost
: wt., 21 wrz 2021 o 16:50 Vinnie Falco via Boost
napisał(a): On Tue, Sep 21, 2021 at 7:34 AM Andrzej Krzemienski via Boost
wrote: I am not trying to solve any specific problem. It just strikes me
that a
shared_ptr is used in a demo example for the library. I was always of the opinion that a shared_ptr is often abused as a way of doing an ad-hoc GC.
In theory it should work since the echo protocol is half-duplex. What happens when you switch it to unique_ptr? Move-only handlers should work, but it is possible that Chris missed a place that is still doing a copy.
It breaks when I pass a callback (completion handler), for instance in:
void do_read() { auto self(shared_from_this()); socket_.async_read_some(boost::asio::buffer(data_, max_length), [this, *self*](boost::system::error_code ec, std::size_t length) { if (!ec) { do_write(length); } }); }
I would need to move the data inside the lambda capture, but if I do it, the subsequent call to socket_.async_read_some() is UB.
In order for this to work, the function `async_read_some()` would have to pass the socket back to my handler after it has performed the read.
Regards, &rzej;
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost