mirror of
https://github.com/boostorg/beast.git
synced 2025-07-30 12:57:31 +02:00
Fixes to test::stream::async_read:
- Call the completion handler with the correct signature - Replicate ASIO socket behavior of async operation completions - Fix a data race between read_op and a call to stream::nread() Signed-off-by: Damian Jarek <damian.jarek93@gmail.com>
This commit is contained in:
committed by
Vinnie Falco
parent
adcd4bc0c9
commit
34362256c0
@ -7,6 +7,7 @@ Version 210:
|
|||||||
* Add executor_type trait
|
* Add executor_type trait
|
||||||
* Fix hexadecimal string conversion table
|
* Fix hexadecimal string conversion table
|
||||||
* is_completion_handler, type_traits.hpp are deprecated
|
* is_completion_handler, type_traits.hpp are deprecated
|
||||||
|
* Fixes to test::stream::async_read
|
||||||
|
|
||||||
API Changes:
|
API Changes:
|
||||||
|
|
||||||
|
@ -210,13 +210,16 @@ New websocket-chat-multi example
|
|||||||
* `ostream`
|
* `ostream`
|
||||||
does not overflow or exceed the dynamic buffer's maximum size
|
does not overflow or exceed the dynamic buffer's maximum size
|
||||||
|
|
||||||
* A handler work guard is maintained on paused websocket operations
|
* Fixes to
|
||||||
|
`test::stream::async_read`
|
||||||
* All behavior of default-constructed iterators is conforming
|
|
||||||
|
|
||||||
* `file_mode::append_existing`
|
* `file_mode::append_existing`
|
||||||
works correctly
|
works correctly
|
||||||
|
|
||||||
|
* A handler work guard is maintained on paused websocket operations
|
||||||
|
|
||||||
|
* All behavior of default-constructed iterators is conforming
|
||||||
|
|
||||||
[/-----------------------------------------------------------------------------]
|
[/-----------------------------------------------------------------------------]
|
||||||
|
|
||||||
[heading Boost 1.69]
|
[heading Boost 1.69]
|
||||||
|
@ -427,7 +427,8 @@ TeardownHandler&& handler)
|
|||||||
s.in_->fc->fail(ec))
|
s.in_->fc->fail(ec))
|
||||||
return net::post(
|
return net::post(
|
||||||
s.get_executor(),
|
s.get_executor(),
|
||||||
beast::bind_front_handler(std::move(handler), ec));
|
beast::bind_front_handler(
|
||||||
|
std::move(handler), ec));
|
||||||
s.close();
|
s.close();
|
||||||
if( s.in_->fc &&
|
if( s.in_->fc &&
|
||||||
s.in_->fc->fail(ec))
|
s.in_->fc->fail(ec))
|
||||||
@ -437,7 +438,8 @@ TeardownHandler&& handler)
|
|||||||
|
|
||||||
net::post(
|
net::post(
|
||||||
s.get_executor(),
|
s.get_executor(),
|
||||||
beast::bind_front_handler(std::move(handler), ec));
|
beast::bind_front_handler(
|
||||||
|
std::move(handler), ec));
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@ -445,15 +447,16 @@ TeardownHandler&& handler)
|
|||||||
template<class Handler, class Buffers>
|
template<class Handler, class Buffers>
|
||||||
class stream::read_op : public stream::read_op_base
|
class stream::read_op : public stream::read_op_base
|
||||||
{
|
{
|
||||||
using ex1_type = net::io_context::executor_type;
|
using ex1_type =
|
||||||
using ex2_type = net::associated_executor_t<Handler, ex1_type>;
|
net::io_context::executor_type;
|
||||||
|
using ex2_type
|
||||||
|
= net::associated_executor_t<Handler, ex1_type>;
|
||||||
|
|
||||||
class lambda
|
class lambda
|
||||||
{
|
{
|
||||||
state& s_;
|
state& s_;
|
||||||
Buffers b_;
|
Buffers b_;
|
||||||
Handler h_;
|
Handler h_;
|
||||||
net::executor_work_guard<ex1_type> wg1_;
|
|
||||||
net::executor_work_guard<ex2_type> wg2_;
|
net::executor_work_guard<ex2_type> wg2_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -465,76 +468,66 @@ class stream::read_op : public stream::read_op_base
|
|||||||
: s_(s)
|
: s_(s)
|
||||||
, b_(b)
|
, b_(b)
|
||||||
, h_(std::forward<DeducedHandler>(h))
|
, h_(std::forward<DeducedHandler>(h))
|
||||||
, wg1_(s_.ioc.get_executor())
|
|
||||||
, wg2_(net::get_associated_executor(
|
, wg2_(net::get_associated_executor(
|
||||||
h_, s_.ioc.get_executor()))
|
h_, s_.ioc.get_executor()))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
post()
|
|
||||||
{
|
|
||||||
net::post(
|
|
||||||
s_.ioc.get_executor(),
|
|
||||||
std::move(*this));
|
|
||||||
wg1_.reset();
|
|
||||||
wg2_.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
operator()()
|
operator()()
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lock{s_.m};
|
std::unique_lock<std::mutex> lock{s_.m};
|
||||||
|
error_code ec;
|
||||||
|
std::size_t bytes_transferred = 0;
|
||||||
BOOST_ASSERT(! s_.op);
|
BOOST_ASSERT(! s_.op);
|
||||||
if(s_.b.size() > 0)
|
if(s_.b.size() > 0)
|
||||||
{
|
{
|
||||||
auto const bytes_transferred =
|
bytes_transferred =
|
||||||
net::buffer_copy(
|
net::buffer_copy(
|
||||||
b_, s_.b.data(), s_.read_max);
|
b_, s_.b.data(), s_.read_max);
|
||||||
s_.b.consume(bytes_transferred);
|
s_.b.consume(bytes_transferred);
|
||||||
auto& s = s_;
|
++s_.nread;
|
||||||
Handler h{std::move(h_)};
|
|
||||||
lock.unlock();
|
|
||||||
++s.nread;
|
|
||||||
net::post(
|
|
||||||
s.ioc.get_executor(),
|
|
||||||
beast::bind_front_handler(
|
|
||||||
std::move(h),
|
|
||||||
error_code{},
|
|
||||||
bytes_transferred));
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(s_.code != status::ok);
|
BOOST_ASSERT(s_.code != status::ok);
|
||||||
auto& s = s_;
|
auto& s = s_;
|
||||||
Handler h{std::move(h_)};
|
|
||||||
lock.unlock();
|
|
||||||
++s.nread;
|
++s.nread;
|
||||||
error_code ec;
|
|
||||||
if(s.code == status::eof)
|
if(s.code == status::eof)
|
||||||
ec = net::error::eof;
|
ec = net::error::eof;
|
||||||
else if(s.code == status::reset)
|
else if(s.code == status::reset)
|
||||||
ec = net::error::connection_reset;
|
ec = net::error::connection_reset;
|
||||||
net::post(
|
|
||||||
s.ioc.get_executor(),
|
|
||||||
beast::bind_front_handler(std::move(h), ec, 0));
|
|
||||||
}
|
}
|
||||||
|
lock.unlock();
|
||||||
|
auto alloc = net::get_associated_allocator(h_);
|
||||||
|
wg2_.get_executor().dispatch(
|
||||||
|
beast::bind_front_handler(
|
||||||
|
std::move(h_),
|
||||||
|
ec,
|
||||||
|
bytes_transferred), alloc);
|
||||||
|
wg2_.reset();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
lambda fn_;
|
lambda fn_;
|
||||||
|
net::executor_work_guard<ex1_type> wg1_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
template<class DeducedHandler>
|
template<class DeducedHandler>
|
||||||
read_op(state& s, Buffers const& b, DeducedHandler&& h)
|
read_op(state& s, Buffers const& b, DeducedHandler&& h)
|
||||||
: fn_(s, b, std::forward<DeducedHandler>(h))
|
: fn_(s, b, std::forward<DeducedHandler>(h))
|
||||||
|
, wg1_(s.ioc.get_executor())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
operator()() override
|
operator()() override
|
||||||
{
|
{
|
||||||
fn_.post();
|
net::post(
|
||||||
|
wg1_.get_executor(),
|
||||||
|
std::move(fn_));
|
||||||
|
wg1_.reset();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user