|
Boost : |
From: Richard Hodges (hodges.r_at_[hidden])
Date: 2021-09-21 20:46:49
On Tue, 21 Sept 2021 at 17:22, ÐмиÑÑий ÐÑÑ
ипов via Boost <
boost_at_[hidden]> wrote:
> I haven't tested it, but this should probably work:
>
> class session {
> public:
> session(tcp::socket socket)
> : session(std::make_unique<session_impl>(std::move(socket)))
> {}
>
> void start() { do_read(); }
>
> private:
> session(std::unique_ptr<session_impl> 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();
>
> вÑ, 21 ÑенÑ. 2021 г. в 18:02, Andrzej Krzemienski via Boost
> <boost_at_[hidden]>:
> >
> > wt., 21 wrz 2021 o 16:50 Vinnie Falco via Boost <boost_at_[hidden]>
> > napisaÅ(a):
> >
> > > On Tue, Sep 21, 2021 at 7:34 AM Andrzej Krzemienski via Boost
> > > <boost_at_[hidden]> 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.
>
Dear Andrzej,
The use of shared_ptr in asio examples is largely an historic artefact from
when the only completion type was only a function object, as in these
examples.
When using this style of asynchronous completion it is convenient to use
some kind of reference-counted pointer to maintain the lifetime of IO
objects such as sockets and their associated state, such as buffers. You
don't *have* to use a reference-counting but you will need to ensure that
the io objects and related buffers are not deleted while there are any
asynchronous operations in progress against them. A shared_ptr happens to
be the most convenient way of doing this when:
- using continuation-passing style completion handlers, and
- the lifetime of the io object is not deterministic.
When using other styles of completion handling, such as the in-built
coroutine support, reference counting can often become less important since
code can be written in a "structured concurrency" style. In this way,
asynchronous code can be laid out with the same structure as synchronous
code. IO Object lifetimes then become governed by the coroutines that
created them and are awaiting asynchronous operations against them.
> > >
> > > 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
>
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk