#include <boost/beast/core/role.hpp>
#include <boost/beast/core/string.hpp>
#include <boost/beast/_experimental/test/fail_count.hpp>
+#include <boost/beast/_experimental/test/detail/stream_state.hpp>
#include <boost/asio/async_result.hpp>
#include <boost/asio/buffer.hpp>
#include <boost/asio/error.hpp>
#include <boost/asio/executor_work_guard.hpp>
+#include <boost/asio/any_io_executor.hpp>
#include <boost/asio/io_context.hpp>
#include <boost/asio/post.hpp>
#include <boost/assert.hpp>
@li <em>AsyncReadStream</em>
@li <em>AsyncWriteStream</em>
*/
-class stream
-{
- struct state;
+template<class Executor = net::any_io_executor>
+class basic_stream;
- boost::shared_ptr<state> in_;
- boost::weak_ptr<state> out_;
+template<class Executor>
+void
+teardown(
+ role_type,
+ basic_stream<Executor>& s,
+ boost::system::error_code& ec);
- enum class status
- {
- ok,
- eof,
- };
+template<class Executor, class TeardownHandler>
+void
+async_teardown(
+ role_type role,
+ basic_stream<Executor>& s,
+ TeardownHandler&& handler);
- class service;
- struct service_impl;
+template<class Executor>
+class basic_stream
+{
+public:
+ /// The type of the executor associated with the object.
+ using executor_type =
+ Executor;
- struct read_op_base
+ /// Rebinds the socket type to another executor.
+ template <typename Executor1>
+ struct rebind_executor
{
- virtual ~read_op_base() = default;
- virtual void operator()(error_code ec) = 0;
+ /// The socket type when rebound to the specified executor.
+ typedef basic_stream<Executor1> other;
};
- struct state
- {
- friend class stream;
-
- net::io_context& ioc;
- boost::weak_ptr<service_impl> wp;
- std::mutex m;
- flat_buffer b;
- std::condition_variable cv;
- std::unique_ptr<read_op_base> op;
- status code = status::ok;
- fail_count* fc = nullptr;
- std::size_t nread = 0;
- std::size_t nread_bytes = 0;
- std::size_t nwrite = 0;
- std::size_t nwrite_bytes = 0;
- std::size_t read_max =
- (std::numeric_limits<std::size_t>::max)();
- std::size_t write_max =
- (std::numeric_limits<std::size_t>::max)();
-
- BOOST_BEAST_DECL
- state(
- net::io_context& ioc_,
- boost::weak_ptr<service_impl> wp_,
- fail_count* fc_);
-
-
- BOOST_BEAST_DECL
- ~state();
-
- BOOST_BEAST_DECL
- void
- remove() noexcept;
-
- BOOST_BEAST_DECL
- void
- notify_read();
-
- BOOST_BEAST_DECL
- void
- cancel_read();
- };
+private:
+ template<class Executor2>
+ friend class basic_stream;
+
+ boost::shared_ptr<detail::stream_state> in_;
+ boost::weak_ptr<detail::stream_state> out_;
template<class Handler, class Buffers>
class read_op;
struct run_read_op;
struct run_write_op;
- BOOST_BEAST_DECL
static
void
initiate_read(
- boost::shared_ptr<state> const& in,
- std::unique_ptr<read_op_base>&& op,
+ boost::shared_ptr<detail::stream_state> const& in,
+ std::unique_ptr<detail::stream_read_op_base>&& op,
std::size_t buf_size);
#if ! BOOST_BEAST_DOXYGEN
template<class>
friend class boost::asio::ssl::stream;
// DEPRECATED
- using lowest_layer_type = stream;
+ using lowest_layer_type = basic_stream;
// DEPRECATED
lowest_layer_type&
lowest_layer() noexcept
the peer will see the error `net::error::connection_reset`
when performing any reads or writes.
*/
- BOOST_BEAST_DECL
- ~stream();
+ ~basic_stream();
/** Move Constructor
Moving the stream while asynchronous operations are pending
results in undefined behavior.
*/
- BOOST_BEAST_DECL
- stream(stream&& other);
+ basic_stream(basic_stream&& other);
+
+ /** Move Constructor
+
+ Moving the stream while asynchronous operations are pending
+ results in undefined behavior.
+ */
+ template<class Executor2>
+ basic_stream(basic_stream<Executor2>&& other)
+ : in_(std::move(other.in_))
+ , out_(std::move(other.out_))
+ {
+ BOOST_ASSERT(in_->exec.template target<Executor2>() != nullptr);
+ in_->exec = executor_type(*in_->exec.template target<Executor2>());
+ }
/** Move Assignment
Moving the stream while asynchronous operations are pending
results in undefined behavior.
*/
- BOOST_BEAST_DECL
- stream&
- operator=(stream&& other);
+ basic_stream&
+ operator=(basic_stream&& other);
+
+ template<class Executor2>
+ basic_stream&
+ operator==(basic_stream<Executor2>&& other);
/** Construct a stream
@param ioc The `io_context` object that the stream will use to
dispatch handlers for any asynchronous operations.
*/
- BOOST_BEAST_DECL
+ template <typename ExecutionContext>
+ explicit basic_stream(ExecutionContext& context,
+ typename std::enable_if<
+ std::is_convertible<ExecutionContext&, net::execution_context&>::value
+ >::type* = 0)
+ : basic_stream(context.get_executor())
+ {
+ }
+
+ /** Construct a stream
+
+ The stream will be created in a disconnected state.
+
+ @param exec The `executor` object that the stream will use to
+ dispatch handlers for any asynchronous operations.
+ */
explicit
- stream(net::io_context& ioc);
+ basic_stream(executor_type exec);
/** Construct a stream
fail count. When the fail count reaches its internal limit,
a simulated failure error will be raised.
*/
- BOOST_BEAST_DECL
- stream(
+ basic_stream(
net::io_context& ioc,
fail_count& fc);
@param s A string which will be appended to the input area, not
including the null terminator.
*/
- BOOST_BEAST_DECL
- stream(
+ basic_stream(
net::io_context& ioc,
string_view s);
@param s A string which will be appended to the input area, not
including the null terminator.
*/
- BOOST_BEAST_DECL
- stream(
+ basic_stream(
net::io_context& ioc,
fail_count& fc,
string_view s);
/// Establish a connection
- BOOST_BEAST_DECL
void
- connect(stream& remote);
-
- /// The type of the executor associated with the object.
- using executor_type =
- net::io_context::executor_type;
+ connect(basic_stream& remote);
/// Return the executor associated with the object.
executor_type
- get_executor() noexcept
- {
- return in_->ioc.get_executor();
- };
+ get_executor() noexcept;
/// Set the maximum number of bytes returned by read_some
void
}
/// Returns a string view representing the pending input data
- BOOST_BEAST_DECL
string_view
str() const;
/// Appends a string to the pending input data
- BOOST_BEAST_DECL
void
append(string_view s);
/// Clear the pending input area
- BOOST_BEAST_DECL
void
clear();
The other end of the connection will see
`error::eof` after reading all the remaining data.
*/
- BOOST_BEAST_DECL
void
close();
This end of the connection will see
`error::eof` after reading all the remaining data.
*/
- BOOST_BEAST_DECL
void
close_remote();
*/
template<
class MutableBufferSequence,
- BOOST_BEAST_ASYNC_TPARAM2 ReadHandler>
- BOOST_BEAST_ASYNC_RESULT2(ReadHandler)
+ BOOST_ASIO_COMPLETION_TOKEN_FOR(void(error_code, std::size_t)) ReadHandler
+ BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
+ BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, void(error_code, std::size_t))
async_read_some(
MutableBufferSequence const& buffers,
- ReadHandler&& handler);
+ ReadHandler&& handler BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type));
/** Write some data to the stream.
*/
template<
class ConstBufferSequence,
- BOOST_BEAST_ASYNC_TPARAM2 WriteHandler>
- BOOST_BEAST_ASYNC_RESULT2(WriteHandler)
+ BOOST_ASIO_COMPLETION_TOKEN_FOR(void(error_code, std::size_t)) WriteHandler
+ BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
+ BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, void(error_code, std::size_t))
async_write_some(
ConstBufferSequence const& buffers,
- WriteHandler&& handler);
+ WriteHandler&& handler BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)
+ );
#if ! BOOST_BEAST_DOXYGEN
friend
- BOOST_BEAST_DECL
void
- teardown(
+ teardown<>(
role_type,
- stream& s,
+ basic_stream& s,
boost::system::error_code& ec);
- template<class TeardownHandler>
+ template<class Ex2, class TeardownHandler>
friend
- BOOST_BEAST_DECL
void
async_teardown(
role_type role,
- stream& s,
+ basic_stream<Ex2>& s,
TeardownHandler&& handler);
#endif
};
#if ! BOOST_BEAST_DOXYGEN
-inline
+template<class Executor>
void
-beast_close_socket(stream& s)
+beast_close_socket(basic_stream<Executor>& s)
{
s.close();
}
@return The new, connected stream.
*/
+template<class Executor>
template<class... Args>
-stream
-connect(stream& to, Args&&... args);
+basic_stream
+connect(basic_stream& to, Args&&... args);
#else
-BOOST_BEAST_DECL
-stream
-connect(stream& to);
+template<class Executor>
+basic_stream<Executor>
+connect(basic_stream<Executor>& to);
-BOOST_BEAST_DECL
+template<class Executor>
void
-connect(stream& s1, stream& s2);
+connect(basic_stream<Executor>& s1, basic_stream<Executor>& s2);
-template<class Arg1, class... ArgN>
-stream
-connect(stream& to, Arg1&& arg1, ArgN&&... argn);
+template<class Executor, class Arg1, class... ArgN>
+basic_stream<Executor>
+connect(basic_stream<Executor>& to, Arg1&& arg1, ArgN&&... argn);
#endif
+using stream = basic_stream<>;
+
} // test
} // beast
} // boost
#include <boost/beast/_experimental/test/impl/stream.hpp>
-#ifdef BOOST_BEAST_HEADER_ONLY
+//#ifdef BOOST_BEAST_HEADER_ONLY
#include <boost/beast/_experimental/test/impl/stream.ipp>
-#endif
+//#endif
#endif