Skip to content

Commit 57a8b1e

Browse files
committed
fix serializer move constructor and assignment
1 parent e3d1943 commit 57a8b1e

5 files changed

Lines changed: 244 additions & 50 deletions

File tree

include/boost/http_proto/detail/workspace.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,11 @@ class workspace
8888
*/
8989
workspace(workspace&&) noexcept;
9090

91+
/** Assignment.
92+
*/
93+
workspace&
94+
operator=(workspace&&) noexcept;
95+
9196
/** Allocate internal storage.
9297
9398
@throws std::logic_error this->size() > 0

include/boost/http_proto/serializer.hpp

Lines changed: 61 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ class serializer
7070
using const_buffers_type =
7171
buffers::const_buffer_span;
7272

73+
class stream;
74+
7375
/** Serializer configuration settings.
7476
*/
7577
struct config
@@ -159,27 +161,75 @@ class serializer
159161
std::size_t max_type_erase = 1024;
160162
};
161163

162-
class stream;
164+
/** Constructor.
163165
164-
/** Destructor
166+
@param ctx The serializer will access services
167+
registered with this context.
165168
*/
166169
BOOST_HTTP_PROTO_DECL
167-
~serializer();
170+
serializer(
171+
const rts::context& ctx);
168172

169-
/** Constructor
173+
/** Constructor.
174+
175+
The states of `other` are transferred
176+
to the newly constructed object,
177+
which includes the allocated buffer.
178+
After construction, the moved-from object
179+
left in a valid but unspecified state.
180+
181+
Buffer sequences previously obtained
182+
using @ref prepare or @ref stream::prepare
183+
remain valid.
184+
185+
@par Postconditions
186+
@code
187+
other.is_done() == true
188+
@endcode
189+
190+
@par Complexity
191+
Constant.
192+
193+
@par Exception Safety
194+
Throws nothing.
195+
196+
@param other The serializer to move from.
170197
*/
171198
BOOST_HTTP_PROTO_DECL
172199
serializer(
173-
serializer&&) noexcept;
200+
serializer&& other) noexcept;
174201

175-
/** Constructor
202+
/** Assignment.
176203
177-
@param ctx The serializer will access services
178-
registered with this context.
204+
The states of `other` are transferred
205+
`this`, which includes the allocated buffer.
206+
The previous state of `this` are destroyed.
207+
After assignment, the moved-from object
208+
left in a valid but unspecified state.
209+
210+
@par Postconditions
211+
@code
212+
other.is_done() == true
213+
@endcode
214+
215+
@par Complexity
216+
Constant.
217+
218+
@par Exception Safety
219+
Throws nothing.
220+
221+
@param other The serializer to assign from.
222+
@return A reference to this object.
179223
*/
180224
BOOST_HTTP_PROTO_DECL
181-
serializer(
182-
rts::context& ctx);
225+
serializer&
226+
operator=(
227+
serializer&& other) noexcept;
228+
229+
/** Destructor
230+
*/
231+
BOOST_HTTP_PROTO_DECL
232+
~serializer();
183233

184234
//--------------------------------------------
185235

@@ -381,9 +431,7 @@ class serializer
381431
stream
382432
};
383433

384-
rts::context& ctx_;
385-
serializer_service& svc_;
386-
434+
const rts::context* ctx_;
387435
detail::workspace ws_;
388436

389437
detail::filter* filter_;

src/detail/workspace.cpp

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <boost/http_proto/detail/workspace.hpp>
1212
#include <boost/http_proto/detail/except.hpp>
1313
#include <boost/assert.hpp>
14+
#include <utility>
1415

