Skip to content

Commit 5a8dfd9

Browse files
committed
github comments addressed
1 parent 397251c commit 5a8dfd9

3 files changed

Lines changed: 251 additions & 141 deletions

File tree

include/boost/beast2/body_write_stream.hpp

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,16 @@
1919
namespace boost {
2020
namespace beast2 {
2121

22+
namespace detail {
23+
24+
template<class, class>
25+
class body_write_stream_op;
26+
27+
template<class>
28+
class body_write_stream_close_op;
29+
30+
} // detail
31+
2232
/** A body writer for HTTP/1 messages.
2333
2434
This type is modelled on asio's AsyncWriteStream, and is constructed with a
@@ -95,15 +105,13 @@ class body_write_stream
95105
valid until the handler is called.
96106
97107
@param srs A http_proto::serializer::stream object which must have been
98-
obtained by a call to `start_stream` on `sr`. Ownership of the
99-
serializer::stream is
100-
retained by the caller, which must guarantee that it remains
101-
valid until the handler is called.
108+
obtained by a call to `start_stream` on `sr`. Ownership of
109+
the serializer::stream is transferred to this object.
102110
*/
103111
explicit body_write_stream(
104112
AsyncWriteStream& s,
105113
http_proto::serializer& sr,
106-
http_proto::serializer::stream& srs);
114+
http_proto::serializer::stream srs);
107115

108116
/** Write some data asynchronously.
109117
@@ -239,9 +247,15 @@ class body_write_stream
239247
async_close(CompletionToken&& handler);
240248

241249
private:
250+
template<class, class>
251+
friend class detail::body_write_stream_op;
252+
253+
template<class>
254+
friend class detail::body_write_stream_close_op;
255+
242256
AsyncWriteStream& stream_;
243257
http_proto::serializer& sr_;
244-
http_proto::serializer::stream& srs_;
258+
http_proto::serializer::stream srs_;
245259
system::error_code ec_;
246260
};
247261

include/boost/beast2/impl/body_write_stream.hpp

Lines changed: 63 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
#include <boost/beast2/write.hpp>
1414

15+
#include <boost/assert.hpp>
1516
#include <boost/asio/buffer.hpp>
1617
#include <boost/asio/buffers_iterator.hpp>
1718
#include <boost/asio/coroutine.hpp>
@@ -24,18 +25,12 @@ namespace detail {
2425
template<class AsyncWriteStream>
2526
class body_write_stream_close_op : public asio::coroutine
2627
{
27-
AsyncWriteStream& stream_;
28-
http_proto::serializer& sr_;
29-
http_proto::serializer::stream& srs_;
28+
body_write_stream<AsyncWriteStream>& bws_;
3029

3130
public:
3231
body_write_stream_close_op(
33-
AsyncWriteStream& s,
34-
http_proto::serializer& sr,
35-
http_proto::serializer::stream& srs) noexcept
36-
: stream_(s)
37-
, sr_(sr)
38-
, srs_(srs)
32+
body_write_stream<AsyncWriteStream>& bws) noexcept
33+
: bws_(bws)
3934
{
4035
}
4136

@@ -50,15 +45,33 @@ class body_write_stream_close_op : public asio::coroutine
5045
{
5146
self.reset_cancellation_state(asio::enable_total_cancellation());
5247

53-
srs_.close();
48+
// Check for a saved error from a previous async_write_some call.
49+
if(bws_.ec_.failed())
50+
{
51+
ec = bws_.ec_;
52+
bws_.ec_ = {};
53+
BOOST_ASIO_CORO_YIELD
54+
{
55+
BOOST_ASIO_HANDLER_LOCATION(
56+
(__FILE__, __LINE__, "immediate"));
57+
auto io_ex = self.get_io_executor();
58+
asio::async_immediate(
59+
io_ex,
60+
asio::append(std::move(self), ec));
61+
}
62+
goto upcall;
63+
}
64+
65+
bws_.srs_.close();
5466

5567
BOOST_ASIO_CORO_YIELD
5668
{
5769
BOOST_ASIO_HANDLER_LOCATION(
5870
(__FILE__, __LINE__, "async_write_some"));
59-
beast2::async_write(stream_, sr_, std::move(self));
71+
beast2::async_write(bws_.stream_, bws_.sr_, std::move(self));
6072
}
6173

74+
upcall:
6275
self.complete(ec);
6376
}
6477
}
@@ -67,25 +80,16 @@ class body_write_stream_close_op : public asio::coroutine
6780
template<class ConstBufferSequence, class AsyncWriteStream>
6881
class body_write_stream_op : public asio::coroutine
6982
{
70-
AsyncWriteStream& stream_;
83+
body_write_stream<AsyncWriteStream>& bws_;
7184
ConstBufferSequence cb_;
72-
http_proto::serializer& sr_;
73-
http_proto::serializer::stream& srs_;
74-
system::error_code& saved_ec_;
7585
std::size_t bytes_;
7686

7787
public:
7888
body_write_stream_op(
79-
AsyncWriteStream& s,
80-
ConstBufferSequence const& cb,
81-
http_proto::serializer& sr,
82-
http_proto::serializer::stream& srs,
83-
system::error_code& saved_ec) noexcept
84-
: stream_(s)
89+
body_write_stream<AsyncWriteStream>& bws,
90+
ConstBufferSequence const& cb) noexcept
91+
: bws_(bws)
8592
, cb_(cb)
86-
, sr_(sr)
87-
, srs_(srs)
88-
, saved_ec_(saved_ec)
8993
, bytes_(0)
9094
{
9195
}
@@ -99,28 +103,19 @@ class body_write_stream_op : public asio::coroutine
99103
{
100104
BOOST_ASIO_CORO_REENTER(*this)
101105
{
102-
self.reset_cancellation_state(asio::enable_total_cancellation());
106+
// Verify preconditions
107+
BOOST_ASSERT(!bws_.sr_.is_done());
103108

104-
bytes_ = 0;
109+
self.reset_cancellation_state(asio::enable_total_cancellation());
105110

106-
// Check for a saved error from a previous call
107-
if(saved_ec_.failed())
108-
{
109-
ec = saved_ec_;
110-
saved_ec_ = {};
111-
}
112-
else if(buffers::size(cb_) == 0)
113-
// A zero-sized buffer is a special case, we are required to
114-
// complete immediately with no error.
115-
;
116-
else if(sr_.is_done() ||
117-
!srs_.is_open())
118-
// The serializer and stream are in the wrong state.
119-
ec = asio::error::not_connected;
120-
121-
if(ec.failed() ||
111+
// A zero-sized buffer is a special case, we are required to
112+
// complete immediately with no error. Also check for a saved
113+
// error from a previous call.
114+
if(bws_.ec_.failed() ||
122115
buffers::size(cb_) == 0)
123116
{
117+
ec = bws_.ec_;
118+
bws_.ec_ = {};
124119
BOOST_ASIO_CORO_YIELD
125120
{
126121
BOOST_ASIO_HANDLER_LOCATION(
@@ -137,39 +132,36 @@ class body_write_stream_op : public asio::coroutine
137132
// option but to try to write to the stream to clear space.
138133
// This may require multiple attempts as buffer space cannot
139134
// be cleared until the headers have been written.
140-
while(!(bytes_ = asio::buffer_copy(srs_.prepare(), cb_)))
135+
for(;;)
141136
{
137+
bytes_ = asio::buffer_copy(bws_.srs_.prepare(), cb_);
138+
bws_.srs_.commit(bytes_);
139+
142140
BOOST_ASIO_CORO_YIELD
143141
{
144142
BOOST_ASIO_HANDLER_LOCATION(
145143
(__FILE__, __LINE__, "async_write_some"));
146-
async_write_some(stream_, sr_, std::move(self));
144+
async_write_some(bws_.stream_, bws_.sr_, std::move(self));
147145
}
148146

149-
if(sr_.is_done() ||
150-
!srs_.is_open())
151-
ec = asio::error::not_connected;
152-
else if(!!self.cancelled())
153-
ec = asio::error::operation_aborted;
154-
155147
if(ec.failed())
156-
goto upcall;
157-
}
158-
srs_.commit(bytes_);
148+
{
149+
if(bytes_ != 0)
150+
{
151+
bws_.ec_ = ec;
152+
ec = {};
153+
}
154+
break;
155+
}
159156

160-
BOOST_ASIO_CORO_YIELD
161-
{
162-
BOOST_ASIO_HANDLER_LOCATION(
163-
(__FILE__, __LINE__, "async_write_some"));
164-
beast2::async_write_some(stream_, sr_, std::move(self));
165-
}
157+
if(bytes_ != 0)
158+
break;
166159

167-
// Save error/cancellation for next call, but report success with bytes
168-
if(ec.failed() ||
169-
!!self.cancelled())
170-
{
171-
saved_ec_ = ec.failed() ? ec : asio::error::operation_aborted;
172-
ec = {};
160+
if(!!self.cancelled())
161+
{
162+
ec = asio::error::operation_aborted;
163+
break;
164+
}
173165
}
174166

175167
upcall:
@@ -190,11 +182,13 @@ body_write_stream<AsyncWriteStream>::
190182
body_write_stream(
191183
AsyncWriteStream& s,
192184
http_proto::serializer& sr,
193-
http_proto::serializer::stream& srs)
185+
http_proto::serializer::stream srs)
194186
: stream_(s)
195187
, sr_(sr)
196-
, srs_(srs)
188+
, srs_(std::move(srs))
197189
{
190+
// Verify preconditions
191+
BOOST_ASSERT(srs_.is_open());
198192
}
199193

200194
template<class AsyncWriteStream>
@@ -213,7 +207,7 @@ async_write_some(
213207
return asio::
214208
async_compose<CompletionToken, void(system::error_code, std::size_t)>(
215209
detail::body_write_stream_op<ConstBufferSequence, AsyncWriteStream>{
216-
stream_, cb, sr_, srs_, ec_ },
210+
*this, cb },
217211
token,
218212
stream_);
219213
}
@@ -231,8 +225,7 @@ async_close(
231225
{
232226
return asio::
233227
async_compose<CompletionToken, void(system::error_code)>(
234-
detail::body_write_stream_close_op<AsyncWriteStream>{
235-
stream_, sr_, srs_ },
228+
detail::body_write_stream_close_op<AsyncWriteStream>{ *this },
236229
token,
237230
stream_);
238231
}

0 commit comments

Comments
 (0)