1516
namespace boost {
1617
namespace http_proto {
@@ -46,7 +47,7 @@ workspace(
4647
workspace&& other) noexcept
4748
: begin_(other.begin_)
4849
, front_(other.front_)
49-
, head_(other.end_)
50+
, head_(other.head_)
5051
, back_(other.back_)
5152
, end_(other.end_)
5253
{
@@ -57,6 +58,25 @@ workspace(
5758
other.end_ = nullptr;
5859
}
5960

61+
workspace&
62+
workspace::
63+
operator=(
64+
workspace&& other) noexcept
65+
{
66+
if(begin_)
67+
{
68+
clear();
69+
delete[] begin_;
70+
begin_ = nullptr;
71+
}
72+
std::swap(begin_, other.begin_);
73+
std::swap(front_, other.front_);
74+
std::swap(head_, other.head_);
75+
std::swap(back_, other.back_);
76+
std::swap(end_, other.end_);
77+
return *this;
78+
}
79+
6080
void
6181
workspace::
6282
allocate(

src/serializer.cpp

Lines changed: 73 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -113,13 +113,13 @@ class zlib_filter
113113

114114
public:
115115
zlib_filter(
116-
rts::context& ctx,
116+
const rts::context* ctx,
117117
http_proto::detail::workspace& ws,
118118
int comp_level,
119119
int window_bits,
120120
int mem_level)
121121
: zlib_filter_base(ws)
122-
, svc_(ctx.get_service<rts::zlib::deflate_service>())
122+
, svc_(ctx->get_service<rts::zlib::deflate_service>())
123123
{
124124
system::error_code ec = static_cast<rts::zlib::error>(svc_.init2(
125125
strm_,
@@ -179,11 +179,11 @@ class brotli_filter
179179

180180
public:
181181
brotli_filter(
182-
rts::context& ctx,
182+
const rts::context* ctx,
183183
http_proto::detail::workspace&,
184184
std::uint32_t comp_quality,
185185
std::uint32_t comp_window)
186-
: svc_(ctx.get_service<rts::brotli::encode_service>())
186+
: svc_(ctx->get_service<rts::brotli::encode_service>())
187187
{
188188
// TODO: use custom allocator
189189
state_ = svc_.create_instance(nullptr, nullptr, nullptr);
@@ -292,13 +292,61 @@ serializer::
292292

293293
serializer::
294294
serializer(
295-
serializer&&) noexcept = default;
295+
serializer&& other) noexcept
296+
: ctx_(other.ctx_)
297+
, ws_(std::move(other.ws_))
298+
, filter_(other.filter_)
299+
, buf_gen_(other.buf_gen_)
300+
, source_(other.source_)
301+
, out_(other.out_)
302+
, in_(other.in_)
303+
, prepped_(other.prepped_)
304+
, tmp_(other.tmp_)
305+
, st_(other.st_)
306+
, chunk_header_len_(other.chunk_header_len_)
307+
, more_input_(other.more_input_)
308+
, is_done_(other.is_done_)
309+
, is_header_done_(other.is_header_done_)
310+
, is_chunked_(other.is_chunked_)
311+
, needs_exp100_continue_(other.needs_exp100_continue_)
312+
, filter_done_(other.filter_done_)
313+
{
314+
other.is_done_ = true;
315+
}
296316

317+
serializer&
297318
serializer::
298-
serializer(rts::context& ctx)
299-
: ctx_(ctx)
300-
, svc_(ctx.get_service<serializer_service>())
301-
, ws_(svc_.space_needed)
319+
operator=(
320+
serializer&& other) noexcept
321+
{
322+
ctx_ = other.ctx_;
323+
ws_ = std::move(other.ws_);
324+
filter_ = other.filter_;
325+
buf_gen_ = other.buf_gen_;
326+
source_ = other.source_;
327+
out_ = other.out_;
328+
in_ = other.in_;
329+
prepped_ = other.prepped_;
330+
tmp_ = other.tmp_;
331+
st_ = other.st_;
332+
chunk_header_len_ = other.chunk_header_len_;
333+
more_input_ = other.more_input_;
334+
is_done_ = other.is_done_;
335+
is_header_done_ = other.is_header_done_;
336+
is_chunked_ = other.is_chunked_;
337+
needs_exp100_continue_ = other.needs_exp100_continue_;
338+
filter_done_ = other.filter_done_;
339+
340+
other.is_done_ = true;
341+
342+
return *this;
343+
}
344+
345+
serializer::
346+
serializer(const rts::context& ctx)
347+
: ctx_(&ctx)
348+
, ws_(ctx_->get_service<
349+
serializer_service>().space_needed)
302350
, is_done_(true)
303351
{
304352
}
@@ -609,8 +657,8 @@ consume(
609657
if(needs_exp100_continue_)
610658
return;
611659

612-
ws_.clear();
613-
is_done_ = true;
660+
// ready for next message
661+
reset();
614662
}
615663

616664
//------------------------------------------------
@@ -653,41 +701,44 @@ start_init(
653701
// Transfer-Encoding
654702
is_chunked_ = md.transfer_encoding.is_chunked;
655703

704+
auto& cfg = ctx_->get_service<
705+
serializer_service>().cfg;
706+
656707
// Content-Encoding
657708
switch (md.content_encoding.coding)
658709
{
659710
case content_coding::deflate:
660-
if(!svc_.cfg.apply_deflate_encoder)
711+
if(!cfg.apply_deflate_encoder)
661712
goto no_filter;
662713
filter_ = &ws_.emplace<zlib_filter>(
663714
ctx_,
664715
ws_,
665-
svc_.cfg.zlib_comp_level,
666-
svc_.cfg.zlib_window_bits,
667-
svc_.cfg.zlib_mem_level);
716+
cfg.zlib_comp_level,
717+
cfg.zlib_window_bits,
718+
cfg.zlib_mem_level);
668719
filter_done_ = false;
669720
break;
670721

671722
case content_coding::gzip:
672-
if(!svc_.cfg.apply_gzip_encoder)
723+
if(!cfg.apply_gzip_encoder)
673724
goto no_filter;
674725
filter_ = &ws_.emplace<zlib_filter>(
675726
ctx_,
676727
ws_,
677-
svc_.cfg.zlib_comp_level,
678-
svc_.cfg.zlib_window_bits + 16,
679-
svc_.cfg.zlib_mem_level);
728+
cfg.zlib_comp_level,
729+
cfg.zlib_window_bits + 16,
730+
cfg.zlib_mem_level);
680731
filter_done_ = false;
681732
break;
682733

683734
case content_coding::br:
684-
if(!svc_.cfg.apply_brotli_encoder)
735+
if(!cfg.apply_brotli_encoder)
685736
goto no_filter;
686737
filter_ = &ws_.emplace<brotli_filter>(
687738
ctx_,
688739
ws_,
689-
svc_.cfg.brotli_comp_quality,
690-
svc_.cfg.brotli_comp_window);
740+
cfg.brotli_comp_quality,
741+
cfg.brotli_comp_window);
691742
filter_done_ = false;
692743
break;
693744

0 commit comments

Comments
 (0)