summaryrefslogtreecommitdiff
path: root/boost/asio/impl
diff options
context:
space:
mode:
Diffstat (limited to 'boost/asio/impl')
-rw-r--r--boost/asio/impl/awaitable.hpp424
-rw-r--r--boost/asio/impl/buffered_read_stream.hpp107
-rw-r--r--boost/asio/impl/buffered_write_stream.hpp99
-rw-r--r--boost/asio/impl/co_spawn.hpp140
-rw-r--r--boost/asio/impl/compose.hpp421
-rw-r--r--boost/asio/impl/connect.hpp410
-rw-r--r--boost/asio/impl/defer.hpp58
-rw-r--r--boost/asio/impl/detached.hpp132
-rw-r--r--boost/asio/impl/dispatch.hpp59
-rw-r--r--boost/asio/impl/error.ipp2
-rw-r--r--boost/asio/impl/execution_context.hpp14
-rw-r--r--boost/asio/impl/execution_context.ipp2
-rw-r--r--boost/asio/impl/executor.hpp31
-rw-r--r--boost/asio/impl/executor.ipp2
-rw-r--r--boost/asio/impl/handler_alloc_hook.ipp2
-rw-r--r--boost/asio/impl/io_context.hpp130
-rw-r--r--boost/asio/impl/io_context.ipp7
-rw-r--r--boost/asio/impl/post.hpp58
-rw-r--r--boost/asio/impl/read.hpp570
-rw-r--r--boost/asio/impl/read_at.hpp147
-rw-r--r--boost/asio/impl/read_until.hpp2070
-rw-r--r--boost/asio/impl/redirect_error.hpp374
-rw-r--r--boost/asio/impl/serial_port_base.hpp2
-rw-r--r--boost/asio/impl/serial_port_base.ipp2
-rw-r--r--boost/asio/impl/spawn.hpp47
-rw-r--r--boost/asio/impl/src.cpp2
-rw-r--r--boost/asio/impl/src.hpp2
-rw-r--r--boost/asio/impl/system_context.hpp2
-rw-r--r--boost/asio/impl/system_context.ipp11
-rw-r--r--boost/asio/impl/system_executor.hpp2
-rw-r--r--boost/asio/impl/thread_pool.hpp2
-rw-r--r--boost/asio/impl/thread_pool.ipp21
-rw-r--r--boost/asio/impl/use_awaitable.hpp278
-rw-r--r--boost/asio/impl/use_future.hpp52
-rw-r--r--boost/asio/impl/write.hpp520
-rw-r--r--boost/asio/impl/write_at.hpp146
36 files changed, 5146 insertions, 1202 deletions
diff --git a/boost/asio/impl/awaitable.hpp b/boost/asio/impl/awaitable.hpp
new file mode 100644
index 0000000000..b8cf5373a1
--- /dev/null
+++ b/boost/asio/impl/awaitable.hpp
@@ -0,0 +1,424 @@
+//
+// impl/awaitable.hpp
+// ~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_IMPL_AWAITABLE_HPP
+#define BOOST_ASIO_IMPL_AWAITABLE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <exception>
+#include <new>
+#include <tuple>
+#include <utility>
+#include <boost/asio/detail/thread_context.hpp>
+#include <boost/asio/detail/thread_info_base.hpp>
+#include <boost/asio/detail/type_traits.hpp>
+#include <boost/asio/post.hpp>
+#include <boost/system/system_error.hpp>
+#include <boost/asio/this_coro.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+// An awaitable_thread represents a thread-of-execution that is composed of one
+// or more "stack frames", with each frame represented by an awaitable_frame.
+// All execution occurs in the context of the awaitable_thread's executor. An
+// awaitable_thread continues to "pump" the stack frames by repeatedly resuming
+// the top stack frame until the stack is empty, or until ownership of the
+// stack is transferred to another awaitable_thread object.
+//
+// +------------------------------------+
+// | top_of_stack_ |
+// | V
+// +--------------+---+ +-----------------+
+// | | | |
+// | awaitable_thread |<---------------------------+ awaitable_frame |
+// | | attached_thread_ | |
+// +--------------+---+ (Set only when +---+-------------+
+// | frames are being |
+// | actively pumped | caller_
+// | by a thread, and |
+// | then only for V
+// | the top frame.) +-----------------+
+// | | |
+// | | awaitable_frame |
+// | | |
+// | +---+-------------+
+// | |
+// | | caller_
+// | :
+// | :
+// | |
+// | V
+// | +-----------------+
+// | bottom_of_stack_ | |
+// +------------------------------->| awaitable_frame |
+// | |
+// +-----------------+
+
+template <typename Executor>
+class awaitable_frame_base
+{
+public:
+#if !defined(BOOST_ASIO_DISABLE_AWAITABLE_FRAME_RECYCLING)
+ void* operator new(std::size_t size)
+ {
+ return boost::asio::detail::thread_info_base::allocate(
+ boost::asio::detail::thread_info_base::awaitable_frame_tag(),
+ boost::asio::detail::thread_context::thread_call_stack::top(),
+ size);
+ }
+
+ void operator delete(void* pointer, std::size_t size)
+ {
+ boost::asio::detail::thread_info_base::deallocate(
+ boost::asio::detail::thread_info_base::awaitable_frame_tag(),
+ boost::asio::detail::thread_context::thread_call_stack::top(),
+ pointer, size);
+ }
+#endif // !defined(BOOST_ASIO_DISABLE_AWAITABLE_FRAME_RECYCLING)
+
+ // The frame starts in a suspended state until the awaitable_thread object
+ // pumps the stack.
+ auto initial_suspend() noexcept
+ {
+ return suspend_always();
+ }
+
+ // On final suspension the frame is popped from the top of the stack.
+ auto final_suspend() noexcept
+ {
+ struct result
+ {
+ awaitable_frame_base* this_;
+
+ bool await_ready() const noexcept
+ {
+ return false;
+ }
+
+ void await_suspend(coroutine_handle<void>) noexcept
+ {
+ this_->pop_frame();
+ }
+
+ void await_resume() const noexcept
+ {
+ }
+ };
+
+ return result{this};
+ }
+
+ void set_except(std::exception_ptr e) noexcept
+ {
+ pending_exception_ = e;
+ }
+
+ void set_error(const boost::system::error_code& ec)
+ {
+ this->set_except(std::make_exception_ptr(boost::system::system_error(ec)));
+ }
+
+ void unhandled_exception()
+ {
+ set_except(std::current_exception());
+ }
+
+ void rethrow_exception()
+ {
+ if (pending_exception_)
+ {
+ std::exception_ptr ex = std::exchange(pending_exception_, nullptr);
+ std::rethrow_exception(ex);
+ }
+ }
+
+ template <typename T>
+ auto await_transform(awaitable<T, Executor> a) const
+ {
+ return a;
+ }
+
+ // This await transformation obtains the associated executor of the thread of
+ // execution.
+ auto await_transform(this_coro::executor_t) noexcept
+ {
+ struct result
+ {
+ awaitable_frame_base* this_;
+
+ bool await_ready() const noexcept
+ {
+ return true;
+ }
+
+ void await_suspend(coroutine_handle<void>) noexcept
+ {
+ }
+
+ auto await_resume() const noexcept
+ {
+ return this_->attached_thread_->get_executor();
+ }
+ };
+
+ return result{this};
+ }
+
+ // This await transformation is used to run an async operation's initiation
+ // function object after the coroutine has been suspended. This ensures that
+ // immediate resumption of the coroutine in another thread does not cause a
+ // race condition.
+ template <typename Function>
+ auto await_transform(Function f,
+ typename enable_if<
+ is_convertible<
+ typename result_of<Function(awaitable_frame_base*)>::type,
+ awaitable_thread<Executor>*
+ >::value
+ >::type* = 0)
+ {
+ struct result
+ {
+ Function function_;
+ awaitable_frame_base* this_;
+
+ bool await_ready() const noexcept
+ {
+ return false;
+ }
+
+ void await_suspend(coroutine_handle<void>) noexcept
+ {
+ function_(this_);
+ }
+
+ void await_resume() const noexcept
+ {
+ }
+ };
+
+ return result{std::move(f), this};
+ }
+
+ void attach_thread(awaitable_thread<Executor>* handler) noexcept
+ {
+ attached_thread_ = handler;
+ }
+
+ awaitable_thread<Executor>* detach_thread() noexcept
+ {
+ return std::exchange(attached_thread_, nullptr);
+ }
+
+ void push_frame(awaitable_frame_base<Executor>* caller) noexcept
+ {
+ caller_ = caller;
+ attached_thread_ = caller_->attached_thread_;
+ attached_thread_->top_of_stack_ = this;
+ caller_->attached_thread_ = nullptr;
+ }
+
+ void pop_frame() noexcept
+ {
+ if (caller_)
+ caller_->attached_thread_ = attached_thread_;
+ attached_thread_->top_of_stack_ = caller_;
+ attached_thread_ = nullptr;
+ caller_ = nullptr;
+ }
+
+ void resume()
+ {
+ coro_.resume();
+ }
+
+ void destroy()
+ {
+ coro_.destroy();
+ }
+
+protected:
+ coroutine_handle<void> coro_ = nullptr;
+ awaitable_thread<Executor>* attached_thread_ = nullptr;
+ awaitable_frame_base<Executor>* caller_ = nullptr;
+ std::exception_ptr pending_exception_ = nullptr;
+};
+
+template <typename T, typename Executor>
+class awaitable_frame
+ : public awaitable_frame_base<Executor>
+{
+public:
+ awaitable_frame() noexcept
+ {
+ }
+
+ awaitable_frame(awaitable_frame&& other) noexcept
+ : awaitable_frame_base<Executor>(std::move(other))
+ {
+ }
+
+ ~awaitable_frame()
+ {
+ if (has_result_)
+ static_cast<T*>(static_cast<void*>(result_))->~T();
+ }
+
+ awaitable<T, Executor> get_return_object() noexcept
+ {
+ this->coro_ = coroutine_handle<awaitable_frame>::from_promise(*this);
+ return awaitable<T, Executor>(this);
+ };
+
+ template <typename U>
+ void return_value(U&& u)
+ {
+ new (&result_) T(std::forward<U>(u));
+ has_result_ = true;
+ }
+
+ template <typename... Us>
+ void return_values(Us&&... us)
+ {
+ this->return_value(std::forward_as_tuple(std::forward<Us>(us)...));
+ }
+
+ T get()
+ {
+ this->caller_ = nullptr;
+ this->rethrow_exception();
+ return std::move(*static_cast<T*>(static_cast<void*>(result_)));
+ }
+
+private:
+ alignas(T) unsigned char result_[sizeof(T)];
+ bool has_result_ = false;
+};
+
+template <typename Executor>
+class awaitable_frame<void, Executor>
+ : public awaitable_frame_base<Executor>
+{
+public:
+ awaitable<void, Executor> get_return_object()
+ {
+ this->coro_ = coroutine_handle<awaitable_frame>::from_promise(*this);
+ return awaitable<void, Executor>(this);
+ };
+
+ void return_void()
+ {
+ }
+
+ void get()
+ {
+ this->caller_ = nullptr;
+ this->rethrow_exception();
+ }
+};
+
+template <typename Executor>
+class awaitable_thread
+{
+public:
+ typedef Executor executor_type;
+
+ // Construct from the entry point of a new thread of execution.
+ awaitable_thread(awaitable<void, Executor> p, const Executor& ex)
+ : bottom_of_stack_(std::move(p)),
+ top_of_stack_(bottom_of_stack_.frame_),
+ executor_(ex)
+ {
+ }
+
+ // Transfer ownership from another awaitable_thread.
+ awaitable_thread(awaitable_thread&& other) noexcept
+ : bottom_of_stack_(std::move(other.bottom_of_stack_)),
+ top_of_stack_(std::exchange(other.top_of_stack_, nullptr)),
+ executor_(std::move(other.executor_))
+ {
+ }
+
+ // Clean up with a last ditch effort to ensure the thread is unwound within
+ // the context of the executor.
+ ~awaitable_thread()
+ {
+ if (bottom_of_stack_.valid())
+ {
+ // Coroutine "stack unwinding" must be performed through the executor.
+ (post)(executor_,
+ [a = std::move(bottom_of_stack_)]() mutable
+ {
+ awaitable<void, Executor>(std::move(a));
+ });
+ }
+ }
+
+ executor_type get_executor() const noexcept
+ {
+ return executor_;
+ }
+
+ // Launch a new thread of execution.
+ void launch()
+ {
+ top_of_stack_->attach_thread(this);
+ pump();
+ }
+
+protected:
+ template <typename> friend class awaitable_frame_base;
+
+ // Repeatedly resume the top stack frame until the stack is empty or until it
+ // has been transferred to another resumable_thread object.
+ void pump()
+ {
+ do top_of_stack_->resume(); while (top_of_stack_);
+ if (bottom_of_stack_.valid())
+ {
+ awaitable<void, Executor> a(std::move(bottom_of_stack_));
+ a.frame_->rethrow_exception();
+ }
+ }
+
+ awaitable<void, Executor> bottom_of_stack_;
+ awaitable_frame_base<Executor>* top_of_stack_;
+ executor_type executor_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#if !defined(GENERATING_DOCUMENTATION)
+
+namespace std { namespace experimental {
+
+template <typename T, typename Executor, typename... Args>
+struct coroutine_traits<boost::asio::awaitable<T, Executor>, Args...>
+{
+ typedef boost::asio::detail::awaitable_frame<T, Executor> promise_type;
+};
+
+}} // namespace std::experimental
+
+#endif // !defined(GENERATING_DOCUMENTATION)
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_IMPL_AWAITABLE_HPP
diff --git a/boost/asio/impl/buffered_read_stream.hpp b/boost/asio/impl/buffered_read_stream.hpp
index 2e1c55842b..6a51d8ee56 100644
--- a/boost/asio/impl/buffered_read_stream.hpp
+++ b/boost/asio/impl/buffered_read_stream.hpp
@@ -2,7 +2,7 @@
// impl/buffered_read_stream.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -21,6 +21,7 @@
#include <boost/asio/detail/handler_cont_helpers.hpp>
#include <boost/asio/detail/handler_invoke_helpers.hpp>
#include <boost/asio/detail/handler_type_requirements.hpp>
+#include <boost/asio/detail/non_const_lvalue.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -138,6 +139,28 @@ namespace detail
boost_asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
}
+
+ struct initiate_async_buffered_fill
+ {
+ template <typename ReadHandler, typename Stream>
+ void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
+ buffered_stream_storage* storage, Stream* next_layer) const
+ {
+ // If you get an error on the following line it means that your handler
+ // does not meet the documented type requirements for a ReadHandler.
+ BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
+
+ non_const_lvalue<ReadHandler> handler2(handler);
+ std::size_t previous_size = storage->size();
+ storage->resize(storage->capacity());
+ next_layer->async_read_some(
+ buffer(
+ storage->data() + previous_size,
+ storage->size() - previous_size),
+ buffered_fill_handler<typename decay<ReadHandler>::type>(
+ *storage, previous_size, handler2.value));
+ }
+ };
} // namespace detail
#if !defined(GENERATING_DOCUMENTATION)
@@ -177,24 +200,9 @@ BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
buffered_read_stream<Stream>::async_fill(
BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
{
- // If you get an error on the following line it means that your handler does
- // not meet the documented type requirements for a ReadHandler.
- BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
-
- async_completion<ReadHandler,
- void (boost::system::error_code, std::size_t)> init(handler);
-
- std::size_t previous_size = storage_.size();
- storage_.resize(storage_.capacity());
- next_layer_.async_read_some(
- buffer(
- storage_.data() + previous_size,
- storage_.size() - previous_size),
- detail::buffered_fill_handler<BOOST_ASIO_HANDLER_TYPE(
- ReadHandler, void (boost::system::error_code, std::size_t))>(
- storage_, previous_size, init.completion_handler));
-
- return init.result.get();
+ return async_initiate<ReadHandler,
+ void (boost::system::error_code, std::size_t)>(
+ detail::initiate_async_buffered_fill(), handler, &storage_, &next_layer_);
}
template <typename Stream>
@@ -327,6 +335,38 @@ namespace detail
boost_asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
}
+
+ struct initiate_async_buffered_read_some
+ {
+ template <typename ReadHandler, typename Stream,
+ typename MutableBufferSequence>
+ void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
+ buffered_stream_storage* storage, Stream* next_layer,
+ const MutableBufferSequence& buffers) const
+ {
+ // If you get an error on the following line it means that your handler
+ // does not meet the documented type requirements for a ReadHandler.
+ BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
+
+ using boost::asio::buffer_size;
+ non_const_lvalue<ReadHandler> handler2(handler);
+ if (buffer_size(buffers) == 0 || !storage->empty())
+ {
+ next_layer->async_read_some(BOOST_ASIO_MUTABLE_BUFFER(0, 0),
+ buffered_read_some_handler<MutableBufferSequence,
+ typename decay<ReadHandler>::type>(
+ *storage, buffers, handler2.value));
+ }
+ else
+ {
+ initiate_async_buffered_fill()(
+ buffered_read_some_handler<MutableBufferSequence,
+ typename decay<ReadHandler>::type>(
+ *storage, buffers, handler2.value),
+ storage, next_layer);
+ }
+ }
+ };
} // namespace detail
#if !defined(GENERATING_DOCUMENTATION)
@@ -375,31 +415,10 @@ buffered_read_stream<Stream>::async_read_some(
const MutableBufferSequence& buffers,
BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
{
- // If you get an error on the following line it means that your handler does
- // not meet the documented type requirements for a ReadHandler.
- BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
-
- async_completion<ReadHandler,
- void (boost::system::error_code, std::size_t)> init(handler);
-
- using boost::asio::buffer_size;
- if (buffer_size(buffers) == 0 || !storage_.empty())
- {
- next_layer_.async_read_some(BOOST_ASIO_MUTABLE_BUFFER(0, 0),
- detail::buffered_read_some_handler<
- MutableBufferSequence, BOOST_ASIO_HANDLER_TYPE(
- ReadHandler, void (boost::system::error_code, std::size_t))>(
- storage_, buffers, init.completion_handler));
- }
- else
- {
- this->async_fill(detail::buffered_read_some_handler<
- MutableBufferSequence, BOOST_ASIO_HANDLER_TYPE(
- ReadHandler, void (boost::system::error_code, std::size_t))>(
- storage_, buffers, init.completion_handler));
- }
-
- return init.result.get();
+ return async_initiate<ReadHandler,
+ void (boost::system::error_code, std::size_t)>(
+ detail::initiate_async_buffered_read_some(),
+ handler, &storage_, &next_layer_, buffers);
}
template <typename Stream>
diff --git a/boost/asio/impl/buffered_write_stream.hpp b/boost/asio/impl/buffered_write_stream.hpp
index c5ebf7537b..05d4406347 100644
--- a/boost/asio/impl/buffered_write_stream.hpp
+++ b/boost/asio/impl/buffered_write_stream.hpp
@@ -2,7 +2,7 @@
// impl/buffered_write_stream.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -21,6 +21,7 @@
#include <boost/asio/detail/handler_cont_helpers.hpp>
#include <boost/asio/detail/handler_invoke_helpers.hpp>
#include <boost/asio/detail/handler_type_requirements.hpp>
+#include <boost/asio/detail/non_const_lvalue.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -124,6 +125,23 @@ namespace detail
boost_asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
}
+
+ struct initiate_async_buffered_flush
+ {
+ template <typename WriteHandler, typename Stream>
+ void operator()(BOOST_ASIO_MOVE_ARG(WriteHandler) handler,
+ buffered_stream_storage* storage, Stream* next_layer) const
+ {
+ // If you get an error on the following line it means that your handler
+ // does not meet the documented type requirements for a WriteHandler.
+ BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
+
+ non_const_lvalue<WriteHandler> handler2(handler);
+ async_write(*next_layer, buffer(storage->data(), storage->size()),
+ buffered_flush_handler<typename decay<WriteHandler>::type>(
+ *storage, handler2.value));
+ }
+ };
} // namespace detail
#if !defined(GENERATING_DOCUMENTATION)
@@ -163,19 +181,10 @@ BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
buffered_write_stream<Stream>::async_flush(
BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
{
- // If you get an error on the following line it means that your handler does
- // not meet the documented type requirements for a WriteHandler.
- BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
-
- async_completion<WriteHandler,
- void (boost::system::error_code, std::size_t)> init(handler);
-
- async_write(next_layer_, buffer(storage_.data(), storage_.size()),
- detail::buffered_flush_handler<BOOST_ASIO_HANDLER_TYPE(
- WriteHandler, void (boost::system::error_code, std::size_t))>(
- storage_, init.completion_handler));
-
- return init.result.get();
+ return async_initiate<WriteHandler,
+ void (boost::system::error_code, std::size_t)>(
+ detail::initiate_async_buffered_flush(),
+ handler, &storage_, &next_layer_);
}
template <typename Stream>
@@ -314,6 +323,38 @@ namespace detail
boost_asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
}
+
+ struct initiate_async_buffered_write_some
+ {
+ template <typename WriteHandler, typename Stream,
+ typename ConstBufferSequence>
+ void operator()(BOOST_ASIO_MOVE_ARG(WriteHandler) handler,
+ buffered_stream_storage* storage, Stream* next_layer,
+ const ConstBufferSequence& buffers) const
+ {
+ // If you get an error on the following line it means that your handler
+ // does not meet the documented type requirements for a WriteHandler.
+ BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
+
+ using boost::asio::buffer_size;
+ non_const_lvalue<WriteHandler> handler2(handler);
+ if (buffer_size(buffers) == 0 || storage->size() < storage->capacity())
+ {
+ next_layer->async_write_some(BOOST_ASIO_CONST_BUFFER(0, 0),
+ buffered_write_some_handler<ConstBufferSequence,
+ typename decay<WriteHandler>::type>(
+ *storage, buffers, handler2.value));
+ }
+ else
+ {
+ initiate_async_buffered_flush()(
+ buffered_write_some_handler<ConstBufferSequence,
+ typename decay<WriteHandler>::type>(
+ *storage, buffers, handler2.value),
+ storage, next_layer);
+ }
+ }
+ };
} // namespace detail
#if !defined(GENERATING_DOCUMENTATION)
@@ -362,32 +403,10 @@ buffered_write_stream<Stream>::async_write_some(
const ConstBufferSequence& buffers,
BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
{
- // If you get an error on the following line it means that your handler does
- // not meet the documented type requirements for a WriteHandler.
- BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
-
- async_completion<WriteHandler,
- void (boost::system::error_code, std::size_t)> init(handler);
-
- using boost::asio::buffer_size;
- if (buffer_size(buffers) == 0
- || storage_.size() < storage_.capacity())
- {
- next_layer_.async_write_some(BOOST_ASIO_CONST_BUFFER(0, 0),
- detail::buffered_write_some_handler<
- ConstBufferSequence, BOOST_ASIO_HANDLER_TYPE(
- WriteHandler, void (boost::system::error_code, std::size_t))>(
- storage_, buffers, init.completion_handler));
- }
- else
- {
- this->async_flush(detail::buffered_write_some_handler<
- ConstBufferSequence, BOOST_ASIO_HANDLER_TYPE(
- WriteHandler, void (boost::system::error_code, std::size_t))>(
- storage_, buffers, init.completion_handler));
- }
-
- return init.result.get();
+ return async_initiate<WriteHandler,
+ void (boost::system::error_code, std::size_t)>(
+ detail::initiate_async_buffered_write_some(),
+ handler, &storage_, &next_layer_, buffers);
}
template <typename Stream>
diff --git a/boost/asio/impl/co_spawn.hpp b/boost/asio/impl/co_spawn.hpp
new file mode 100644
index 0000000000..19770cd865
--- /dev/null
+++ b/boost/asio/impl/co_spawn.hpp
@@ -0,0 +1,140 @@
+//
+// impl/co_spawn.hpp
+// ~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_IMPL_CO_SPAWN_HPP
+#define BOOST_ASIO_IMPL_CO_SPAWN_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <boost/asio/awaitable.hpp>
+#include <boost/asio/dispatch.hpp>
+#include <boost/asio/post.hpp>
+#include <boost/asio/use_awaitable.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+template <typename T, typename Executor, typename F, typename Handler>
+awaitable<void, Executor> co_spawn_entry_point(
+ awaitable<T, Executor>*, Executor ex, F f, Handler handler)
+{
+ auto spawn_work = make_work_guard(ex);
+ auto handler_work = make_work_guard(handler, ex);
+
+ (void) co_await (post)(spawn_work.get_executor(),
+ use_awaitable_t<Executor>{});
+
+ bool done = false;
+ try
+ {
+ T t = co_await f();
+
+ done = true;
+
+ (dispatch)(handler_work.get_executor(),
+ [handler = std::move(handler), t = std::move(t)]() mutable
+ {
+ handler(std::exception_ptr(), std::move(t));
+ });
+ }
+ catch (...)
+ {
+ if (done)
+ throw;
+
+ (dispatch)(handler_work.get_executor(),
+ [handler = std::move(handler), e = std::current_exception()]() mutable
+ {
+ handler(e, T());
+ });
+ }
+}
+
+template <typename Executor, typename F, typename Handler>
+awaitable<void, Executor> co_spawn_entry_point(
+ awaitable<void, Executor>*, Executor ex, F f, Handler handler)
+{
+ auto spawn_work = make_work_guard(ex);
+ auto handler_work = make_work_guard(handler, ex);
+
+ (void) co_await (post)(spawn_work.get_executor(),
+ use_awaitable_t<Executor>{});
+
+ std::exception_ptr e = nullptr;
+ try
+ {
+ co_await f();
+ }
+ catch (...)
+ {
+ e = std::current_exception();
+ }
+
+ (dispatch)(handler_work.get_executor(),
+ [handler = std::move(handler), e]() mutable
+ {
+ handler(e);
+ });
+}
+
+struct initiate_co_spawn
+{
+ template <typename Handler, typename Executor, typename F>
+ void operator()(Handler&& handler, const Executor& ex, F&& f) const
+ {
+ typedef typename result_of<F()>::type awaitable_type;
+ typedef typename awaitable_type::executor_type executor_type;
+
+ executor_type ex2(ex);
+ auto a = (co_spawn_entry_point)(static_cast<awaitable_type*>(nullptr),
+ ex2, std::forward<F>(f), std::forward<Handler>(handler));
+ awaitable_handler<executor_type, void>(std::move(a), ex2).launch();
+ }
+};
+
+} // namespace detail
+
+template <typename Executor, typename F, typename CompletionToken>
+inline BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken,
+ typename detail::awaitable_signature<typename result_of<F()>::type>::type)
+co_spawn(const Executor& ex, F&& f, CompletionToken&& token,
+ typename enable_if<
+ is_executor<Executor>::value
+ >::type*)
+{
+ return async_initiate<CompletionToken,
+ typename detail::awaitable_signature<typename result_of<F()>::type>>(
+ detail::initiate_co_spawn(), token, ex, std::forward<F>(f));
+}
+
+template <typename ExecutionContext, typename F, typename CompletionToken>
+inline BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken,
+ typename detail::awaitable_signature<typename result_of<F()>::type>::type)
+co_spawn(ExecutionContext& ctx, F&& f, CompletionToken&& token,
+ typename enable_if<
+ is_convertible<ExecutionContext&, execution_context&>::value
+ >::type*)
+{
+ return (co_spawn)(ctx.get_executor(), std::forward<F>(f),
+ std::forward<CompletionToken>(token));
+}
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_IMPL_CO_SPAWN_HPP
diff --git a/boost/asio/impl/compose.hpp b/boost/asio/impl/compose.hpp
new file mode 100644
index 0000000000..76fe54d066
--- /dev/null
+++ b/boost/asio/impl/compose.hpp
@@ -0,0 +1,421 @@
+//
+// impl/compose.hpp
+// ~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_IMPL_COMPOSE_HPP
+#define BOOST_ASIO_IMPL_COMPOSE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <boost/asio/detail/handler_alloc_helpers.hpp>
+#include <boost/asio/detail/handler_cont_helpers.hpp>
+#include <boost/asio/detail/handler_invoke_helpers.hpp>
+#include <boost/asio/detail/type_traits.hpp>
+#include <boost/asio/detail/variadic_templates.hpp>
+#include <boost/asio/executor_work_guard.hpp>
+#include <boost/asio/is_executor.hpp>
+#include <boost/asio/system_executor.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+
+namespace detail
+{
+ template <typename>
+ struct composed_work;
+
+ template <>
+ struct composed_work<void()>
+ {
+ composed_work() BOOST_ASIO_NOEXCEPT
+ : head_(system_executor())
+ {
+ }
+
+ void reset()
+ {
+ head_.reset();
+ }
+
+ typedef system_executor head_type;
+ executor_work_guard<system_executor> head_;
+ };
+
+ inline composed_work<void()> make_composed_work()
+ {
+ return composed_work<void()>();
+ }
+
+ template <typename Head>
+ struct composed_work<void(Head)>
+ {
+ explicit composed_work(const Head& ex) BOOST_ASIO_NOEXCEPT
+ : head_(ex)
+ {
+ }
+
+ void reset()
+ {
+ head_.reset();
+ }
+
+ typedef Head head_type;
+ executor_work_guard<Head> head_;
+ };
+
+ template <typename Head>
+ inline composed_work<void(Head)> make_composed_work(const Head& head)
+ {
+ return composed_work<void(Head)>(head);
+ }
+
+#if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
+
+ template <typename Head, typename... Tail>
+ struct composed_work<void(Head, Tail...)>
+ {
+ explicit composed_work(const Head& head,
+ const Tail&... tail) BOOST_ASIO_NOEXCEPT
+ : head_(head),
+ tail_(tail...)
+ {
+ }
+
+ void reset()
+ {
+ head_.reset();
+ tail_.reset();
+ }
+
+ typedef Head head_type;
+ executor_work_guard<Head> head_;
+ composed_work<void(Tail...)> tail_;
+ };
+
+ template <typename Head, typename... Tail>
+ inline composed_work<void(Head, Tail...)>
+ make_composed_work(const Head& head, const Tail&... tail)
+ {
+ return composed_work<void(Head, Tail...)>(head, tail...);
+ }
+
+#else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
+
+#define BOOST_ASIO_PRIVATE_COMPOSED_WORK_DEF(n) \
+ template <typename Head, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
+ struct composed_work<void(Head, BOOST_ASIO_VARIADIC_TARGS(n))> \
+ { \
+ explicit composed_work(const Head& head, \
+ BOOST_ASIO_VARIADIC_CONSTREF_PARAMS(n)) BOOST_ASIO_NOEXCEPT \
+ : head_(head), \
+ tail_(BOOST_ASIO_VARIADIC_BYVAL_ARGS(n)) \
+ { \
+ } \
+ \
+ void reset() \
+ { \
+ head_.reset(); \
+ tail_.reset(); \
+ } \
+ \
+ typedef Head head_type; \
+ executor_work_guard<Head> head_; \
+ composed_work<void(BOOST_ASIO_VARIADIC_TARGS(n))> tail_; \
+ }; \
+ \
+ template <typename Head, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
+ inline composed_work<void(Head, BOOST_ASIO_VARIADIC_TARGS(n))> \
+ make_composed_work(const Head& head, BOOST_ASIO_VARIADIC_CONSTREF_PARAMS(n)) \
+ { \
+ return composed_work< \
+ void(Head, BOOST_ASIO_VARIADIC_TARGS(n))>( \
+ head, BOOST_ASIO_VARIADIC_BYVAL_ARGS(n)); \
+ } \
+ /**/
+ BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_COMPOSED_WORK_DEF)
+#undef BOOST_ASIO_PRIVATE_COMPOSED_WORK_DEF
+
+#endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
+
+#if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
+ template <typename Impl, typename Work, typename Handler, typename Signature>
+ class composed_op;
+
+ template <typename Impl, typename Work, typename Handler,
+ typename R, typename... Args>
+ class composed_op<Impl, Work, Handler, R(Args...)>
+#else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
+ template <typename Impl, typename Work, typename Handler, typename Signature>
+ class composed_op
+#endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
+ {
+ public:
+ composed_op(BOOST_ASIO_MOVE_ARG(Impl) impl,
+ BOOST_ASIO_MOVE_ARG(Work) work,
+ BOOST_ASIO_MOVE_ARG(Handler) handler)
+ : impl_(BOOST_ASIO_MOVE_CAST(Impl)(impl)),
+ work_(BOOST_ASIO_MOVE_CAST(Work)(work)),
+ handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)),
+ invocations_(0)
+ {
+ }
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+ composed_op(composed_op&& other)
+ : impl_(BOOST_ASIO_MOVE_CAST(Impl)(other.impl_)),
+ work_(BOOST_ASIO_MOVE_CAST(Work)(other.work_)),
+ handler_(BOOST_ASIO_MOVE_CAST(Handler)(other.handler_)),
+ invocations_(other.invocations_)
+ {
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+ typedef typename associated_executor<Handler,
+ typename Work::head_type>::type executor_type;
+
+ executor_type get_executor() const BOOST_ASIO_NOEXCEPT
+ {
+ return (get_associated_executor)(handler_, work_.head_.get_executor());
+ }
+
+ typedef typename associated_allocator<Handler,
+ std::allocator<void> >::type allocator_type;
+
+ allocator_type get_allocator() const BOOST_ASIO_NOEXCEPT
+ {
+ return (get_associated_allocator)(handler_, std::allocator<void>());
+ }
+
+#if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
+
+ template<typename... T>
+ void operator()(BOOST_ASIO_MOVE_ARG(T)... t)
+ {
+ if (invocations_ < ~unsigned(0))
+ ++invocations_;
+ impl_(*this, BOOST_ASIO_MOVE_CAST(T)(t)...);
+ }
+
+ void complete(Args... args)
+ {
+ this->work_.reset();
+ this->handler_(BOOST_ASIO_MOVE_CAST(Args)(args)...);
+ }
+
+#else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
+
+ void operator()()
+ {
+ if (invocations_ < ~unsigned(0))
+ ++invocations_;
+ impl_(*this);
+ }
+
+ void complete()
+ {
+ this->work_.reset();
+ this->handler_();
+ }
+
+#define BOOST_ASIO_PRIVATE_COMPOSED_OP_DEF(n) \
+ template<BOOST_ASIO_VARIADIC_TPARAMS(n)> \
+ void operator()(BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
+ { \
+ if (invocations_ < ~unsigned(0)) \
+ ++invocations_; \
+ impl_(*this, BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \
+ } \
+ \
+ template<BOOST_ASIO_VARIADIC_TPARAMS(n)> \
+ void complete(BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
+ { \
+ this->work_.reset(); \
+ this->handler_(BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \
+ } \
+ /**/
+ BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_COMPOSED_OP_DEF)
+#undef BOOST_ASIO_PRIVATE_COMPOSED_OP_DEF
+
+#endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
+
+ //private:
+ Impl impl_;
+ Work work_;
+ Handler handler_;
+ unsigned invocations_;
+ };
+
+ template <typename Impl, typename Work, typename Handler, typename Signature>
+ inline void* asio_handler_allocate(std::size_t size,
+ composed_op<Impl, Work, Handler, Signature>* this_handler)
+ {
+ return boost_asio_handler_alloc_helpers::allocate(
+ size, this_handler->handler_);
+ }
+
+ template <typename Impl, typename Work, typename Handler, typename Signature>
+ inline void asio_handler_deallocate(void* pointer, std::size_t size,
+ composed_op<Impl, Work, Handler, Signature>* this_handler)
+ {
+ boost_asio_handler_alloc_helpers::deallocate(
+ pointer, size, this_handler->handler_);
+ }
+
+ template <typename Impl, typename Work, typename Handler, typename Signature>
+ inline bool asio_handler_is_continuation(
+ composed_op<Impl, Work, Handler, Signature>* this_handler)
+ {
+ return this_handler->invocations_ > 1 ? true
+ : boost_asio_handler_cont_helpers::is_continuation(
+ this_handler->handler_);
+ }
+
+ template <typename Function, typename Impl,
+ typename Work, typename Handler, typename Signature>
+ inline void asio_handler_invoke(Function& function,
+ composed_op<Impl, Work, Handler, Signature>* this_handler)
+ {
+ boost_asio_handler_invoke_helpers::invoke(
+ function, this_handler->handler_);
+ }
+
+ template <typename Function, typename Impl,
+ typename Work, typename Handler, typename Signature>
+ inline void asio_handler_invoke(const Function& function,
+ composed_op<Impl, Work, Handler, Signature>* this_handler)
+ {
+ boost_asio_handler_invoke_helpers::invoke(
+ function, this_handler->handler_);
+ }
+
+ template <typename Signature>
+ struct initiate_composed_op
+ {
+ template <typename Handler, typename Impl, typename Work>
+ void operator()(BOOST_ASIO_MOVE_ARG(Handler) handler,
+ BOOST_ASIO_MOVE_ARG(Impl) impl,
+ BOOST_ASIO_MOVE_ARG(Work) work) const
+ {
+ composed_op<typename decay<Impl>::type, typename decay<Work>::type,
+ typename decay<Handler>::type, Signature>(
+ BOOST_ASIO_MOVE_CAST(Impl)(impl), BOOST_ASIO_MOVE_CAST(Work)(work),
+ BOOST_ASIO_MOVE_CAST(Handler)(handler))();
+ }
+ };
+
+ template <typename IoObject>
+ inline typename IoObject::executor_type
+ get_composed_io_executor(IoObject& io_object)
+ {
+ return io_object.get_executor();
+ }
+
+ template <typename Executor>
+ inline const Executor& get_composed_io_executor(const Executor& ex,
+ typename enable_if<is_executor<Executor>::value>::type* = 0)
+ {
+ return ex;
+ }
+} // namespace detail
+
+#if !defined(GENERATING_DOCUMENTATION)
+#if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
+
+template <typename CompletionToken, typename Signature,
+ typename Implementation, typename... IoObjectsOrExecutors>
+BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, Signature)
+async_compose(BOOST_ASIO_MOVE_ARG(Implementation) implementation,
+ BOOST_ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token,
+ BOOST_ASIO_MOVE_ARG(IoObjectsOrExecutors)... io_objects_or_executors)
+{
+ return async_initiate<CompletionToken, Signature>(
+ detail::initiate_composed_op<Signature>(), token,
+ BOOST_ASIO_MOVE_CAST(Implementation)(implementation),
+ detail::make_composed_work(
+ detail::get_composed_io_executor(
+ BOOST_ASIO_MOVE_CAST(IoObjectsOrExecutors)(
+ io_objects_or_executors))...));
+}
+
+#else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
+
+template <typename CompletionToken, typename Signature, typename Implementation>
+BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, Signature)
+async_compose(BOOST_ASIO_MOVE_ARG(Implementation) implementation,
+ BOOST_ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token)
+{
+ return async_initiate<CompletionToken, Signature>(
+ detail::initiate_composed_op<Signature>(), token,
+ BOOST_ASIO_MOVE_CAST(Implementation)(implementation),
+ detail::make_composed_work());
+}
+
+# define BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR(n) \
+ BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_##n
+
+# define BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_1 \
+ detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T1)(x1))
+# define BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_2 \
+ detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T1)(x1)), \
+ detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T2)(x2))
+# define BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_3 \
+ detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T1)(x1)), \
+ detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T2)(x2)), \
+ detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T3)(x3))
+# define BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_4 \
+ detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T1)(x1)), \
+ detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T2)(x2)), \
+ detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T3)(x3)), \
+ detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T4)(x4))
+# define BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_5 \
+ detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T1)(x1)), \
+ detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T2)(x2)), \
+ detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T3)(x3)), \
+ detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T4)(x4)), \
+ detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T5)(x5))
+
+#define BOOST_ASIO_PRIVATE_ASYNC_COMPOSE_DEF(n) \
+ template <typename CompletionToken, typename Signature, \
+ typename Implementation, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
+ BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, Signature) \
+ async_compose(BOOST_ASIO_MOVE_ARG(Implementation) implementation, \
+ BOOST_ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token, \
+ BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
+ { \
+ return async_initiate<CompletionToken, Signature>( \
+ detail::initiate_composed_op<Signature>(), token, \
+ BOOST_ASIO_MOVE_CAST(Implementation)(implementation), \
+ detail::make_composed_work( \
+ BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR(n))); \
+ } \
+ /**/
+ BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_ASYNC_COMPOSE_DEF)
+#undef BOOST_ASIO_PRIVATE_ASYNC_COMPOSE_DEF
+
+#undef BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR
+#undef BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_1
+#undef BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_2
+#undef BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_3
+#undef BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_4
+#undef BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_5
+
+#endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
+#endif // !defined(GENERATING_DOCUMENTATION)
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_IMPL_COMPOSE_HPP
diff --git a/boost/asio/impl/connect.hpp b/boost/asio/impl/connect.hpp
index 497f25884c..51e5e6cb16 100644
--- a/boost/asio/impl/connect.hpp
+++ b/boost/asio/impl/connect.hpp
@@ -2,7 +2,7 @@
// impl/connect.hpp
// ~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -23,6 +23,7 @@
#include <boost/asio/detail/handler_cont_helpers.hpp>
#include <boost/asio/detail/handler_invoke_helpers.hpp>
#include <boost/asio/detail/handler_type_requirements.hpp>
+#include <boost/asio/detail/non_const_lvalue.hpp>
#include <boost/asio/detail/throw_error.hpp>
#include <boost/asio/error.hpp>
#include <boost/asio/post.hpp>
@@ -101,9 +102,8 @@ namespace detail
}
}
-template <typename Protocol BOOST_ASIO_SVC_TPARAM, typename EndpointSequence>
-typename Protocol::endpoint connect(
- basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s,
+template <typename Protocol, typename Executor, typename EndpointSequence>
+typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s,
const EndpointSequence& endpoints,
typename enable_if<is_endpoint_sequence<
EndpointSequence>::value>::type*)
@@ -114,9 +114,8 @@ typename Protocol::endpoint connect(
return result;
}
-template <typename Protocol BOOST_ASIO_SVC_TPARAM, typename EndpointSequence>
-typename Protocol::endpoint connect(
- basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s,
+template <typename Protocol, typename Executor, typename EndpointSequence>
+typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s,
const EndpointSequence& endpoints, boost::system::error_code& ec,
typename enable_if<is_endpoint_sequence<
EndpointSequence>::value>::type*)
@@ -127,8 +126,8 @@ typename Protocol::endpoint connect(
}
#if !defined(BOOST_ASIO_NO_DEPRECATED)
-template <typename Protocol BOOST_ASIO_SVC_TPARAM, typename Iterator>
-Iterator connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s, Iterator begin,
+template <typename Protocol, typename Executor, typename Iterator>
+Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin,
typename enable_if<!is_endpoint_sequence<Iterator>::value>::type*)
{
boost::system::error_code ec;
@@ -137,8 +136,8 @@ Iterator connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s, Iterator begin,
return result;
}
-template <typename Protocol BOOST_ASIO_SVC_TPARAM, typename Iterator>
-inline Iterator connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s,
+template <typename Protocol, typename Executor, typename Iterator>
+inline Iterator connect(basic_socket<Protocol, Executor>& s,
Iterator begin, boost::system::error_code& ec,
typename enable_if<!is_endpoint_sequence<Iterator>::value>::type*)
{
@@ -146,8 +145,8 @@ inline Iterator connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s,
}
#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
-template <typename Protocol BOOST_ASIO_SVC_TPARAM, typename Iterator>
-Iterator connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s,
+template <typename Protocol, typename Executor, typename Iterator>
+Iterator connect(basic_socket<Protocol, Executor>& s,
Iterator begin, Iterator end)
{
boost::system::error_code ec;
@@ -156,17 +155,16 @@ Iterator connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s,
return result;
}
-template <typename Protocol BOOST_ASIO_SVC_TPARAM, typename Iterator>
-inline Iterator connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s,
+template <typename Protocol, typename Executor, typename Iterator>
+inline Iterator connect(basic_socket<Protocol, Executor>& s,
Iterator begin, Iterator end, boost::system::error_code& ec)
{
return connect(s, begin, end, detail::default_connect_condition(), ec);
}
-template <typename Protocol BOOST_ASIO_SVC_TPARAM,
+template <typename Protocol, typename Executor,
typename EndpointSequence, typename ConnectCondition>
-typename Protocol::endpoint connect(
- basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s,
+typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s,
const EndpointSequence& endpoints, ConnectCondition connect_condition,
typename enable_if<is_endpoint_sequence<
EndpointSequence>::value>::type*)
@@ -178,10 +176,9 @@ typename Protocol::endpoint connect(
return result;
}
-template <typename Protocol BOOST_ASIO_SVC_TPARAM,
+template <typename Protocol, typename Executor,
typename EndpointSequence, typename ConnectCondition>
-typename Protocol::endpoint connect(
- basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s,
+typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s,
const EndpointSequence& endpoints, ConnectCondition connect_condition,
boost::system::error_code& ec,
typename enable_if<is_endpoint_sequence<
@@ -193,9 +190,9 @@ typename Protocol::endpoint connect(
}
#if !defined(BOOST_ASIO_NO_DEPRECATED)
-template <typename Protocol BOOST_ASIO_SVC_TPARAM,
+template <typename Protocol, typename Executor,
typename Iterator, typename ConnectCondition>
-Iterator connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s,
+Iterator connect(basic_socket<Protocol, Executor>& s,
Iterator begin, ConnectCondition connect_condition,
typename enable_if<!is_endpoint_sequence<Iterator>::value>::type*)
{
@@ -205,9 +202,9 @@ Iterator connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s,
return result;
}
-template <typename Protocol BOOST_ASIO_SVC_TPARAM,
+template <typename Protocol, typename Executor,
typename Iterator, typename ConnectCondition>
-inline Iterator connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s,
+inline Iterator connect(basic_socket<Protocol, Executor>& s,
Iterator begin, ConnectCondition connect_condition,
boost::system::error_code& ec,
typename enable_if<!is_endpoint_sequence<Iterator>::value>::type*)
@@ -216,10 +213,10 @@ inline Iterator connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s,
}
#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
-template <typename Protocol BOOST_ASIO_SVC_TPARAM,
+template <typename Protocol, typename Executor,
typename Iterator, typename ConnectCondition>
-Iterator connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s,
- Iterator begin, Iterator end, ConnectCondition connect_condition)
+Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin,
+ Iterator end, ConnectCondition connect_condition)
{
boost::system::error_code ec;
Iterator result = connect(s, begin, end, connect_condition, ec);
@@ -227,10 +224,10 @@ Iterator connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s,
return result;
}
-template <typename Protocol BOOST_ASIO_SVC_TPARAM,
+template <typename Protocol, typename Executor,
typename Iterator, typename ConnectCondition>
-Iterator connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s,
- Iterator begin, Iterator end, ConnectCondition connect_condition,
+Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin,
+ Iterator end, ConnectCondition connect_condition,
boost::system::error_code& ec)
{
ec = boost::system::error_code();
@@ -295,13 +292,12 @@ namespace detail
}
};
- template <typename Protocol BOOST_ASIO_SVC_TPARAM,
- typename EndpointSequence, typename ConnectCondition,
- typename RangeConnectHandler>
+ template <typename Protocol, typename Executor, typename EndpointSequence,
+ typename ConnectCondition, typename RangeConnectHandler>
class range_connect_op : base_from_connect_condition<ConnectCondition>
{
public:
- range_connect_op(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& sock,
+ range_connect_op(basic_socket<Protocol, Executor>& sock,
const EndpointSequence& endpoints,
const ConnectCondition& connect_condition,
RangeConnectHandler& handler)
@@ -338,10 +334,18 @@ namespace detail
void operator()(boost::system::error_code ec, int start = 0)
{
- typename EndpointSequence::const_iterator begin = endpoints_.begin();
- typename EndpointSequence::const_iterator iter = begin;
+ this->process(ec, start,
+ const_cast<const EndpointSequence&>(endpoints_).begin(),
+ const_cast<const EndpointSequence&>(endpoints_).end());
+ }
+
+ //private:
+ template <typename Iterator>
+ void process(boost::system::error_code ec,
+ int start, Iterator begin, Iterator end)
+ {
+ Iterator iter = begin;
std::advance(iter, index_);
- typename EndpointSequence::const_iterator end = endpoints_.end();
switch (start_ = start)
{
@@ -392,75 +396,92 @@ namespace detail
}
}
- //private:
- basic_socket<Protocol BOOST_ASIO_SVC_TARG>& socket_;
+ basic_socket<Protocol, Executor>& socket_;
EndpointSequence endpoints_;
std::size_t index_;
int start_;
RangeConnectHandler handler_;
};
- template <typename Protocol BOOST_ASIO_SVC_TPARAM,
- typename EndpointSequence, typename ConnectCondition,
- typename RangeConnectHandler>
+ template <typename Protocol, typename Executor, typename EndpointSequence,
+ typename ConnectCondition, typename RangeConnectHandler>
inline void* asio_handler_allocate(std::size_t size,
- range_connect_op<Protocol BOOST_ASIO_SVC_TARG, EndpointSequence,
+ range_connect_op<Protocol, Executor, EndpointSequence,
ConnectCondition, RangeConnectHandler>* this_handler)
{
return boost_asio_handler_alloc_helpers::allocate(
size, this_handler->handler_);
}
- template <typename Protocol BOOST_ASIO_SVC_TPARAM,
- typename EndpointSequence, typename ConnectCondition,
- typename RangeConnectHandler>
+ template <typename Protocol, typename Executor, typename EndpointSequence,
+ typename ConnectCondition, typename RangeConnectHandler>
inline void asio_handler_deallocate(void* pointer, std::size_t size,
- range_connect_op<Protocol BOOST_ASIO_SVC_TARG, EndpointSequence,
+ range_connect_op<Protocol, Executor, EndpointSequence,
ConnectCondition, RangeConnectHandler>* this_handler)
{
boost_asio_handler_alloc_helpers::deallocate(
pointer, size, this_handler->handler_);
}
- template <typename Protocol BOOST_ASIO_SVC_TPARAM,
- typename EndpointSequence, typename ConnectCondition,
- typename RangeConnectHandler>
+ template <typename Protocol, typename Executor, typename EndpointSequence,
+ typename ConnectCondition, typename RangeConnectHandler>
inline bool asio_handler_is_continuation(
- range_connect_op<Protocol BOOST_ASIO_SVC_TARG, EndpointSequence,
+ range_connect_op<Protocol, Executor, EndpointSequence,
ConnectCondition, RangeConnectHandler>* this_handler)
{
return boost_asio_handler_cont_helpers::is_continuation(
this_handler->handler_);
}
- template <typename Function, typename Protocol
- BOOST_ASIO_SVC_TPARAM, typename EndpointSequence,
- typename ConnectCondition, typename RangeConnectHandler>
+ template <typename Function, typename Executor, typename Protocol,
+ typename EndpointSequence, typename ConnectCondition,
+ typename RangeConnectHandler>
inline void asio_handler_invoke(Function& function,
- range_connect_op<Protocol BOOST_ASIO_SVC_TARG, EndpointSequence,
+ range_connect_op<Protocol, Executor, EndpointSequence,
ConnectCondition, RangeConnectHandler>* this_handler)
{
boost_asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
}
- template <typename Function, typename Protocol
- BOOST_ASIO_SVC_TPARAM, typename EndpointSequence,
- typename ConnectCondition, typename RangeConnectHandler>
+ template <typename Function, typename Executor, typename Protocol,
+ typename EndpointSequence, typename ConnectCondition,
+ typename RangeConnectHandler>
inline void asio_handler_invoke(const Function& function,
- range_connect_op<Protocol BOOST_ASIO_SVC_TARG, EndpointSequence,
+ range_connect_op<Protocol, Executor, EndpointSequence,
ConnectCondition, RangeConnectHandler>* this_handler)
{
boost_asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
}
- template <typename Protocol BOOST_ASIO_SVC_TPARAM, typename Iterator,
+ struct initiate_async_range_connect
+ {
+ template <typename RangeConnectHandler, typename Protocol,
+ typename Executor, typename EndpointSequence, typename ConnectCondition>
+ void operator()(BOOST_ASIO_MOVE_ARG(RangeConnectHandler) handler,
+ basic_socket<Protocol, Executor>* s, const EndpointSequence& endpoints,
+ const ConnectCondition& connect_condition) const
+ {
+ // If you get an error on the following line it means that your
+ // handler does not meet the documented type requirements for an
+ // RangeConnectHandler.
+ BOOST_ASIO_RANGE_CONNECT_HANDLER_CHECK(RangeConnectHandler,
+ handler, typename Protocol::endpoint) type_check;
+
+ non_const_lvalue<RangeConnectHandler> handler2(handler);
+ range_connect_op<Protocol, Executor, EndpointSequence, ConnectCondition,
+ typename decay<RangeConnectHandler>::type>(*s, endpoints,
+ connect_condition, handler2.value)(boost::system::error_code(), 1);
+ }
+ };
+
+ template <typename Protocol, typename Executor, typename Iterator,
typename ConnectCondition, typename IteratorConnectHandler>
class iterator_connect_op : base_from_connect_condition<ConnectCondition>
{
public:
- iterator_connect_op(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& sock,
+ iterator_connect_op(basic_socket<Protocol, Executor>& sock,
const Iterator& begin, const Iterator& end,
const ConnectCondition& connect_condition,
IteratorConnectHandler& handler)
@@ -544,82 +565,101 @@ namespace detail
}
//private:
- basic_socket<Protocol BOOST_ASIO_SVC_TARG>& socket_;
+ basic_socket<Protocol, Executor>& socket_;
Iterator iter_;
Iterator end_;
int start_;
IteratorConnectHandler handler_;
};
- template <typename Protocol BOOST_ASIO_SVC_TPARAM, typename Iterator,
+ template <typename Protocol, typename Executor, typename Iterator,
typename ConnectCondition, typename IteratorConnectHandler>
inline void* asio_handler_allocate(std::size_t size,
- iterator_connect_op<Protocol BOOST_ASIO_SVC_TARG, Iterator,
+ iterator_connect_op<Protocol, Executor, Iterator,
ConnectCondition, IteratorConnectHandler>* this_handler)
{
return boost_asio_handler_alloc_helpers::allocate(
size, this_handler->handler_);
}
- template <typename Protocol BOOST_ASIO_SVC_TPARAM, typename Iterator,
+ template <typename Protocol, typename Executor, typename Iterator,
typename ConnectCondition, typename IteratorConnectHandler>
inline void asio_handler_deallocate(void* pointer, std::size_t size,
- iterator_connect_op<Protocol BOOST_ASIO_SVC_TARG, Iterator,
+ iterator_connect_op<Protocol, Executor, Iterator,
ConnectCondition, IteratorConnectHandler>* this_handler)
{
boost_asio_handler_alloc_helpers::deallocate(
pointer, size, this_handler->handler_);
}
- template <typename Protocol BOOST_ASIO_SVC_TPARAM, typename Iterator,
+ template <typename Protocol, typename Executor, typename Iterator,
typename ConnectCondition, typename IteratorConnectHandler>
inline bool asio_handler_is_continuation(
- iterator_connect_op<Protocol BOOST_ASIO_SVC_TARG, Iterator,
+ iterator_connect_op<Protocol, Executor, Iterator,
ConnectCondition, IteratorConnectHandler>* this_handler)
{
return boost_asio_handler_cont_helpers::is_continuation(
this_handler->handler_);
}
- template <typename Function, typename Protocol
- BOOST_ASIO_SVC_TPARAM, typename Iterator,
- typename ConnectCondition, typename IteratorConnectHandler>
+ template <typename Function, typename Executor, typename Protocol,
+ typename Iterator, typename ConnectCondition,
+ typename IteratorConnectHandler>
inline void asio_handler_invoke(Function& function,
- iterator_connect_op<Protocol BOOST_ASIO_SVC_TARG, Iterator,
+ iterator_connect_op<Protocol, Executor, Iterator,
ConnectCondition, IteratorConnectHandler>* this_handler)
{
boost_asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
}
- template <typename Function, typename Protocol
- BOOST_ASIO_SVC_TPARAM, typename Iterator,
- typename ConnectCondition, typename IteratorConnectHandler>
+ template <typename Function, typename Executor, typename Protocol,
+ typename Iterator, typename ConnectCondition,
+ typename IteratorConnectHandler>
inline void asio_handler_invoke(const Function& function,
- iterator_connect_op<Protocol BOOST_ASIO_SVC_TARG, Iterator,
+ iterator_connect_op<Protocol, Executor, Iterator,
ConnectCondition, IteratorConnectHandler>* this_handler)
{
boost_asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
}
+
+ struct initiate_async_iterator_connect
+ {
+ template <typename IteratorConnectHandler, typename Protocol,
+ typename Executor, typename Iterator, typename ConnectCondition>
+ void operator()(BOOST_ASIO_MOVE_ARG(IteratorConnectHandler) handler,
+ basic_socket<Protocol, Executor>* s, Iterator begin,
+ Iterator end, const ConnectCondition& connect_condition) const
+ {
+ // If you get an error on the following line it means that your
+ // handler does not meet the documented type requirements for an
+ // IteratorConnectHandler.
+ BOOST_ASIO_ITERATOR_CONNECT_HANDLER_CHECK(
+ IteratorConnectHandler, handler, Iterator) type_check;
+
+ non_const_lvalue<IteratorConnectHandler> handler2(handler);
+ iterator_connect_op<Protocol, Executor, Iterator, ConnectCondition,
+ typename decay<IteratorConnectHandler>::type>(*s, begin, end,
+ connect_condition, handler2.value)(boost::system::error_code(), 1);
+ }
+ };
} // namespace detail
#if !defined(GENERATING_DOCUMENTATION)
-template <typename Protocol BOOST_ASIO_SVC_TPARAM,
- typename EndpointSequence, typename ConnectCondition,
- typename RangeConnectHandler, typename Allocator>
+template <typename Protocol, typename Executor, typename EndpointSequence,
+ typename ConnectCondition, typename RangeConnectHandler, typename Allocator>
struct associated_allocator<
- detail::range_connect_op<Protocol BOOST_ASIO_SVC_TARG,
- EndpointSequence, ConnectCondition, RangeConnectHandler>,
- Allocator>
+ detail::range_connect_op<Protocol, Executor, EndpointSequence,
+ ConnectCondition, RangeConnectHandler>, Allocator>
{
typedef typename associated_allocator<
RangeConnectHandler, Allocator>::type type;
static type get(
- const detail::range_connect_op<Protocol BOOST_ASIO_SVC_TARG,
- EndpointSequence, ConnectCondition, RangeConnectHandler>& h,
+ const detail::range_connect_op<Protocol, Executor, EndpointSequence,
+ ConnectCondition, RangeConnectHandler>& h,
const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
{
return associated_allocator<RangeConnectHandler,
@@ -627,40 +667,38 @@ struct associated_allocator<
}
};
-template <typename Protocol BOOST_ASIO_SVC_TPARAM,
- typename EndpointSequence, typename ConnectCondition,
- typename RangeConnectHandler, typename Executor>
+template <typename Protocol, typename Executor, typename EndpointSequence,
+ typename ConnectCondition, typename RangeConnectHandler, typename Executor1>
struct associated_executor<
- detail::range_connect_op<Protocol BOOST_ASIO_SVC_TARG,
- EndpointSequence, ConnectCondition, RangeConnectHandler>,
- Executor>
+ detail::range_connect_op<Protocol, Executor, EndpointSequence,
+ ConnectCondition, RangeConnectHandler>, Executor1>
{
typedef typename associated_executor<
- RangeConnectHandler, Executor>::type type;
+ RangeConnectHandler, Executor1>::type type;
static type get(
- const detail::range_connect_op<Protocol BOOST_ASIO_SVC_TARG,
- EndpointSequence, ConnectCondition, RangeConnectHandler>& h,
- const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
+ const detail::range_connect_op<Protocol, Executor, EndpointSequence,
+ ConnectCondition, RangeConnectHandler>& h,
+ const Executor1& ex = Executor1()) BOOST_ASIO_NOEXCEPT
{
return associated_executor<RangeConnectHandler,
- Executor>::get(h.handler_, ex);
+ Executor1>::get(h.handler_, ex);
}
};
-template <typename Protocol BOOST_ASIO_SVC_TPARAM,
- typename Iterator, typename ConnectCondition,
- typename IteratorConnectHandler, typename Allocator>
+template <typename Protocol, typename Executor, typename Iterator,
+ typename ConnectCondition, typename IteratorConnectHandler,
+ typename Allocator>
struct associated_allocator<
- detail::iterator_connect_op<Protocol BOOST_ASIO_SVC_TARG, Iterator,
- ConnectCondition, IteratorConnectHandler>,
+ detail::iterator_connect_op<Protocol, Executor,
+ Iterator, ConnectCondition, IteratorConnectHandler>,
Allocator>
{
typedef typename associated_allocator<
IteratorConnectHandler, Allocator>::type type;
static type get(
- const detail::iterator_connect_op<Protocol BOOST_ASIO_SVC_TARG,
+ const detail::iterator_connect_op<Protocol, Executor,
Iterator, ConnectCondition, IteratorConnectHandler>& h,
const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
{
@@ -669,189 +707,119 @@ struct associated_allocator<
}
};
-template <typename Protocol BOOST_ASIO_SVC_TPARAM,
- typename Iterator, typename ConnectCondition,
- typename IteratorConnectHandler, typename Executor>
+template <typename Protocol, typename Executor, typename Iterator,
+ typename ConnectCondition, typename IteratorConnectHandler,
+ typename Executor1>
struct associated_executor<
- detail::iterator_connect_op<Protocol BOOST_ASIO_SVC_TARG, Iterator,
- ConnectCondition, IteratorConnectHandler>,
- Executor>
+ detail::iterator_connect_op<Protocol, Executor,
+ Iterator, ConnectCondition, IteratorConnectHandler>,
+ Executor1>
{
typedef typename associated_executor<
- IteratorConnectHandler, Executor>::type type;
+ IteratorConnectHandler, Executor1>::type type;
static type get(
- const detail::iterator_connect_op<Protocol BOOST_ASIO_SVC_TARG,
+ const detail::iterator_connect_op<Protocol, Executor,
Iterator, ConnectCondition, IteratorConnectHandler>& h,
- const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
+ const Executor1& ex = Executor1()) BOOST_ASIO_NOEXCEPT
{
return associated_executor<IteratorConnectHandler,
- Executor>::get(h.handler_, ex);
+ Executor1>::get(h.handler_, ex);
}
};
#endif // !defined(GENERATING_DOCUMENTATION)
-template <typename Protocol BOOST_ASIO_SVC_TPARAM,
+template <typename Protocol, typename Executor,
typename EndpointSequence, typename RangeConnectHandler>
inline BOOST_ASIO_INITFN_RESULT_TYPE(RangeConnectHandler,
void (boost::system::error_code, typename Protocol::endpoint))
-async_connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s,
+async_connect(basic_socket<Protocol, Executor>& s,
const EndpointSequence& endpoints,
BOOST_ASIO_MOVE_ARG(RangeConnectHandler) handler,
typename enable_if<is_endpoint_sequence<
EndpointSequence>::value>::type*)
{
- // If you get an error on the following line it means that your handler does
- // not meet the documented type requirements for a RangeConnectHandler.
- BOOST_ASIO_RANGE_CONNECT_HANDLER_CHECK(
- RangeConnectHandler, handler, typename Protocol::endpoint) type_check;
-
- async_completion<RangeConnectHandler,
- void (boost::system::error_code, typename Protocol::endpoint)>
- init(handler);
-
- detail::range_connect_op<Protocol BOOST_ASIO_SVC_TARG, EndpointSequence,
- detail::default_connect_condition,
- BOOST_ASIO_HANDLER_TYPE(RangeConnectHandler,
- void (boost::system::error_code, typename Protocol::endpoint))>(s,
- endpoints, detail::default_connect_condition(),
- init.completion_handler)(boost::system::error_code(), 1);
-
- return init.result.get();
+ return async_initiate<RangeConnectHandler,
+ void (boost::system::error_code, typename Protocol::endpoint)>(
+ detail::initiate_async_range_connect(), handler,
+ &s, endpoints, detail::default_connect_condition());
}
#if !defined(BOOST_ASIO_NO_DEPRECATED)
-template <typename Protocol BOOST_ASIO_SVC_TPARAM,
+template <typename Protocol, typename Executor,
typename Iterator, typename IteratorConnectHandler>
inline BOOST_ASIO_INITFN_RESULT_TYPE(IteratorConnectHandler,
void (boost::system::error_code, Iterator))
-async_connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s,
- Iterator begin, BOOST_ASIO_MOVE_ARG(IteratorConnectHandler) handler,
+async_connect(basic_socket<Protocol, Executor>& s, Iterator begin,
+ BOOST_ASIO_MOVE_ARG(IteratorConnectHandler) handler,
typename enable_if<!is_endpoint_sequence<Iterator>::value>::type*)
{
- // If you get an error on the following line it means that your handler does
- // not meet the documented type requirements for a IteratorConnectHandler.
- BOOST_ASIO_ITERATOR_CONNECT_HANDLER_CHECK(
- IteratorConnectHandler, handler, Iterator) type_check;
-
- async_completion<IteratorConnectHandler,
- void (boost::system::error_code, Iterator)> init(handler);
-
- detail::iterator_connect_op<Protocol BOOST_ASIO_SVC_TARG, Iterator,
- detail::default_connect_condition, BOOST_ASIO_HANDLER_TYPE(
- IteratorConnectHandler, void (boost::system::error_code, Iterator))>(s,
- begin, Iterator(), detail::default_connect_condition(),
- init.completion_handler)(boost::system::error_code(), 1);
-
- return init.result.get();
+ return async_initiate<IteratorConnectHandler,
+ void (boost::system::error_code, Iterator)>(
+ detail::initiate_async_iterator_connect(), handler,
+ &s, begin, Iterator(), detail::default_connect_condition());
}
#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
-template <typename Protocol BOOST_ASIO_SVC_TPARAM,
+template <typename Protocol, typename Executor,
typename Iterator, typename IteratorConnectHandler>
inline BOOST_ASIO_INITFN_RESULT_TYPE(IteratorConnectHandler,
void (boost::system::error_code, Iterator))
-async_connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s,
- Iterator begin, Iterator end,
+async_connect(basic_socket<Protocol, Executor>& s, Iterator begin, Iterator end,
BOOST_ASIO_MOVE_ARG(IteratorConnectHandler) handler)
{
- // If you get an error on the following line it means that your handler does
- // not meet the documented type requirements for a IteratorConnectHandler.
- BOOST_ASIO_ITERATOR_CONNECT_HANDLER_CHECK(
- IteratorConnectHandler, handler, Iterator) type_check;
-
- async_completion<IteratorConnectHandler,
- void (boost::system::error_code, Iterator)> init(handler);
-
- detail::iterator_connect_op<Protocol BOOST_ASIO_SVC_TARG, Iterator,
- detail::default_connect_condition, BOOST_ASIO_HANDLER_TYPE(
- IteratorConnectHandler, void (boost::system::error_code, Iterator))>(s,
- begin, end, detail::default_connect_condition(),
- init.completion_handler)(boost::system::error_code(), 1);
-
- return init.result.get();
+ return async_initiate<IteratorConnectHandler,
+ void (boost::system::error_code, Iterator)>(
+ detail::initiate_async_iterator_connect(), handler,
+ &s, begin, end, detail::default_connect_condition());
}
-template <typename Protocol BOOST_ASIO_SVC_TPARAM, typename EndpointSequence,
+template <typename Protocol, typename Executor, typename EndpointSequence,
typename ConnectCondition, typename RangeConnectHandler>
inline BOOST_ASIO_INITFN_RESULT_TYPE(RangeConnectHandler,
void (boost::system::error_code, typename Protocol::endpoint))
-async_connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s,
+async_connect(basic_socket<Protocol, Executor>& s,
const EndpointSequence& endpoints, ConnectCondition connect_condition,
BOOST_ASIO_MOVE_ARG(RangeConnectHandler) handler,
typename enable_if<is_endpoint_sequence<
EndpointSequence>::value>::type*)
{
- // If you get an error on the following line it means that your handler does
- // not meet the documented type requirements for a RangeConnectHandler.
- BOOST_ASIO_RANGE_CONNECT_HANDLER_CHECK(
- RangeConnectHandler, handler, typename Protocol::endpoint) type_check;
-
- async_completion<RangeConnectHandler,
- void (boost::system::error_code, typename Protocol::endpoint)>
- init(handler);
-
- detail::range_connect_op<Protocol BOOST_ASIO_SVC_TARG, EndpointSequence,
- ConnectCondition, BOOST_ASIO_HANDLER_TYPE(RangeConnectHandler,
- void (boost::system::error_code, typename Protocol::endpoint))>(s,
- endpoints, connect_condition, init.completion_handler)(
- boost::system::error_code(), 1);
-
- return init.result.get();
+ return async_initiate<RangeConnectHandler,
+ void (boost::system::error_code, typename Protocol::endpoint)>(
+ detail::initiate_async_range_connect(),
+ handler, &s, endpoints, connect_condition);
}
#if !defined(BOOST_ASIO_NO_DEPRECATED)
-template <typename Protocol BOOST_ASIO_SVC_TPARAM, typename Iterator,
+template <typename Protocol, typename Executor, typename Iterator,
typename ConnectCondition, typename IteratorConnectHandler>
inline BOOST_ASIO_INITFN_RESULT_TYPE(IteratorConnectHandler,
void (boost::system::error_code, Iterator))
-async_connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s,
- Iterator begin, ConnectCondition connect_condition,
+async_connect(basic_socket<Protocol, Executor>& s, Iterator begin,
+ ConnectCondition connect_condition,
BOOST_ASIO_MOVE_ARG(IteratorConnectHandler) handler,
typename enable_if<!is_endpoint_sequence<Iterator>::value>::type*)
{
- // If you get an error on the following line it means that your handler does
- // not meet the documented type requirements for a IteratorConnectHandler.
- BOOST_ASIO_ITERATOR_CONNECT_HANDLER_CHECK(
- IteratorConnectHandler, handler, Iterator) type_check;
-
- async_completion<IteratorConnectHandler,
- void (boost::system::error_code, Iterator)> init(handler);
-
- detail::iterator_connect_op<Protocol BOOST_ASIO_SVC_TARG, Iterator,
- ConnectCondition, BOOST_ASIO_HANDLER_TYPE(
- IteratorConnectHandler, void (boost::system::error_code, Iterator))>(s,
- begin, Iterator(), connect_condition, init.completion_handler)(
- boost::system::error_code(), 1);
-
- return init.result.get();
+ return async_initiate<IteratorConnectHandler,
+ void (boost::system::error_code, Iterator)>(
+ detail::initiate_async_iterator_connect(),
+ handler, &s, begin, Iterator(), connect_condition);
}
#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
-template <typename Protocol BOOST_ASIO_SVC_TPARAM, typename Iterator,
+template <typename Protocol, typename Executor, typename Iterator,
typename ConnectCondition, typename IteratorConnectHandler>
inline BOOST_ASIO_INITFN_RESULT_TYPE(IteratorConnectHandler,
void (boost::system::error_code, Iterator))
-async_connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s,
- Iterator begin, Iterator end, ConnectCondition connect_condition,
+async_connect(basic_socket<Protocol, Executor>& s, Iterator begin,
+ Iterator end, ConnectCondition connect_condition,
BOOST_ASIO_MOVE_ARG(IteratorConnectHandler) handler)
{
- // If you get an error on the following line it means that your handler does
- // not meet the documented type requirements for a IteratorConnectHandler.
- BOOST_ASIO_ITERATOR_CONNECT_HANDLER_CHECK(
- IteratorConnectHandler, handler, Iterator) type_check;
-
- async_completion<IteratorConnectHandler,
- void (boost::system::error_code, Iterator)> init(handler);
-
- detail::iterator_connect_op<Protocol BOOST_ASIO_SVC_TARG, Iterator,
- ConnectCondition, BOOST_ASIO_HANDLER_TYPE(
- IteratorConnectHandler, void (boost::system::error_code, Iterator))>(s,
- begin, end, connect_condition, init.completion_handler)(
- boost::system::error_code(), 1);
-
- return init.result.get();
+ return async_initiate<IteratorConnectHandler,
+ void (boost::system::error_code, Iterator)>(
+ detail::initiate_async_iterator_connect(),
+ handler, &s, begin, end, connect_condition);
}
} // namespace asio
diff --git a/boost/asio/impl/defer.hpp b/boost/asio/impl/defer.hpp
index 7cc86da45c..856a33c788 100644
--- a/boost/asio/impl/defer.hpp
+++ b/boost/asio/impl/defer.hpp
@@ -2,7 +2,7 @@
// impl/defer.hpp
// ~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -24,24 +24,46 @@
namespace boost {
namespace asio {
+namespace detail {
-template <typename CompletionToken>
-BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void()) defer(
- BOOST_ASIO_MOVE_ARG(CompletionToken) token)
+struct initiate_defer
{
- typedef BOOST_ASIO_HANDLER_TYPE(CompletionToken, void()) handler;
+ template <typename CompletionHandler>
+ void operator()(BOOST_ASIO_MOVE_ARG(CompletionHandler) handler) const
+ {
+ typedef typename decay<CompletionHandler>::type DecayedHandler;
+
+ typename associated_executor<DecayedHandler>::type ex(
+ (get_associated_executor)(handler));
- async_completion<CompletionToken, void()> init(token);
+ typename associated_allocator<DecayedHandler>::type alloc(
+ (get_associated_allocator)(handler));
- typename associated_executor<handler>::type ex(
- (get_associated_executor)(init.completion_handler));
+ ex.defer(BOOST_ASIO_MOVE_CAST(CompletionHandler)(handler), alloc);
+ }
- typename associated_allocator<handler>::type alloc(
- (get_associated_allocator)(init.completion_handler));
+ template <typename CompletionHandler, typename Executor>
+ void operator()(BOOST_ASIO_MOVE_ARG(CompletionHandler) handler,
+ BOOST_ASIO_MOVE_ARG(Executor) ex) const
+ {
+ typedef typename decay<CompletionHandler>::type DecayedHandler;
- ex.defer(BOOST_ASIO_MOVE_CAST(handler)(init.completion_handler), alloc);
+ typename associated_allocator<DecayedHandler>::type alloc(
+ (get_associated_allocator)(handler));
- return init.result.get();
+ ex.defer(detail::work_dispatcher<DecayedHandler>(
+ BOOST_ASIO_MOVE_CAST(CompletionHandler)(handler)), alloc);
+ }
+};
+
+} // namespace detail
+
+template <typename CompletionToken>
+BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void()) defer(
+ BOOST_ASIO_MOVE_ARG(CompletionToken) token)
+{
+ return async_initiate<CompletionToken, void()>(
+ detail::initiate_defer(), token);
}
template <typename Executor, typename CompletionToken>
@@ -49,16 +71,8 @@ BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void()) defer(
const Executor& ex, BOOST_ASIO_MOVE_ARG(CompletionToken) token,
typename enable_if<is_executor<Executor>::value>::type*)
{
- typedef BOOST_ASIO_HANDLER_TYPE(CompletionToken, void()) handler;
-
- async_completion<CompletionToken, void()> init(token);
-
- typename associated_allocator<handler>::type alloc(
- (get_associated_allocator)(init.completion_handler));
-
- ex.defer(detail::work_dispatcher<handler>(init.completion_handler), alloc);
-
- return init.result.get();
+ return async_initiate<CompletionToken, void()>(
+ detail::initiate_defer(), token, ex);
}
template <typename ExecutionContext, typename CompletionToken>
diff --git a/boost/asio/impl/detached.hpp b/boost/asio/impl/detached.hpp
new file mode 100644
index 0000000000..ae2c882fba
--- /dev/null
+++ b/boost/asio/impl/detached.hpp
@@ -0,0 +1,132 @@
+//
+// impl/detached.hpp
+// ~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_IMPL_DETACHED_HPP
+#define BOOST_ASIO_IMPL_DETACHED_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <boost/asio/async_result.hpp>
+#include <boost/asio/detail/variadic_templates.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+ // Class to adapt a detached_t as a completion handler.
+ class detached_handler
+ {
+ public:
+ typedef void result_type;
+
+ detached_handler(detached_t)
+ {
+ }
+
+#if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
+
+ template <typename... Args>
+ void operator()(Args...)
+ {
+ }
+
+#else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
+
+ void operator()()
+ {
+ }
+
+#define BOOST_ASIO_PRIVATE_DETACHED_DEF(n) \
+ template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \
+ void operator()(BOOST_ASIO_VARIADIC_TARGS(n)) \
+ { \
+ } \
+ /**/
+ BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_DETACHED_DEF)
+#undef BOOST_ASIO_PRIVATE_DETACHED_DEF
+
+#endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
+ };
+
+} // namespace detail
+
+#if !defined(GENERATING_DOCUMENTATION)
+
+template <typename Signature>
+struct async_result<detached_t, Signature>
+{
+ typedef boost::asio::detail::detached_handler completion_handler_type;
+
+ typedef void return_type;
+
+ explicit async_result(completion_handler_type&)
+ {
+ }
+
+ void get()
+ {
+ }
+
+#if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
+
+ template <typename Initiation, typename RawCompletionToken, typename... Args>
+ static return_type initiate(
+ BOOST_ASIO_MOVE_ARG(Initiation) initiation,
+ BOOST_ASIO_MOVE_ARG(RawCompletionToken),
+ BOOST_ASIO_MOVE_ARG(Args)... args)
+ {
+ BOOST_ASIO_MOVE_CAST(Initiation)(initiation)(
+ detail::detached_handler(detached_t()),
+ BOOST_ASIO_MOVE_CAST(Args)(args)...);
+ }
+
+#else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
+
+ template <typename Initiation, typename RawCompletionToken>
+ static return_type initiate(
+ BOOST_ASIO_MOVE_ARG(Initiation) initiation,
+ BOOST_ASIO_MOVE_ARG(RawCompletionToken))
+ {
+ BOOST_ASIO_MOVE_CAST(Initiation)(initiation)(
+ detail::detached_handler(detached_t()));
+ }
+
+#define BOOST_ASIO_PRIVATE_INITIATE_DEF(n) \
+ template <typename Initiation, typename RawCompletionToken, \
+ BOOST_ASIO_VARIADIC_TPARAMS(n)> \
+ static return_type initiate( \
+ BOOST_ASIO_MOVE_ARG(Initiation) initiation, \
+ BOOST_ASIO_MOVE_ARG(RawCompletionToken), \
+ BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
+ { \
+ BOOST_ASIO_MOVE_CAST(Initiation)(initiation)( \
+ detail::detached_handler(detached_t()), \
+ BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \
+ } \
+ /**/
+ BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_INITIATE_DEF)
+#undef BOOST_ASIO_PRIVATE_INITIATE_DEF
+
+#endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
+};
+
+#endif // !defined(GENERATING_DOCUMENTATION)
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_IMPL_DETACHED_HPP
diff --git a/boost/asio/impl/dispatch.hpp b/boost/asio/impl/dispatch.hpp
index 8bdce85180..bcba2ee401 100644
--- a/boost/asio/impl/dispatch.hpp
+++ b/boost/asio/impl/dispatch.hpp
@@ -2,7 +2,7 @@
// impl/dispatch.hpp
// ~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -24,24 +24,46 @@
namespace boost {
namespace asio {
+namespace detail {
-template <typename CompletionToken>
-BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void()) dispatch(
- BOOST_ASIO_MOVE_ARG(CompletionToken) token)
+struct initiate_dispatch
{
- typedef BOOST_ASIO_HANDLER_TYPE(CompletionToken, void()) handler;
+ template <typename CompletionHandler>
+ void operator()(BOOST_ASIO_MOVE_ARG(CompletionHandler) handler) const
+ {
+ typedef typename decay<CompletionHandler>::type DecayedHandler;
+
+ typename associated_executor<DecayedHandler>::type ex(
+ (get_associated_executor)(handler));
- async_completion<CompletionToken, void()> init(token);
+ typename associated_allocator<DecayedHandler>::type alloc(
+ (get_associated_allocator)(handler));
- typename associated_executor<handler>::type ex(
- (get_associated_executor)(init.completion_handler));
+ ex.dispatch(BOOST_ASIO_MOVE_CAST(CompletionHandler)(handler), alloc);
+ }
- typename associated_allocator<handler>::type alloc(
- (get_associated_allocator)(init.completion_handler));
+ template <typename CompletionHandler, typename Executor>
+ void operator()(BOOST_ASIO_MOVE_ARG(CompletionHandler) handler,
+ BOOST_ASIO_MOVE_ARG(Executor) ex) const
+ {
+ typedef typename decay<CompletionHandler>::type DecayedHandler;
- ex.dispatch(BOOST_ASIO_MOVE_CAST(handler)(init.completion_handler), alloc);
+ typename associated_allocator<DecayedHandler>::type alloc(
+ (get_associated_allocator)(handler));
- return init.result.get();
+ ex.dispatch(detail::work_dispatcher<DecayedHandler>(
+ BOOST_ASIO_MOVE_CAST(CompletionHandler)(handler)), alloc);
+ }
+};
+
+} // namespace detail
+
+template <typename CompletionToken>
+BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void()) dispatch(
+ BOOST_ASIO_MOVE_ARG(CompletionToken) token)
+{
+ return async_initiate<CompletionToken, void()>(
+ detail::initiate_dispatch(), token);
}
template <typename Executor, typename CompletionToken>
@@ -49,17 +71,8 @@ BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void()) dispatch(
const Executor& ex, BOOST_ASIO_MOVE_ARG(CompletionToken) token,
typename enable_if<is_executor<Executor>::value>::type*)
{
- typedef BOOST_ASIO_HANDLER_TYPE(CompletionToken, void()) handler;
-
- async_completion<CompletionToken, void()> init(token);
-
- typename associated_allocator<handler>::type alloc(
- (get_associated_allocator)(init.completion_handler));
-
- ex.dispatch(detail::work_dispatcher<handler>(
- init.completion_handler), alloc);
-
- return init.result.get();
+ return async_initiate<CompletionToken, void()>(
+ detail::initiate_dispatch(), token, ex);
}
template <typename ExecutionContext, typename CompletionToken>
diff --git a/boost/asio/impl/error.ipp b/boost/asio/impl/error.ipp
index 49a10462bd..0dcb1257c7 100644
--- a/boost/asio/impl/error.ipp
+++ b/boost/asio/impl/error.ipp
@@ -2,7 +2,7 @@
// impl/error.ipp
// ~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/impl/execution_context.hpp b/boost/asio/impl/execution_context.hpp
index eadf36b145..a1617f8c9c 100644
--- a/boost/asio/impl/execution_context.hpp
+++ b/boost/asio/impl/execution_context.hpp
@@ -2,7 +2,7 @@
// impl/execution_context.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -24,6 +24,8 @@
namespace boost {
namespace asio {
+#if !defined(GENERATING_DOCUMENTATION)
+
template <typename Service>
inline Service& use_service(execution_context& e)
{
@@ -33,8 +35,7 @@ inline Service& use_service(execution_context& e)
return e.service_registry_->template use_service<Service>();
}
-#if !defined(GENERATING_DOCUMENTATION)
-# if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
+#if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
template <typename Service, typename... Args>
Service& make_service(execution_context& e, BOOST_ASIO_MOVE_ARG(Args)... args)
@@ -47,7 +48,7 @@ Service& make_service(execution_context& e, BOOST_ASIO_MOVE_ARG(Args)... args)
return result;
}
-# else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
+#else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
template <typename Service>
Service& make_service(execution_context& e)
@@ -75,8 +76,7 @@ Service& make_service(execution_context& e)
BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_MAKE_SERVICE_DEF)
#undef BOOST_ASIO_PRIVATE_MAKE_SERVICE_DEF
-# endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
-#endif // !defined(GENERATING_DOCUMENTATION)
+#endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
template <typename Service>
inline void add_service(execution_context& e, Service* svc)
@@ -96,6 +96,8 @@ inline bool has_service(execution_context& e)
return e.service_registry_->template has_service<Service>();
}
+#endif // !defined(GENERATING_DOCUMENTATION)
+
inline execution_context& execution_context::service::context()
{
return owner_;
diff --git a/boost/asio/impl/execution_context.ipp b/boost/asio/impl/execution_context.ipp
index 219a66113d..30e7bb926f 100644
--- a/boost/asio/impl/execution_context.ipp
+++ b/boost/asio/impl/execution_context.ipp
@@ -2,7 +2,7 @@
// impl/execution_context.ipp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/impl/executor.hpp b/boost/asio/impl/executor.hpp
index 106763b042..b1c6cd748f 100644
--- a/boost/asio/impl/executor.hpp
+++ b/boost/asio/impl/executor.hpp
@@ -2,7 +2,7 @@
// impl/executor.hpp
// ~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -17,7 +17,7 @@
#include <boost/asio/detail/config.hpp>
#include <boost/asio/detail/atomic_count.hpp>
-#include <boost/asio/detail/executor_op.hpp>
+#include <boost/asio/detail/executor_function.hpp>
#include <boost/asio/detail/global.hpp>
#include <boost/asio/detail/memory.hpp>
#include <boost/asio/detail/recycling_allocator.hpp>
@@ -41,36 +41,37 @@ public:
explicit function(F f, const Alloc& a)
{
// Allocate and construct an operation to wrap the function.
- typedef detail::executor_op<F, Alloc> op;
- typename op::ptr p = { detail::addressof(a), op::ptr::allocate(a), 0 };
- op_ = new (p.v) op(BOOST_ASIO_MOVE_CAST(F)(f), a);
+ typedef detail::executor_function<F, Alloc> func_type;
+ typename func_type::ptr p = {
+ detail::addressof(a), func_type::ptr::allocate(a), 0 };
+ func_ = new (p.v) func_type(BOOST_ASIO_MOVE_CAST(F)(f), a);
p.v = 0;
}
- function(function&& other)
- : op_(other.op_)
+ function(function&& other) BOOST_ASIO_NOEXCEPT
+ : func_(other.func_)
{
- other.op_ = 0;
+ other.func_ = 0;
}
~function()
{
- if (op_)
- op_->destroy();
+ if (func_)
+ func_->destroy();
}
void operator()()
{
- if (op_)
+ if (func_)
{
- detail::scheduler_operation* op = op_;
- op_ = 0;
- op->complete(this, boost::system::error_code(), 0);
+ detail::executor_function_base* func = func_;
+ func_ = 0;
+ func->complete();
}
}
private:
- detail::scheduler_operation* op_;
+ detail::executor_function_base* func_;
};
#else // defined(BOOST_ASIO_HAS_MOVE)
diff --git a/boost/asio/impl/executor.ipp b/boost/asio/impl/executor.ipp
index 86114d93f1..289265d706 100644
--- a/boost/asio/impl/executor.ipp
+++ b/boost/asio/impl/executor.ipp
@@ -2,7 +2,7 @@
// impl/executor.ipp
// ~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/impl/handler_alloc_hook.ipp b/boost/asio/impl/handler_alloc_hook.ipp
index 2b04ec104e..a580f71ffa 100644
--- a/boost/asio/impl/handler_alloc_hook.ipp
+++ b/boost/asio/impl/handler_alloc_hook.ipp
@@ -2,7 +2,7 @@
// impl/handler_alloc_hook.ipp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/impl/io_context.hpp b/boost/asio/impl/io_context.hpp
index 37f8ace42a..2cf8c4bc8d 100644
--- a/boost/asio/impl/io_context.hpp
+++ b/boost/asio/impl/io_context.hpp
@@ -2,7 +2,7 @@
// impl/io_context.hpp
// ~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -19,6 +19,7 @@
#include <boost/asio/detail/executor_op.hpp>
#include <boost/asio/detail/fenced_block.hpp>
#include <boost/asio/detail/handler_type_requirements.hpp>
+#include <boost/asio/detail/non_const_lvalue.hpp>
#include <boost/asio/detail/recycling_allocator.hpp>
#include <boost/asio/detail/service_registry.hpp>
#include <boost/asio/detail/throw_error.hpp>
@@ -26,6 +27,8 @@
#include <boost/asio/detail/push_options.hpp>
+#if !defined(GENERATING_DOCUMENTATION)
+
namespace boost {
namespace asio {
@@ -49,6 +52,8 @@ inline detail::io_context_impl& use_service<detail::io_context_impl>(
} // namespace asio
} // namespace boost
+#endif // !defined(GENERATING_DOCUMENTATION)
+
#include <boost/asio/detail/pop_options.hpp>
#if defined(BOOST_ASIO_HAS_IOCP)
@@ -130,70 +135,87 @@ inline void io_context::reset()
restart();
}
+struct io_context::initiate_dispatch
+{
+ template <typename LegacyCompletionHandler>
+ void operator()(BOOST_ASIO_MOVE_ARG(LegacyCompletionHandler) handler,
+ io_context* self) const
+ {
+ // If you get an error on the following line it means that your handler does
+ // not meet the documented type requirements for a LegacyCompletionHandler.
+ BOOST_ASIO_LEGACY_COMPLETION_HANDLER_CHECK(
+ LegacyCompletionHandler, handler) type_check;
+
+ detail::non_const_lvalue<LegacyCompletionHandler> handler2(handler);
+ if (self->impl_.can_dispatch())
+ {
+ detail::fenced_block b(detail::fenced_block::full);
+ boost_asio_handler_invoke_helpers::invoke(
+ handler2.value, handler2.value);
+ }
+ else
+ {
+ // Allocate and construct an operation to wrap the handler.
+ typedef detail::completion_handler<
+ typename decay<LegacyCompletionHandler>::type> op;
+ typename op::ptr p = { detail::addressof(handler2.value),
+ op::ptr::allocate(handler2.value), 0 };
+ p.p = new (p.v) op(handler2.value);
+
+ BOOST_ASIO_HANDLER_CREATION((*self, *p.p,
+ "io_context", self, 0, "dispatch"));
+
+ self->impl_.do_dispatch(p.p);
+ p.v = p.p = 0;
+ }
+ }
+};
+
template <typename LegacyCompletionHandler>
BOOST_ASIO_INITFN_RESULT_TYPE(LegacyCompletionHandler, void ())
io_context::dispatch(BOOST_ASIO_MOVE_ARG(LegacyCompletionHandler) handler)
{
- // If you get an error on the following line it means that your handler does
- // not meet the documented type requirements for a LegacyCompletionHandler.
- BOOST_ASIO_LEGACY_COMPLETION_HANDLER_CHECK(
- LegacyCompletionHandler, handler) type_check;
-
- async_completion<LegacyCompletionHandler, void ()> init(handler);
+ return async_initiate<LegacyCompletionHandler, void ()>(
+ initiate_dispatch(), handler, this);
+}
- if (impl_.can_dispatch())
- {
- detail::fenced_block b(detail::fenced_block::full);
- boost_asio_handler_invoke_helpers::invoke(
- init.completion_handler, init.completion_handler);
- }
- else
+struct io_context::initiate_post
+{
+ template <typename LegacyCompletionHandler>
+ void operator()(BOOST_ASIO_MOVE_ARG(LegacyCompletionHandler) handler,
+ io_context* self) const
{
+ // If you get an error on the following line it means that your handler does
+ // not meet the documented type requirements for a LegacyCompletionHandler.
+ BOOST_ASIO_LEGACY_COMPLETION_HANDLER_CHECK(
+ LegacyCompletionHandler, handler) type_check;
+
+ detail::non_const_lvalue<LegacyCompletionHandler> handler2(handler);
+
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler2.value);
+
// Allocate and construct an operation to wrap the handler.
typedef detail::completion_handler<
- typename handler_type<LegacyCompletionHandler, void ()>::type> op;
- typename op::ptr p = { detail::addressof(init.completion_handler),
- op::ptr::allocate(init.completion_handler), 0 };
- p.p = new (p.v) op(init.completion_handler);
+ typename decay<LegacyCompletionHandler>::type> op;
+ typename op::ptr p = { detail::addressof(handler2.value),
+ op::ptr::allocate(handler2.value), 0 };
+ p.p = new (p.v) op(handler2.value);
- BOOST_ASIO_HANDLER_CREATION((*this, *p.p,
- "io_context", this, 0, "dispatch"));
+ BOOST_ASIO_HANDLER_CREATION((*self, *p.p,
+ "io_context", self, 0, "post"));
- impl_.do_dispatch(p.p);
+ self->impl_.post_immediate_completion(p.p, is_continuation);
p.v = p.p = 0;
}
-
- return init.result.get();
-}
+};
template <typename LegacyCompletionHandler>
BOOST_ASIO_INITFN_RESULT_TYPE(LegacyCompletionHandler, void ())
io_context::post(BOOST_ASIO_MOVE_ARG(LegacyCompletionHandler) handler)
{
- // If you get an error on the following line it means that your handler does
- // not meet the documented type requirements for a LegacyCompletionHandler.
- BOOST_ASIO_LEGACY_COMPLETION_HANDLER_CHECK(
- LegacyCompletionHandler, handler) type_check;
-
- async_completion<LegacyCompletionHandler, void ()> init(handler);
-
- bool is_continuation =
- boost_asio_handler_cont_helpers::is_continuation(init.completion_handler);
-
- // Allocate and construct an operation to wrap the handler.
- typedef detail::completion_handler<
- typename handler_type<LegacyCompletionHandler, void ()>::type> op;
- typename op::ptr p = { detail::addressof(init.completion_handler),
- op::ptr::allocate(init.completion_handler), 0 };
- p.p = new (p.v) op(init.completion_handler);
-
- BOOST_ASIO_HANDLER_CREATION((*this, *p.p,
- "io_context", this, 0, "post"));
-
- impl_.post_immediate_completion(p.p, is_continuation);
- p.v = p.p = 0;
-
- return init.result.get();
+ return async_initiate<LegacyCompletionHandler, void ()>(
+ initiate_post(), handler, this);
}
template <typename Handler>
@@ -320,11 +342,6 @@ inline boost::asio::io_context& io_context::work::get_io_context()
{
return static_cast<boost::asio::io_context&>(io_context_impl_.context());
}
-
-inline boost::asio::io_context& io_context::work::get_io_service()
-{
- return static_cast<boost::asio::io_context&>(io_context_impl_.context());
-}
#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
inline boost::asio::io_context& io_context::service::get_io_context()
@@ -332,13 +349,6 @@ inline boost::asio::io_context& io_context::service::get_io_context()
return static_cast<boost::asio::io_context&>(context());
}
-#if !defined(BOOST_ASIO_NO_DEPRECATED)
-inline boost::asio::io_context& io_context::service::get_io_service()
-{
- return static_cast<boost::asio::io_context&>(context());
-}
-#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
-
} // namespace asio
} // namespace boost
diff --git a/boost/asio/impl/io_context.ipp b/boost/asio/impl/io_context.ipp
index 96a7de7415..5de07181d4 100644
--- a/boost/asio/impl/io_context.ipp
+++ b/boost/asio/impl/io_context.ipp
@@ -2,7 +2,7 @@
// impl/io_context.ipp
// ~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -35,13 +35,14 @@ namespace boost {
namespace asio {
io_context::io_context()
- : impl_(add_impl(new impl_type(*this, BOOST_ASIO_CONCURRENCY_HINT_DEFAULT)))
+ : impl_(add_impl(new impl_type(*this,
+ BOOST_ASIO_CONCURRENCY_HINT_DEFAULT, false)))
{
}
io_context::io_context(int concurrency_hint)
: impl_(add_impl(new impl_type(*this, concurrency_hint == 1
- ? BOOST_ASIO_CONCURRENCY_HINT_1 : concurrency_hint)))
+ ? BOOST_ASIO_CONCURRENCY_HINT_1 : concurrency_hint, false)))
{
}
diff --git a/boost/asio/impl/post.hpp b/boost/asio/impl/post.hpp
index d318f890ff..ac0831e532 100644
--- a/boost/asio/impl/post.hpp
+++ b/boost/asio/impl/post.hpp
@@ -2,7 +2,7 @@
// impl/post.hpp
// ~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -24,24 +24,46 @@
namespace boost {
namespace asio {
+namespace detail {
-template <typename CompletionToken>
-BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void()) post(
- BOOST_ASIO_MOVE_ARG(CompletionToken) token)
+struct initiate_post
{
- typedef BOOST_ASIO_HANDLER_TYPE(CompletionToken, void()) handler;
+ template <typename CompletionHandler>
+ void operator()(BOOST_ASIO_MOVE_ARG(CompletionHandler) handler) const
+ {
+ typedef typename decay<CompletionHandler>::type DecayedHandler;
+
+ typename associated_executor<DecayedHandler>::type ex(
+ (get_associated_executor)(handler));
- async_completion<CompletionToken, void()> init(token);
+ typename associated_allocator<DecayedHandler>::type alloc(
+ (get_associated_allocator)(handler));
- typename associated_executor<handler>::type ex(
- (get_associated_executor)(init.completion_handler));
+ ex.post(BOOST_ASIO_MOVE_CAST(CompletionHandler)(handler), alloc);
+ }
- typename associated_allocator<handler>::type alloc(
- (get_associated_allocator)(init.completion_handler));
+ template <typename CompletionHandler, typename Executor>
+ void operator()(BOOST_ASIO_MOVE_ARG(CompletionHandler) handler,
+ BOOST_ASIO_MOVE_ARG(Executor) ex) const
+ {
+ typedef typename decay<CompletionHandler>::type DecayedHandler;
- ex.post(BOOST_ASIO_MOVE_CAST(handler)(init.completion_handler), alloc);
+ typename associated_allocator<DecayedHandler>::type alloc(
+ (get_associated_allocator)(handler));
- return init.result.get();
+ ex.post(detail::work_dispatcher<DecayedHandler>(
+ BOOST_ASIO_MOVE_CAST(CompletionHandler)(handler)), alloc);
+ }
+};
+
+} // namespace detail
+
+template <typename CompletionToken>
+BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void()) post(
+ BOOST_ASIO_MOVE_ARG(CompletionToken) token)
+{
+ return async_initiate<CompletionToken, void()>(
+ detail::initiate_post(), token);
}
template <typename Executor, typename CompletionToken>
@@ -49,16 +71,8 @@ BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void()) post(
const Executor& ex, BOOST_ASIO_MOVE_ARG(CompletionToken) token,
typename enable_if<is_executor<Executor>::value>::type*)
{
- typedef BOOST_ASIO_HANDLER_TYPE(CompletionToken, void()) handler;
-
- async_completion<CompletionToken, void()> init(token);
-
- typename associated_allocator<handler>::type alloc(
- (get_associated_allocator)(init.completion_handler));
-
- ex.post(detail::work_dispatcher<handler>(init.completion_handler), alloc);
-
- return init.result.get();
+ return async_initiate<CompletionToken, void()>(
+ detail::initiate_post(), token, ex);
}
template <typename ExecutionContext, typename CompletionToken>
diff --git a/boost/asio/impl/read.hpp b/boost/asio/impl/read.hpp
index 9fbddc964e..6eabf0f616 100644
--- a/boost/asio/impl/read.hpp
+++ b/boost/asio/impl/read.hpp
@@ -2,7 +2,7 @@
// impl/read.hpp
// ~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -29,6 +29,7 @@
#include <boost/asio/detail/handler_cont_helpers.hpp>
#include <boost/asio/detail/handler_invoke_helpers.hpp>
#include <boost/asio/detail/handler_type_requirements.hpp>
+#include <boost/asio/detail/non_const_lvalue.hpp>
#include <boost/asio/detail/throw_error.hpp>
#include <boost/asio/error.hpp>
@@ -69,7 +70,8 @@ std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
>::type*)
{
return detail::read_buffer_sequence(s, buffers,
- boost::asio::buffer_sequence_begin(buffers), completion_condition, ec);
+ boost::asio::buffer_sequence_begin(buffers),
+ BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);
}
template <typename SyncReadStream, typename MutableBufferSequence>
@@ -103,22 +105,26 @@ inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
>::type*)
{
boost::system::error_code ec;
- std::size_t bytes_transferred = read(s, buffers, completion_condition, ec);
+ std::size_t bytes_transferred = read(s, buffers,
+ BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);
boost::asio::detail::throw_error(ec, "read");
return bytes_transferred;
}
-template <typename SyncReadStream, typename DynamicBuffer,
+#if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
+
+template <typename SyncReadStream, typename DynamicBuffer_v1,
typename CompletionCondition>
std::size_t read(SyncReadStream& s,
- BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
+ BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
CompletionCondition completion_condition, boost::system::error_code& ec,
typename enable_if<
- is_dynamic_buffer<typename decay<DynamicBuffer>::type>::value
+ is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
+ && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
>::type*)
{
- typename decay<DynamicBuffer>::type b(
- BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers));
+ typename decay<DynamicBuffer_v1>::type b(
+ BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers));
ec = boost::system::error_code();
std::size_t total_transferred = 0;
@@ -141,45 +147,48 @@ std::size_t read(SyncReadStream& s,
return total_transferred;
}
-template <typename SyncReadStream, typename DynamicBuffer>
+template <typename SyncReadStream, typename DynamicBuffer_v1>
inline std::size_t read(SyncReadStream& s,
- BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
+ BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
typename enable_if<
- is_dynamic_buffer<typename decay<DynamicBuffer>::type>::value
+ is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
+ && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
>::type*)
{
boost::system::error_code ec;
std::size_t bytes_transferred = read(s,
- BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers), transfer_all(), ec);
+ BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), transfer_all(), ec);
boost::asio::detail::throw_error(ec, "read");
return bytes_transferred;
}
-template <typename SyncReadStream, typename DynamicBuffer>
+template <typename SyncReadStream, typename DynamicBuffer_v1>
inline std::size_t read(SyncReadStream& s,
- BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
+ BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
boost::system::error_code& ec,
typename enable_if<
- is_dynamic_buffer<typename decay<DynamicBuffer>::type>::value
+ is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
+ && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
>::type*)
{
- return read(s, BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers),
+ return read(s, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),
transfer_all(), ec);
}
-template <typename SyncReadStream, typename DynamicBuffer,
+template <typename SyncReadStream, typename DynamicBuffer_v1,
typename CompletionCondition>
inline std::size_t read(SyncReadStream& s,
- BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
+ BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
CompletionCondition completion_condition,
typename enable_if<
- is_dynamic_buffer<typename decay<DynamicBuffer>::type>::value
+ is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
+ && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
>::type*)
{
boost::system::error_code ec;
std::size_t bytes_transferred = read(s,
- BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers),
- completion_condition, ec);
+ BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),
+ BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);
boost::asio::detail::throw_error(ec, "read");
return bytes_transferred;
}
@@ -193,7 +202,8 @@ inline std::size_t read(SyncReadStream& s,
boost::asio::basic_streambuf<Allocator>& b,
CompletionCondition completion_condition, boost::system::error_code& ec)
{
- return read(s, basic_streambuf_ref<Allocator>(b), completion_condition, ec);
+ return read(s, basic_streambuf_ref<Allocator>(b),
+ BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);
}
template <typename SyncReadStream, typename Allocator>
@@ -217,11 +227,87 @@ inline std::size_t read(SyncReadStream& s,
boost::asio::basic_streambuf<Allocator>& b,
CompletionCondition completion_condition)
{
- return read(s, basic_streambuf_ref<Allocator>(b), completion_condition);
+ return read(s, basic_streambuf_ref<Allocator>(b),
+ BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition));
}
#endif // !defined(BOOST_ASIO_NO_IOSTREAM)
#endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
+#endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
+
+template <typename SyncReadStream, typename DynamicBuffer_v2,
+ typename CompletionCondition>
+std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers,
+ CompletionCondition completion_condition, boost::system::error_code& ec,
+ typename enable_if<
+ is_dynamic_buffer_v2<DynamicBuffer_v2>::value
+ >::type*)
+{
+ DynamicBuffer_v2& b = buffers;
+
+ ec = boost::system::error_code();
+ std::size_t total_transferred = 0;
+ std::size_t max_size = detail::adapt_completion_condition_result(
+ completion_condition(ec, total_transferred));
+ std::size_t bytes_available = std::min<std::size_t>(
+ std::max<std::size_t>(512, b.capacity() - b.size()),
+ std::min<std::size_t>(max_size, b.max_size() - b.size()));
+ while (bytes_available > 0)
+ {
+ std::size_t pos = b.size();
+ b.grow(bytes_available);
+ std::size_t bytes_transferred = s.read_some(
+ b.data(pos, bytes_available), ec);
+ b.shrink(bytes_available - bytes_transferred);
+ total_transferred += bytes_transferred;
+ max_size = detail::adapt_completion_condition_result(
+ completion_condition(ec, total_transferred));
+ bytes_available = std::min<std::size_t>(
+ std::max<std::size_t>(512, b.capacity() - b.size()),
+ std::min<std::size_t>(max_size, b.max_size() - b.size()));
+ }
+ return total_transferred;
+}
+
+template <typename SyncReadStream, typename DynamicBuffer_v2>
+inline std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers,
+ typename enable_if<
+ is_dynamic_buffer_v2<DynamicBuffer_v2>::value
+ >::type*)
+{
+ boost::system::error_code ec;
+ std::size_t bytes_transferred = read(s,
+ BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), transfer_all(), ec);
+ boost::asio::detail::throw_error(ec, "read");
+ return bytes_transferred;
+}
+
+template <typename SyncReadStream, typename DynamicBuffer_v2>
+inline std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers,
+ boost::system::error_code& ec,
+ typename enable_if<
+ is_dynamic_buffer_v2<DynamicBuffer_v2>::value
+ >::type*)
+{
+ return read(s, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),
+ transfer_all(), ec);
+}
+
+template <typename SyncReadStream, typename DynamicBuffer_v2,
+ typename CompletionCondition>
+inline std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers,
+ CompletionCondition completion_condition,
+ typename enable_if<
+ is_dynamic_buffer_v2<DynamicBuffer_v2>::value
+ >::type*)
+{
+ boost::system::error_code ec;
+ std::size_t bytes_transferred = read(s,
+ BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),
+ BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);
+ boost::asio::detail::throw_error(ec, "read");
+ return bytes_transferred;
+}
namespace detail
{
@@ -233,7 +319,7 @@ namespace detail
{
public:
read_op(AsyncReadStream& stream, const MutableBufferSequence& buffers,
- CompletionCondition completion_condition, ReadHandler& handler)
+ CompletionCondition& completion_condition, ReadHandler& handler)
: detail::base_from_completion_cond<
CompletionCondition>(completion_condition),
stream_(stream),
@@ -254,9 +340,11 @@ namespace detail
}
read_op(read_op&& other)
- : detail::base_from_completion_cond<CompletionCondition>(other),
+ : detail::base_from_completion_cond<CompletionCondition>(
+ BOOST_ASIO_MOVE_CAST(detail::base_from_completion_cond<
+ CompletionCondition>)(other)),
stream_(other.stream_),
- buffers_(other.buffers_),
+ buffers_(BOOST_ASIO_MOVE_CAST(buffers_type)(other.buffers_)),
start_(other.start_),
handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
{
@@ -287,9 +375,11 @@ namespace detail
}
//private:
+ typedef boost::asio::detail::consuming_buffers<mutable_buffer,
+ MutableBufferSequence, MutableBufferIterator> buffers_type;
+
AsyncReadStream& stream_;
- boost::asio::detail::consuming_buffers<mutable_buffer,
- MutableBufferSequence, MutableBufferIterator> buffers_;
+ buffers_type buffers_;
int start_;
ReadHandler handler_;
};
@@ -355,13 +445,33 @@ namespace detail
typename ReadHandler>
inline void start_read_buffer_sequence_op(AsyncReadStream& stream,
const MutableBufferSequence& buffers, const MutableBufferIterator&,
- CompletionCondition completion_condition, ReadHandler& handler)
+ CompletionCondition& completion_condition, ReadHandler& handler)
{
detail::read_op<AsyncReadStream, MutableBufferSequence,
MutableBufferIterator, CompletionCondition, ReadHandler>(
stream, buffers, completion_condition, handler)(
boost::system::error_code(), 0, 1);
}
+
+ struct initiate_async_read_buffer_sequence
+ {
+ template <typename ReadHandler, typename AsyncReadStream,
+ typename MutableBufferSequence, typename CompletionCondition>
+ void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
+ AsyncReadStream* s, const MutableBufferSequence& buffers,
+ BOOST_ASIO_MOVE_ARG(CompletionCondition) completion_cond) const
+ {
+ // If you get an error on the following line it means that your handler
+ // does not meet the documented type requirements for a ReadHandler.
+ BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
+
+ non_const_lvalue<ReadHandler> handler2(handler);
+ non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);
+ start_read_buffer_sequence_op(*s, buffers,
+ boost::asio::buffer_sequence_begin(buffers),
+ completion_cond2.value, handler2.value);
+ }
+ };
} // namespace detail
#if !defined(GENERATING_DOCUMENTATION)
@@ -417,18 +527,10 @@ async_read(AsyncReadStream& s, const MutableBufferSequence& buffers,
is_mutable_buffer_sequence<MutableBufferSequence>::value
>::type*)
{
- // If you get an error on the following line it means that your handler does
- // not meet the documented type requirements for a ReadHandler.
- BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
-
- async_completion<ReadHandler,
- void (boost::system::error_code, std::size_t)> init(handler);
-
- detail::start_read_buffer_sequence_op(s, buffers,
- boost::asio::buffer_sequence_begin(buffers), completion_condition,
- init.completion_handler);
-
- return init.result.get();
+ return async_initiate<ReadHandler,
+ void (boost::system::error_code, std::size_t)>(
+ detail::initiate_async_read_buffer_sequence(), handler, &s, buffers,
+ BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition));
}
template <typename AsyncReadStream, typename MutableBufferSequence,
@@ -441,32 +543,26 @@ async_read(AsyncReadStream& s, const MutableBufferSequence& buffers,
is_mutable_buffer_sequence<MutableBufferSequence>::value
>::type*)
{
- // If you get an error on the following line it means that your handler does
- // not meet the documented type requirements for a ReadHandler.
- BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
-
- async_completion<ReadHandler,
- void (boost::system::error_code, std::size_t)> init(handler);
-
- detail::start_read_buffer_sequence_op(s, buffers,
- boost::asio::buffer_sequence_begin(buffers), transfer_all(),
- init.completion_handler);
-
- return init.result.get();
+ return async_initiate<ReadHandler,
+ void (boost::system::error_code, std::size_t)>(
+ detail::initiate_async_read_buffer_sequence(),
+ handler, &s, buffers, transfer_all());
}
+#if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
+
namespace detail
{
- template <typename AsyncReadStream, typename DynamicBuffer,
+ template <typename AsyncReadStream, typename DynamicBuffer_v1,
typename CompletionCondition, typename ReadHandler>
- class read_dynbuf_op
+ class read_dynbuf_v1_op
: detail::base_from_completion_cond<CompletionCondition>
{
public:
template <typename BufferSequence>
- read_dynbuf_op(AsyncReadStream& stream,
+ read_dynbuf_v1_op(AsyncReadStream& stream,
BOOST_ASIO_MOVE_ARG(BufferSequence) buffers,
- CompletionCondition completion_condition, ReadHandler& handler)
+ CompletionCondition& completion_condition, ReadHandler& handler)
: detail::base_from_completion_cond<
CompletionCondition>(completion_condition),
stream_(stream),
@@ -478,7 +574,7 @@ namespace detail
}
#if defined(BOOST_ASIO_HAS_MOVE)
- read_dynbuf_op(const read_dynbuf_op& other)
+ read_dynbuf_v1_op(const read_dynbuf_v1_op& other)
: detail::base_from_completion_cond<CompletionCondition>(other),
stream_(other.stream_),
buffers_(other.buffers_),
@@ -488,10 +584,12 @@ namespace detail
{
}
- read_dynbuf_op(read_dynbuf_op&& other)
- : detail::base_from_completion_cond<CompletionCondition>(other),
+ read_dynbuf_v1_op(read_dynbuf_v1_op&& other)
+ : detail::base_from_completion_cond<CompletionCondition>(
+ BOOST_ASIO_MOVE_CAST(detail::base_from_completion_cond<
+ CompletionCondition>)(other)),
stream_(other.stream_),
- buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer)(other.buffers_)),
+ buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(other.buffers_)),
start_(other.start_),
total_transferred_(other.total_transferred_),
handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
@@ -515,7 +613,7 @@ namespace detail
for (;;)
{
stream_.async_read_some(buffers_.prepare(bytes_available),
- BOOST_ASIO_MOVE_CAST(read_dynbuf_op)(*this));
+ BOOST_ASIO_MOVE_CAST(read_dynbuf_v1_op)(*this));
return; default:
total_transferred_ += bytes_transferred;
buffers_.commit(bytes_transferred);
@@ -535,36 +633,36 @@ namespace detail
//private:
AsyncReadStream& stream_;
- DynamicBuffer buffers_;
+ DynamicBuffer_v1 buffers_;
int start_;
std::size_t total_transferred_;
ReadHandler handler_;
};
- template <typename AsyncReadStream, typename DynamicBuffer,
+ template <typename AsyncReadStream, typename DynamicBuffer_v1,
typename CompletionCondition, typename ReadHandler>
inline void* asio_handler_allocate(std::size_t size,
- read_dynbuf_op<AsyncReadStream, DynamicBuffer,
+ read_dynbuf_v1_op<AsyncReadStream, DynamicBuffer_v1,
CompletionCondition, ReadHandler>* this_handler)
{
return boost_asio_handler_alloc_helpers::allocate(
size, this_handler->handler_);
}
- template <typename AsyncReadStream, typename DynamicBuffer,
+ template <typename AsyncReadStream, typename DynamicBuffer_v1,
typename CompletionCondition, typename ReadHandler>
inline void asio_handler_deallocate(void* pointer, std::size_t size,
- read_dynbuf_op<AsyncReadStream, DynamicBuffer,
+ read_dynbuf_v1_op<AsyncReadStream, DynamicBuffer_v1,
CompletionCondition, ReadHandler>* this_handler)
{
boost_asio_handler_alloc_helpers::deallocate(
pointer, size, this_handler->handler_);
}
- template <typename AsyncReadStream, typename DynamicBuffer,
+ template <typename AsyncReadStream, typename DynamicBuffer_v1,
typename CompletionCondition, typename ReadHandler>
inline bool asio_handler_is_continuation(
- read_dynbuf_op<AsyncReadStream, DynamicBuffer,
+ read_dynbuf_v1_op<AsyncReadStream, DynamicBuffer_v1,
CompletionCondition, ReadHandler>* this_handler)
{
return this_handler->start_ == 0 ? true
@@ -573,10 +671,10 @@ namespace detail
}
template <typename Function, typename AsyncReadStream,
- typename DynamicBuffer, typename CompletionCondition,
+ typename DynamicBuffer_v1, typename CompletionCondition,
typename ReadHandler>
inline void asio_handler_invoke(Function& function,
- read_dynbuf_op<AsyncReadStream, DynamicBuffer,
+ read_dynbuf_v1_op<AsyncReadStream, DynamicBuffer_v1,
CompletionCondition, ReadHandler>* this_handler)
{
boost_asio_handler_invoke_helpers::invoke(
@@ -584,49 +682,71 @@ namespace detail
}
template <typename Function, typename AsyncReadStream,
- typename DynamicBuffer, typename CompletionCondition,
+ typename DynamicBuffer_v1, typename CompletionCondition,
typename ReadHandler>
inline void asio_handler_invoke(const Function& function,
- read_dynbuf_op<AsyncReadStream, DynamicBuffer,
+ read_dynbuf_v1_op<AsyncReadStream, DynamicBuffer_v1,
CompletionCondition, ReadHandler>* this_handler)
{
boost_asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
}
+
+ struct initiate_async_read_dynbuf_v1
+ {
+ template <typename ReadHandler, typename AsyncReadStream,
+ typename DynamicBuffer_v1, typename CompletionCondition>
+ void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
+ AsyncReadStream* s, BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
+ BOOST_ASIO_MOVE_ARG(CompletionCondition) completion_cond) const
+ {
+ // If you get an error on the following line it means that your handler
+ // does not meet the documented type requirements for a ReadHandler.
+ BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
+
+ non_const_lvalue<ReadHandler> handler2(handler);
+ non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);
+ read_dynbuf_v1_op<AsyncReadStream, typename decay<DynamicBuffer_v1>::type,
+ CompletionCondition, typename decay<ReadHandler>::type>(
+ *s, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),
+ completion_cond2.value, handler2.value)(
+ boost::system::error_code(), 0, 1);
+ }
+ };
} // namespace detail
#if !defined(GENERATING_DOCUMENTATION)
-template <typename AsyncReadStream, typename DynamicBuffer,
+template <typename AsyncReadStream, typename DynamicBuffer_v1,
typename CompletionCondition, typename ReadHandler, typename Allocator>
struct associated_allocator<
- detail::read_dynbuf_op<AsyncReadStream,
- DynamicBuffer, CompletionCondition, ReadHandler>,
+ detail::read_dynbuf_v1_op<AsyncReadStream,
+ DynamicBuffer_v1, CompletionCondition, ReadHandler>,
Allocator>
{
typedef typename associated_allocator<ReadHandler, Allocator>::type type;
static type get(
- const detail::read_dynbuf_op<AsyncReadStream,
- DynamicBuffer, CompletionCondition, ReadHandler>& h,
+ const detail::read_dynbuf_v1_op<AsyncReadStream,
+ DynamicBuffer_v1, CompletionCondition, ReadHandler>& h,
const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
{
return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);
}
};
-template <typename AsyncReadStream, typename DynamicBuffer,
+template <typename AsyncReadStream, typename DynamicBuffer_v1,
typename CompletionCondition, typename ReadHandler, typename Executor>
struct associated_executor<
- detail::read_dynbuf_op<AsyncReadStream,
- DynamicBuffer, CompletionCondition, ReadHandler>,
+ detail::read_dynbuf_v1_op<AsyncReadStream,
+ DynamicBuffer_v1, CompletionCondition, ReadHandler>,
Executor>
{
typedef typename associated_executor<ReadHandler, Executor>::type type;
static type get(
- const detail::read_dynbuf_op<AsyncReadStream,
- DynamicBuffer, CompletionCondition, ReadHandler>& h,
+ const detail::read_dynbuf_v1_op<AsyncReadStream,
+ DynamicBuffer_v1, CompletionCondition, ReadHandler>& h,
const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
{
return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);
@@ -636,49 +756,44 @@ struct associated_executor<
#endif // !defined(GENERATING_DOCUMENTATION)
template <typename AsyncReadStream,
- typename DynamicBuffer, typename ReadHandler>
+ typename DynamicBuffer_v1, typename ReadHandler>
inline BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
void (boost::system::error_code, std::size_t))
async_read(AsyncReadStream& s,
- BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
+ BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
typename enable_if<
- is_dynamic_buffer<typename decay<DynamicBuffer>::type>::value
+ is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
+ && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
>::type*)
{
return async_read(s,
- BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers),
+ BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),
transfer_all(), BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
}
-template <typename AsyncReadStream, typename DynamicBuffer,
+template <typename AsyncReadStream, typename DynamicBuffer_v1,
typename CompletionCondition, typename ReadHandler>
inline BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
void (boost::system::error_code, std::size_t))
async_read(AsyncReadStream& s,
- BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
+ BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
CompletionCondition completion_condition,
BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
typename enable_if<
- is_dynamic_buffer<typename decay<DynamicBuffer>::type>::value
+ is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
+ && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
>::type*)
{
// If you get an error on the following line it means that your handler does
// not meet the documented type requirements for a ReadHandler.
BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
- async_completion<ReadHandler,
- void (boost::system::error_code, std::size_t)> init(handler);
-
- detail::read_dynbuf_op<AsyncReadStream,
- typename decay<DynamicBuffer>::type,
- CompletionCondition, BOOST_ASIO_HANDLER_TYPE(
- ReadHandler, void (boost::system::error_code, std::size_t))>(
- s, BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers),
- completion_condition, init.completion_handler)(
- boost::system::error_code(), 0, 1);
-
- return init.result.get();
+ return async_initiate<ReadHandler,
+ void (boost::system::error_code, std::size_t)>(
+ detail::initiate_async_read_dynbuf_v1(), handler, &s,
+ BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),
+ BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition));
}
#if !defined(BOOST_ASIO_NO_EXTENSIONS)
@@ -703,11 +818,260 @@ async_read(AsyncReadStream& s, basic_streambuf<Allocator>& b,
BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
{
return async_read(s, basic_streambuf_ref<Allocator>(b),
- completion_condition, BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
+ BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition),
+ BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
}
#endif // !defined(BOOST_ASIO_NO_IOSTREAM)
#endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
+#endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
+
+namespace detail
+{
+ template <typename AsyncReadStream, typename DynamicBuffer_v2,
+ typename CompletionCondition, typename ReadHandler>
+ class read_dynbuf_v2_op
+ : detail::base_from_completion_cond<CompletionCondition>
+ {
+ public:
+ template <typename BufferSequence>
+ read_dynbuf_v2_op(AsyncReadStream& stream,
+ BOOST_ASIO_MOVE_ARG(BufferSequence) buffers,
+ CompletionCondition& completion_condition, ReadHandler& handler)
+ : detail::base_from_completion_cond<
+ CompletionCondition>(completion_condition),
+ stream_(stream),
+ buffers_(BOOST_ASIO_MOVE_CAST(BufferSequence)(buffers)),
+ start_(0),
+ total_transferred_(0),
+ bytes_available_(0),
+ handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
+ {
+ }
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+ read_dynbuf_v2_op(const read_dynbuf_v2_op& other)
+ : detail::base_from_completion_cond<CompletionCondition>(other),
+ stream_(other.stream_),
+ buffers_(other.buffers_),
+ start_(other.start_),
+ total_transferred_(other.total_transferred_),
+ bytes_available_(other.bytes_available_),
+ handler_(other.handler_)
+ {
+ }
+
+ read_dynbuf_v2_op(read_dynbuf_v2_op&& other)
+ : detail::base_from_completion_cond<CompletionCondition>(
+ BOOST_ASIO_MOVE_CAST(detail::base_from_completion_cond<
+ CompletionCondition>)(other)),
+ stream_(other.stream_),
+ buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(other.buffers_)),
+ start_(other.start_),
+ total_transferred_(other.total_transferred_),
+ bytes_available_(other.bytes_available_),
+ handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
+ {
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+ void operator()(const boost::system::error_code& ec,
+ std::size_t bytes_transferred, int start = 0)
+ {
+ std::size_t max_size, pos;
+ switch (start_ = start)
+ {
+ case 1:
+ max_size = this->check_for_completion(ec, total_transferred_);
+ bytes_available_ = std::min<std::size_t>(
+ std::max<std::size_t>(512,
+ buffers_.capacity() - buffers_.size()),
+ std::min<std::size_t>(max_size,
+ buffers_.max_size() - buffers_.size()));
+ for (;;)
+ {
+ pos = buffers_.size();
+ buffers_.grow(bytes_available_);
+ stream_.async_read_some(buffers_.data(pos, bytes_available_),
+ BOOST_ASIO_MOVE_CAST(read_dynbuf_v2_op)(*this));
+ return; default:
+ total_transferred_ += bytes_transferred;
+ buffers_.shrink(bytes_available_ - bytes_transferred);
+ max_size = this->check_for_completion(ec, total_transferred_);
+ bytes_available_ = std::min<std::size_t>(
+ std::max<std::size_t>(512,
+ buffers_.capacity() - buffers_.size()),
+ std::min<std::size_t>(max_size,
+ buffers_.max_size() - buffers_.size()));
+ if ((!ec && bytes_transferred == 0) || bytes_available_ == 0)
+ break;
+ }
+
+ handler_(ec, static_cast<const std::size_t&>(total_transferred_));
+ }
+ }
+
+ //private:
+ AsyncReadStream& stream_;
+ DynamicBuffer_v2 buffers_;
+ int start_;
+ std::size_t total_transferred_;
+ std::size_t bytes_available_;
+ ReadHandler handler_;
+ };
+
+ template <typename AsyncReadStream, typename DynamicBuffer_v2,
+ typename CompletionCondition, typename ReadHandler>
+ inline void* asio_handler_allocate(std::size_t size,
+ read_dynbuf_v2_op<AsyncReadStream, DynamicBuffer_v2,
+ CompletionCondition, ReadHandler>* this_handler)
+ {
+ return boost_asio_handler_alloc_helpers::allocate(
+ size, this_handler->handler_);
+ }
+
+ template <typename AsyncReadStream, typename DynamicBuffer_v2,
+ typename CompletionCondition, typename ReadHandler>
+ inline void asio_handler_deallocate(void* pointer, std::size_t size,
+ read_dynbuf_v2_op<AsyncReadStream, DynamicBuffer_v2,
+ CompletionCondition, ReadHandler>* this_handler)
+ {
+ boost_asio_handler_alloc_helpers::deallocate(
+ pointer, size, this_handler->handler_);
+ }
+
+ template <typename AsyncReadStream, typename DynamicBuffer_v2,
+ typename CompletionCondition, typename ReadHandler>
+ inline bool asio_handler_is_continuation(
+ read_dynbuf_v2_op<AsyncReadStream, DynamicBuffer_v2,
+ CompletionCondition, ReadHandler>* this_handler)
+ {
+ return this_handler->start_ == 0 ? true
+ : boost_asio_handler_cont_helpers::is_continuation(
+ this_handler->handler_);
+ }
+
+ template <typename Function, typename AsyncReadStream,
+ typename DynamicBuffer_v2, typename CompletionCondition,
+ typename ReadHandler>
+ inline void asio_handler_invoke(Function& function,
+ read_dynbuf_v2_op<AsyncReadStream, DynamicBuffer_v2,
+ CompletionCondition, ReadHandler>* this_handler)
+ {
+ boost_asio_handler_invoke_helpers::invoke(
+ function, this_handler->handler_);
+ }
+
+ template <typename Function, typename AsyncReadStream,
+ typename DynamicBuffer_v2, typename CompletionCondition,
+ typename ReadHandler>
+ inline void asio_handler_invoke(const Function& function,
+ read_dynbuf_v2_op<AsyncReadStream, DynamicBuffer_v2,
+ CompletionCondition, ReadHandler>* this_handler)
+ {
+ boost_asio_handler_invoke_helpers::invoke(
+ function, this_handler->handler_);
+ }
+
+ struct initiate_async_read_dynbuf_v2
+ {
+ template <typename ReadHandler, typename AsyncReadStream,
+ typename DynamicBuffer_v2, typename CompletionCondition>
+ void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
+ AsyncReadStream* s, BOOST_ASIO_MOVE_ARG(DynamicBuffer_v2) buffers,
+ BOOST_ASIO_MOVE_ARG(CompletionCondition) completion_cond) const
+ {
+ // If you get an error on the following line it means that your handler
+ // does not meet the documented type requirements for a ReadHandler.
+ BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
+
+ non_const_lvalue<ReadHandler> handler2(handler);
+ non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);
+ read_dynbuf_v2_op<AsyncReadStream, typename decay<DynamicBuffer_v2>::type,
+ CompletionCondition, typename decay<ReadHandler>::type>(
+ *s, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),
+ completion_cond2.value, handler2.value)(
+ boost::system::error_code(), 0, 1);
+ }
+ };
+} // namespace detail
+
+#if !defined(GENERATING_DOCUMENTATION)
+
+template <typename AsyncReadStream, typename DynamicBuffer_v2,
+ typename CompletionCondition, typename ReadHandler, typename Allocator>
+struct associated_allocator<
+ detail::read_dynbuf_v2_op<AsyncReadStream,
+ DynamicBuffer_v2, CompletionCondition, ReadHandler>,
+ Allocator>
+{
+ typedef typename associated_allocator<ReadHandler, Allocator>::type type;
+
+ static type get(
+ const detail::read_dynbuf_v2_op<AsyncReadStream,
+ DynamicBuffer_v2, CompletionCondition, ReadHandler>& h,
+ const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
+ {
+ return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);
+ }
+};
+
+template <typename AsyncReadStream, typename DynamicBuffer_v2,
+ typename CompletionCondition, typename ReadHandler, typename Executor>
+struct associated_executor<
+ detail::read_dynbuf_v2_op<AsyncReadStream,
+ DynamicBuffer_v2, CompletionCondition, ReadHandler>,
+ Executor>
+{
+ typedef typename associated_executor<ReadHandler, Executor>::type type;
+
+ static type get(
+ const detail::read_dynbuf_v2_op<AsyncReadStream,
+ DynamicBuffer_v2, CompletionCondition, ReadHandler>& h,
+ const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
+ {
+ return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);
+ }
+};
+
+#endif // !defined(GENERATING_DOCUMENTATION)
+
+template <typename AsyncReadStream,
+ typename DynamicBuffer_v2, typename ReadHandler>
+inline BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
+ void (boost::system::error_code, std::size_t))
+async_read(AsyncReadStream& s, DynamicBuffer_v2 buffers,
+ BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
+ typename enable_if<
+ is_dynamic_buffer_v2<DynamicBuffer_v2>::value
+ >::type*)
+{
+ return async_read(s,
+ BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),
+ transfer_all(), BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
+}
+
+template <typename AsyncReadStream, typename DynamicBuffer_v2,
+ typename CompletionCondition, typename ReadHandler>
+inline BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
+ void (boost::system::error_code, std::size_t))
+async_read(AsyncReadStream& s, DynamicBuffer_v2 buffers,
+ CompletionCondition completion_condition,
+ BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
+ typename enable_if<
+ is_dynamic_buffer_v2<DynamicBuffer_v2>::value
+ >::type*)
+{
+ // If you get an error on the following line it means that your handler does
+ // not meet the documented type requirements for a ReadHandler.
+ BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
+
+ return async_initiate<ReadHandler,
+ void (boost::system::error_code, std::size_t)>(
+ detail::initiate_async_read_dynbuf_v2(), handler, &s,
+ BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),
+ BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition));
+}
} // namespace asio
} // namespace boost
diff --git a/boost/asio/impl/read_at.hpp b/boost/asio/impl/read_at.hpp
index e3c31c543e..8152ef99a4 100644
--- a/boost/asio/impl/read_at.hpp
+++ b/boost/asio/impl/read_at.hpp
@@ -2,7 +2,7 @@
// impl/read_at.hpp
// ~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -29,6 +29,7 @@
#include <boost/asio/detail/handler_cont_helpers.hpp>
#include <boost/asio/detail/handler_invoke_helpers.hpp>
#include <boost/asio/detail/handler_type_requirements.hpp>
+#include <boost/asio/detail/non_const_lvalue.hpp>
#include <boost/asio/detail/throw_error.hpp>
#include <boost/asio/error.hpp>
@@ -71,7 +72,8 @@ std::size_t read_at(SyncRandomAccessReadDevice& d,
CompletionCondition completion_condition, boost::system::error_code& ec)
{
return detail::read_at_buffer_sequence(d, offset, buffers,
- boost::asio::buffer_sequence_begin(buffers), completion_condition, ec);
+ boost::asio::buffer_sequence_begin(buffers),
+ BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);
}
template <typename SyncRandomAccessReadDevice, typename MutableBufferSequence>
@@ -100,8 +102,8 @@ inline std::size_t read_at(SyncRandomAccessReadDevice& d,
CompletionCondition completion_condition)
{
boost::system::error_code ec;
- std::size_t bytes_transferred = read_at(
- d, offset, buffers, completion_condition, ec);
+ std::size_t bytes_transferred = read_at(d, offset, buffers,
+ BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);
boost::asio::detail::throw_error(ec, "read_at");
return bytes_transferred;
}
@@ -159,8 +161,8 @@ inline std::size_t read_at(SyncRandomAccessReadDevice& d,
CompletionCondition completion_condition)
{
boost::system::error_code ec;
- std::size_t bytes_transferred = read_at(
- d, offset, b, completion_condition, ec);
+ std::size_t bytes_transferred = read_at(d, offset, b,
+ BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);
boost::asio::detail::throw_error(ec, "read_at");
return bytes_transferred;
}
@@ -179,7 +181,7 @@ namespace detail
public:
read_at_op(AsyncRandomAccessReadDevice& device,
uint64_t offset, const MutableBufferSequence& buffers,
- CompletionCondition completion_condition, ReadHandler& handler)
+ CompletionCondition& completion_condition, ReadHandler& handler)
: detail::base_from_completion_cond<
CompletionCondition>(completion_condition),
device_(device),
@@ -202,10 +204,12 @@ namespace detail
}
read_at_op(read_at_op&& other)
- : detail::base_from_completion_cond<CompletionCondition>(other),
+ : detail::base_from_completion_cond<CompletionCondition>(
+ BOOST_ASIO_MOVE_CAST(detail::base_from_completion_cond<
+ CompletionCondition>)(other)),
device_(other.device_),
offset_(other.offset_),
- buffers_(other.buffers_),
+ buffers_(BOOST_ASIO_MOVE_CAST(buffers_type)(other.buffers_)),
start_(other.start_),
handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
{
@@ -237,10 +241,12 @@ namespace detail
}
//private:
+ typedef boost::asio::detail::consuming_buffers<mutable_buffer,
+ MutableBufferSequence, MutableBufferIterator> buffers_type;
+
AsyncRandomAccessReadDevice& device_;
uint64_t offset_;
- boost::asio::detail::consuming_buffers<mutable_buffer,
- MutableBufferSequence, MutableBufferIterator> buffers_;
+ buffers_type buffers_;
int start_;
ReadHandler handler_;
};
@@ -306,7 +312,7 @@ namespace detail
typename CompletionCondition, typename ReadHandler>
inline void start_read_at_buffer_sequence_op(AsyncRandomAccessReadDevice& d,
uint64_t offset, const MutableBufferSequence& buffers,
- const MutableBufferIterator&, CompletionCondition completion_condition,
+ const MutableBufferIterator&, CompletionCondition& completion_condition,
ReadHandler& handler)
{
detail::read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,
@@ -314,6 +320,27 @@ namespace detail
d, offset, buffers, completion_condition, handler)(
boost::system::error_code(), 0, 1);
}
+
+ struct initiate_async_read_at_buffer_sequence
+ {
+ template <typename ReadHandler, typename AsyncRandomAccessReadDevice,
+ typename MutableBufferSequence, typename CompletionCondition>
+ void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
+ AsyncRandomAccessReadDevice* d, uint64_t offset,
+ const MutableBufferSequence& buffers,
+ BOOST_ASIO_MOVE_ARG(CompletionCondition) completion_cond) const
+ {
+ // If you get an error on the following line it means that your handler
+ // does not meet the documented type requirements for a ReadHandler.
+ BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
+
+ non_const_lvalue<ReadHandler> handler2(handler);
+ non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);
+ start_read_at_buffer_sequence_op(*d, offset, buffers,
+ boost::asio::buffer_sequence_begin(buffers),
+ completion_cond2.value, handler2.value);
+ }
+ };
} // namespace detail
#if !defined(GENERATING_DOCUMENTATION)
@@ -369,18 +396,10 @@ async_read_at(AsyncRandomAccessReadDevice& d,
CompletionCondition completion_condition,
BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
{
- // If you get an error on the following line it means that your handler does
- // not meet the documented type requirements for a ReadHandler.
- BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
-
- async_completion<ReadHandler,
- void (boost::system::error_code, std::size_t)> init(handler);
-
- detail::start_read_at_buffer_sequence_op(d, offset, buffers,
- boost::asio::buffer_sequence_begin(buffers), completion_condition,
- init.completion_handler);
-
- return init.result.get();
+ return async_initiate<ReadHandler,
+ void (boost::system::error_code, std::size_t)>(
+ detail::initiate_async_read_at_buffer_sequence(), handler, &d, offset,
+ buffers, BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition));
}
template <typename AsyncRandomAccessReadDevice, typename MutableBufferSequence,
@@ -391,18 +410,10 @@ async_read_at(AsyncRandomAccessReadDevice& d,
uint64_t offset, const MutableBufferSequence& buffers,
BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
{
- // If you get an error on the following line it means that your handler does
- // not meet the documented type requirements for a ReadHandler.
- BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
-
- async_completion<ReadHandler,
- void (boost::system::error_code, std::size_t)> init(handler);
-
- detail::start_read_at_buffer_sequence_op(d, offset, buffers,
- boost::asio::buffer_sequence_begin(buffers), transfer_all(),
- init.completion_handler);
-
- return init.result.get();
+ return async_initiate<ReadHandler,
+ void (boost::system::error_code, std::size_t)>(
+ detail::initiate_async_read_at_buffer_sequence(),
+ handler, &d, offset, buffers, transfer_all());
}
#if !defined(BOOST_ASIO_NO_EXTENSIONS)
@@ -418,7 +429,7 @@ namespace detail
public:
read_at_streambuf_op(AsyncRandomAccessReadDevice& device,
uint64_t offset, basic_streambuf<Allocator>& streambuf,
- CompletionCondition completion_condition, ReadHandler& handler)
+ CompletionCondition& completion_condition, ReadHandler& handler)
: detail::base_from_completion_cond<
CompletionCondition>(completion_condition),
device_(device),
@@ -443,7 +454,9 @@ namespace detail
}
read_at_streambuf_op(read_at_streambuf_op&& other)
- : detail::base_from_completion_cond<CompletionCondition>(other),
+ : detail::base_from_completion_cond<CompletionCondition>(
+ BOOST_ASIO_MOVE_CAST(detail::base_from_completion_cond<
+ CompletionCondition>)(other)),
device_(other.device_),
offset_(other.offset_),
streambuf_(other.streambuf_),
@@ -540,6 +553,28 @@ namespace detail
boost_asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
}
+
+ struct initiate_async_read_at_streambuf
+ {
+ template <typename ReadHandler, typename AsyncRandomAccessReadDevice,
+ typename Allocator, typename CompletionCondition>
+ void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
+ AsyncRandomAccessReadDevice* d, uint64_t offset,
+ basic_streambuf<Allocator>* b,
+ BOOST_ASIO_MOVE_ARG(CompletionCondition) completion_cond) const
+ {
+ // If you get an error on the following line it means that your handler
+ // does not meet the documented type requirements for a ReadHandler.
+ BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
+
+ non_const_lvalue<ReadHandler> handler2(handler);
+ non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);
+ read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator,
+ CompletionCondition, typename decay<ReadHandler>::type>(
+ *d, offset, *b, completion_cond2.value, handler2.value)(
+ boost::system::error_code(), 0, 1);
+ }
+ };
} // namespace detail
#if !defined(GENERATING_DOCUMENTATION)
@@ -591,20 +626,10 @@ async_read_at(AsyncRandomAccessReadDevice& d,
CompletionCondition completion_condition,
BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
{
- // If you get an error on the following line it means that your handler does
- // not meet the documented type requirements for a ReadHandler.
- BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
-
- async_completion<ReadHandler,
- void (boost::system::error_code, std::size_t)> init(handler);
-
- detail::read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator,
- CompletionCondition, BOOST_ASIO_HANDLER_TYPE(ReadHandler,
- void (boost::system::error_code, std::size_t))>(
- d, offset, b, completion_condition, init.completion_handler)(
- boost::system::error_code(), 0, 1);
-
- return init.result.get();
+ return async_initiate<ReadHandler,
+ void (boost::system::error_code, std::size_t)>(
+ detail::initiate_async_read_at_streambuf(), handler, &d, offset,
+ &b, BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition));
}
template <typename AsyncRandomAccessReadDevice, typename Allocator,
@@ -615,20 +640,10 @@ async_read_at(AsyncRandomAccessReadDevice& d,
uint64_t offset, boost::asio::basic_streambuf<Allocator>& b,
BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
{
- // If you get an error on the following line it means that your handler does
- // not meet the documented type requirements for a ReadHandler.
- BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
-
- async_completion<ReadHandler,
- void (boost::system::error_code, std::size_t)> init(handler);
-
- detail::read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator,
- detail::transfer_all_t, BOOST_ASIO_HANDLER_TYPE(ReadHandler,
- void (boost::system::error_code, std::size_t))>(
- d, offset, b, transfer_all(), init.completion_handler)(
- boost::system::error_code(), 0, 1);
-
- return init.result.get();
+ return async_initiate<ReadHandler,
+ void (boost::system::error_code, std::size_t)>(
+ detail::initiate_async_read_at_streambuf(),
+ handler, &d, offset, &b, transfer_all());
}
#endif // !defined(BOOST_ASIO_NO_IOSTREAM)
diff --git a/boost/asio/impl/read_until.hpp b/boost/asio/impl/read_until.hpp
index 8bc959557a..63b86f8f2e 100644
--- a/boost/asio/impl/read_until.hpp
+++ b/boost/asio/impl/read_until.hpp
@@ -2,7 +2,7 @@
// impl/read_until.hpp
// ~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -29,6 +29,7 @@
#include <boost/asio/detail/handler_invoke_helpers.hpp>
#include <boost/asio/detail/handler_type_requirements.hpp>
#include <boost/asio/detail/limits.hpp>
+#include <boost/asio/detail/non_const_lvalue.hpp>
#include <boost/asio/detail/throw_error.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -36,30 +37,75 @@
namespace boost {
namespace asio {
-template <typename SyncReadStream, typename DynamicBuffer>
+namespace detail
+{
+ // Algorithm that finds a subsequence of equal values in a sequence. Returns
+ // (iterator,true) if a full match was found, in which case the iterator
+ // points to the beginning of the match. Returns (iterator,false) if a
+ // partial match was found at the end of the first sequence, in which case
+ // the iterator points to the beginning of the partial match. Returns
+ // (last1,false) if no full or partial match was found.
+ template <typename Iterator1, typename Iterator2>
+ std::pair<Iterator1, bool> partial_search(
+ Iterator1 first1, Iterator1 last1, Iterator2 first2, Iterator2 last2)
+ {
+ for (Iterator1 iter1 = first1; iter1 != last1; ++iter1)
+ {
+ Iterator1 test_iter1 = iter1;
+ Iterator2 test_iter2 = first2;
+ for (;; ++test_iter1, ++test_iter2)
+ {
+ if (test_iter2 == last2)
+ return std::make_pair(iter1, true);
+ if (test_iter1 == last1)
+ {
+ if (test_iter2 != first2)
+ return std::make_pair(iter1, false);
+ else
+ break;
+ }
+ if (*test_iter1 != *test_iter2)
+ break;
+ }
+ }
+ return std::make_pair(last1, false);
+ }
+} // namespace detail
+
+#if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
+
+template <typename SyncReadStream, typename DynamicBuffer_v1>
inline std::size_t read_until(SyncReadStream& s,
- BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers, char delim)
+ BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, char delim,
+ typename enable_if<
+ is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
+ && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
+ >::type*)
{
boost::system::error_code ec;
std::size_t bytes_transferred = read_until(s,
- BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers), delim, ec);
+ BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), delim, ec);
boost::asio::detail::throw_error(ec, "read_until");
return bytes_transferred;
}
-template <typename SyncReadStream, typename DynamicBuffer>
+template <typename SyncReadStream, typename DynamicBuffer_v1>
std::size_t read_until(SyncReadStream& s,
- BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
- char delim, boost::system::error_code& ec)
+ BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
+ char delim, boost::system::error_code& ec,
+ typename enable_if<
+ is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
+ && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
+ >::type*)
{
- typename decay<DynamicBuffer>::type b(
- BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers));
+ typename decay<DynamicBuffer_v1>::type b(
+ BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers));
std::size_t search_position = 0;
for (;;)
{
// Determine the range of the data to be searched.
- typedef typename DynamicBuffer::const_buffers_type buffers_type;
+ typedef typename DynamicBuffer_v1::const_buffers_type buffers_type;
typedef buffers_iterator<buffers_type> iterator;
buffers_type data_buffers = b.data();
iterator begin = iterator::begin(data_buffers);
@@ -97,66 +143,39 @@ std::size_t read_until(SyncReadStream& s,
}
}
-template <typename SyncReadStream, typename DynamicBuffer>
+template <typename SyncReadStream, typename DynamicBuffer_v1>
inline std::size_t read_until(SyncReadStream& s,
- BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
- BOOST_ASIO_STRING_VIEW_PARAM delim)
+ BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
+ BOOST_ASIO_STRING_VIEW_PARAM delim,
+ typename enable_if<
+ is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
+ && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
+ >::type*)
{
boost::system::error_code ec;
std::size_t bytes_transferred = read_until(s,
- BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers), delim, ec);
+ BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), delim, ec);
boost::asio::detail::throw_error(ec, "read_until");
return bytes_transferred;
}
-namespace detail
-{
- // Algorithm that finds a subsequence of equal values in a sequence. Returns
- // (iterator,true) if a full match was found, in which case the iterator
- // points to the beginning of the match. Returns (iterator,false) if a
- // partial match was found at the end of the first sequence, in which case
- // the iterator points to the beginning of the partial match. Returns
- // (last1,false) if no full or partial match was found.
- template <typename Iterator1, typename Iterator2>
- std::pair<Iterator1, bool> partial_search(
- Iterator1 first1, Iterator1 last1, Iterator2 first2, Iterator2 last2)
- {
- for (Iterator1 iter1 = first1; iter1 != last1; ++iter1)
- {
- Iterator1 test_iter1 = iter1;
- Iterator2 test_iter2 = first2;
- for (;; ++test_iter1, ++test_iter2)
- {
- if (test_iter2 == last2)
- return std::make_pair(iter1, true);
- if (test_iter1 == last1)
- {
- if (test_iter2 != first2)
- return std::make_pair(iter1, false);
- else
- break;
- }
- if (*test_iter1 != *test_iter2)
- break;
- }
- }
- return std::make_pair(last1, false);
- }
-} // namespace detail
-
-template <typename SyncReadStream, typename DynamicBuffer>
+template <typename SyncReadStream, typename DynamicBuffer_v1>
std::size_t read_until(SyncReadStream& s,
- BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
- BOOST_ASIO_STRING_VIEW_PARAM delim, boost::system::error_code& ec)
+ BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
+ BOOST_ASIO_STRING_VIEW_PARAM delim, boost::system::error_code& ec,
+ typename enable_if<
+ is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
+ && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
+ >::type*)
{
- typename decay<DynamicBuffer>::type b(
- BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers));
+ typename decay<DynamicBuffer_v1>::type b(
+ BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers));
std::size_t search_position = 0;
for (;;)
{
// Determine the range of the data to be searched.
- typedef typename DynamicBuffer::const_buffers_type buffers_type;
+ typedef typename DynamicBuffer_v1::const_buffers_type buffers_type;
typedef buffers_iterator<buffers_type> iterator;
buffers_type data_buffers = b.data();
iterator begin = iterator::begin(data_buffers);
@@ -206,31 +225,39 @@ std::size_t read_until(SyncReadStream& s,
#if !defined(BOOST_ASIO_NO_EXTENSIONS)
#if defined(BOOST_ASIO_HAS_BOOST_REGEX)
-template <typename SyncReadStream, typename DynamicBuffer>
+template <typename SyncReadStream, typename DynamicBuffer_v1>
inline std::size_t read_until(SyncReadStream& s,
- BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
- const boost::regex& expr)
+ BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
+ const boost::regex& expr,
+ typename enable_if<
+ is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
+ && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
+ >::type*)
{
boost::system::error_code ec;
std::size_t bytes_transferred = read_until(s,
- BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers), expr, ec);
+ BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), expr, ec);
boost::asio::detail::throw_error(ec, "read_until");
return bytes_transferred;
}
-template <typename SyncReadStream, typename DynamicBuffer>
+template <typename SyncReadStream, typename DynamicBuffer_v1>
std::size_t read_until(SyncReadStream& s,
- BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
- const boost::regex& expr, boost::system::error_code& ec)
+ BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
+ const boost::regex& expr, boost::system::error_code& ec,
+ typename enable_if<
+ is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
+ && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
+ >::type*)
{
- typename decay<DynamicBuffer>::type b(
- BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers));
+ typename decay<DynamicBuffer_v1>::type b(
+ BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers));
std::size_t search_position = 0;
for (;;)
{
// Determine the range of the data to be searched.
- typedef typename DynamicBuffer::const_buffers_type buffers_type;
+ typedef typename DynamicBuffer_v1::const_buffers_type buffers_type;
typedef buffers_iterator<buffers_type> iterator;
buffers_type data_buffers = b.data();
iterator begin = iterator::begin(data_buffers);
@@ -282,35 +309,43 @@ std::size_t read_until(SyncReadStream& s,
#endif // defined(BOOST_ASIO_HAS_BOOST_REGEX)
template <typename SyncReadStream,
- typename DynamicBuffer, typename MatchCondition>
+ typename DynamicBuffer_v1, typename MatchCondition>
inline std::size_t read_until(SyncReadStream& s,
- BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
+ BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
MatchCondition match_condition,
- typename enable_if<is_match_condition<MatchCondition>::value>::type*)
+ typename enable_if<
+ is_match_condition<MatchCondition>::value
+ && is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
+ && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
+ >::type*)
{
boost::system::error_code ec;
std::size_t bytes_transferred = read_until(s,
- BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers),
+ BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),
match_condition, ec);
boost::asio::detail::throw_error(ec, "read_until");
return bytes_transferred;
}
template <typename SyncReadStream,
- typename DynamicBuffer, typename MatchCondition>
+ typename DynamicBuffer_v1, typename MatchCondition>
std::size_t read_until(SyncReadStream& s,
- BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
+ BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
MatchCondition match_condition, boost::system::error_code& ec,
- typename enable_if<is_match_condition<MatchCondition>::value>::type*)
+ typename enable_if<
+ is_match_condition<MatchCondition>::value
+ && is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
+ && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
+ >::type*)
{
- typename decay<DynamicBuffer>::type b(
- BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers));
+ typename decay<DynamicBuffer_v1>::type b(
+ BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers));
std::size_t search_position = 0;
for (;;)
{
// Determine the range of the data to be searched.
- typedef typename DynamicBuffer::const_buffers_type buffers_type;
+ typedef typename DynamicBuffer_v1::const_buffers_type buffers_type;
typedef buffers_iterator<buffers_type> iterator;
buffers_type data_buffers = b.data();
iterator begin = iterator::begin(data_buffers);
@@ -424,16 +459,332 @@ inline std::size_t read_until(SyncReadStream& s,
#endif // !defined(BOOST_ASIO_NO_IOSTREAM)
#endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
+#endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
+
+template <typename SyncReadStream, typename DynamicBuffer_v2>
+inline std::size_t read_until(SyncReadStream& s,
+ DynamicBuffer_v2 buffers, char delim,
+ typename enable_if<
+ is_dynamic_buffer_v2<DynamicBuffer_v2>::value
+ >::type*)
+{
+ boost::system::error_code ec;
+ std::size_t bytes_transferred = read_until(s,
+ BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), delim, ec);
+ boost::asio::detail::throw_error(ec, "read_until");
+ return bytes_transferred;
+}
+
+template <typename SyncReadStream, typename DynamicBuffer_v2>
+std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers,
+ char delim, boost::system::error_code& ec,
+ typename enable_if<
+ is_dynamic_buffer_v2<DynamicBuffer_v2>::value
+ >::type*)
+{
+ DynamicBuffer_v2& b = buffers;
+
+ std::size_t search_position = 0;
+ for (;;)
+ {
+ // Determine the range of the data to be searched.
+ typedef typename DynamicBuffer_v2::const_buffers_type buffers_type;
+ typedef buffers_iterator<buffers_type> iterator;
+ buffers_type data_buffers =
+ const_cast<const DynamicBuffer_v2&>(b).data(0, b.size());
+ iterator begin = iterator::begin(data_buffers);
+ iterator start_pos = begin + search_position;
+ iterator end = iterator::end(data_buffers);
+
+ // Look for a match.
+ iterator iter = std::find(start_pos, end, delim);
+ if (iter != end)
+ {
+ // Found a match. We're done.
+ ec = boost::system::error_code();
+ return iter - begin + 1;
+ }
+ else
+ {
+ // No match. Next search can start with the new data.
+ search_position = end - begin;
+ }
+
+ // Check if buffer is full.
+ if (b.size() == b.max_size())
+ {
+ ec = error::not_found;
+ return 0;
+ }
+
+ // Need more data.
+ std::size_t bytes_to_read = std::min<std::size_t>(
+ std::max<std::size_t>(512, b.capacity() - b.size()),
+ std::min<std::size_t>(65536, b.max_size() - b.size()));
+ std::size_t pos = b.size();
+ b.grow(bytes_to_read);
+ std::size_t bytes_transferred = s.read_some(b.data(pos, bytes_to_read), ec);
+ b.shrink(bytes_to_read - bytes_transferred);
+ if (ec)
+ return 0;
+ }
+}
+
+template <typename SyncReadStream, typename DynamicBuffer_v2>
+inline std::size_t read_until(SyncReadStream& s,
+ DynamicBuffer_v2 buffers, BOOST_ASIO_STRING_VIEW_PARAM delim,
+ typename enable_if<
+ is_dynamic_buffer_v2<DynamicBuffer_v2>::value
+ >::type*)
+{
+ boost::system::error_code ec;
+ std::size_t bytes_transferred = read_until(s,
+ BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), delim, ec);
+ boost::asio::detail::throw_error(ec, "read_until");
+ return bytes_transferred;
+}
+
+template <typename SyncReadStream, typename DynamicBuffer_v2>
+std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers,
+ BOOST_ASIO_STRING_VIEW_PARAM delim, boost::system::error_code& ec,
+ typename enable_if<
+ is_dynamic_buffer_v2<DynamicBuffer_v2>::value
+ >::type*)
+{
+ DynamicBuffer_v2& b = buffers;
+
+ std::size_t search_position = 0;
+ for (;;)
+ {
+ // Determine the range of the data to be searched.
+ typedef typename DynamicBuffer_v2::const_buffers_type buffers_type;
+ typedef buffers_iterator<buffers_type> iterator;
+ buffers_type data_buffers =
+ const_cast<const DynamicBuffer_v2&>(b).data(0, b.size());
+ iterator begin = iterator::begin(data_buffers);
+ iterator start_pos = begin + search_position;
+ iterator end = iterator::end(data_buffers);
+
+ // Look for a match.
+ std::pair<iterator, bool> result = detail::partial_search(
+ start_pos, end, delim.begin(), delim.end());
+ if (result.first != end)
+ {
+ if (result.second)
+ {
+ // Full match. We're done.
+ ec = boost::system::error_code();
+ return result.first - begin + delim.length();
+ }
+ else
+ {
+ // Partial match. Next search needs to start from beginning of match.
+ search_position = result.first - begin;
+ }
+ }
+ else
+ {
+ // No match. Next search can start with the new data.
+ search_position = end - begin;
+ }
+
+ // Check if buffer is full.
+ if (b.size() == b.max_size())
+ {
+ ec = error::not_found;
+ return 0;
+ }
+
+ // Need more data.
+ std::size_t bytes_to_read = std::min<std::size_t>(
+ std::max<std::size_t>(512, b.capacity() - b.size()),
+ std::min<std::size_t>(65536, b.max_size() - b.size()));
+ std::size_t pos = b.size();
+ b.grow(bytes_to_read);
+ std::size_t bytes_transferred = s.read_some(b.data(pos, bytes_to_read), ec);
+ b.shrink(bytes_to_read - bytes_transferred);
+ if (ec)
+ return 0;
+ }
+}
+
+#if !defined(BOOST_ASIO_NO_EXTENSIONS)
+#if defined(BOOST_ASIO_HAS_BOOST_REGEX)
+
+template <typename SyncReadStream, typename DynamicBuffer_v2>
+inline std::size_t read_until(SyncReadStream& s,
+ DynamicBuffer_v2 buffers, const boost::regex& expr,
+ typename enable_if<
+ is_dynamic_buffer_v2<DynamicBuffer_v2>::value
+ >::type*)
+{
+ boost::system::error_code ec;
+ std::size_t bytes_transferred = read_until(s,
+ BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), expr, ec);
+ boost::asio::detail::throw_error(ec, "read_until");
+ return bytes_transferred;
+}
+
+template <typename SyncReadStream, typename DynamicBuffer_v2>
+std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers,
+ const boost::regex& expr, boost::system::error_code& ec,
+ typename enable_if<
+ is_dynamic_buffer_v2<DynamicBuffer_v2>::value
+ >::type*)
+{
+ DynamicBuffer_v2& b = buffers;
+
+ std::size_t search_position = 0;
+ for (;;)
+ {
+ // Determine the range of the data to be searched.
+ typedef typename DynamicBuffer_v2::const_buffers_type buffers_type;
+ typedef buffers_iterator<buffers_type> iterator;
+ buffers_type data_buffers =
+ const_cast<const DynamicBuffer_v2&>(b).data(0, b.size());
+ iterator begin = iterator::begin(data_buffers);
+ iterator start_pos = begin + search_position;
+ iterator end = iterator::end(data_buffers);
+
+ // Look for a match.
+ boost::match_results<iterator,
+ typename std::vector<boost::sub_match<iterator> >::allocator_type>
+ match_results;
+ if (regex_search(start_pos, end, match_results, expr,
+ boost::match_default | boost::match_partial))
+ {
+ if (match_results[0].matched)
+ {
+ // Full match. We're done.
+ ec = boost::system::error_code();
+ return match_results[0].second - begin;
+ }
+ else
+ {
+ // Partial match. Next search needs to start from beginning of match.
+ search_position = match_results[0].first - begin;
+ }
+ }
+ else
+ {
+ // No match. Next search can start with the new data.
+ search_position = end - begin;
+ }
+
+ // Check if buffer is full.
+ if (b.size() == b.max_size())
+ {
+ ec = error::not_found;
+ return 0;
+ }
+
+ // Need more data.
+ std::size_t bytes_to_read = std::min<std::size_t>(
+ std::max<std::size_t>(512, b.capacity() - b.size()),
+ std::min<std::size_t>(65536, b.max_size() - b.size()));
+ std::size_t pos = b.size();
+ b.grow(bytes_to_read);
+ std::size_t bytes_transferred = s.read_some(b.data(pos, bytes_to_read), ec);
+ b.shrink(bytes_to_read - bytes_transferred);
+ if (ec)
+ return 0;
+ }
+}
+
+#endif // defined(BOOST_ASIO_HAS_BOOST_REGEX)
+
+template <typename SyncReadStream,
+ typename DynamicBuffer_v2, typename MatchCondition>
+inline std::size_t read_until(SyncReadStream& s,
+ DynamicBuffer_v2 buffers, MatchCondition match_condition,
+ typename enable_if<
+ is_match_condition<MatchCondition>::value
+ && is_dynamic_buffer_v2<DynamicBuffer_v2>::value
+ >::type*)
+{
+ boost::system::error_code ec;
+ std::size_t bytes_transferred = read_until(s,
+ BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),
+ match_condition, ec);
+ boost::asio::detail::throw_error(ec, "read_until");
+ return bytes_transferred;
+}
+
+template <typename SyncReadStream,
+ typename DynamicBuffer_v2, typename MatchCondition>
+std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers,
+ MatchCondition match_condition, boost::system::error_code& ec,
+ typename enable_if<
+ is_match_condition<MatchCondition>::value
+ && is_dynamic_buffer_v2<DynamicBuffer_v2>::value
+ >::type*)
+{
+ DynamicBuffer_v2& b = buffers;
+
+ std::size_t search_position = 0;
+ for (;;)
+ {
+ // Determine the range of the data to be searched.
+ typedef typename DynamicBuffer_v2::const_buffers_type buffers_type;
+ typedef buffers_iterator<buffers_type> iterator;
+ buffers_type data_buffers =
+ const_cast<const DynamicBuffer_v2&>(b).data(0, b.size());
+ iterator begin = iterator::begin(data_buffers);
+ iterator start_pos = begin + search_position;
+ iterator end = iterator::end(data_buffers);
+
+ // Look for a match.
+ std::pair<iterator, bool> result = match_condition(start_pos, end);
+ if (result.second)
+ {
+ // Full match. We're done.
+ ec = boost::system::error_code();
+ return result.first - begin;
+ }
+ else if (result.first != end)
+ {
+ // Partial match. Next search needs to start from beginning of match.
+ search_position = result.first - begin;
+ }
+ else
+ {
+ // No match. Next search can start with the new data.
+ search_position = end - begin;
+ }
+
+ // Check if buffer is full.
+ if (b.size() == b.max_size())
+ {
+ ec = error::not_found;
+ return 0;
+ }
+
+ // Need more data.
+ std::size_t bytes_to_read = std::min<std::size_t>(
+ std::max<std::size_t>(512, b.capacity() - b.size()),
+ std::min<std::size_t>(65536, b.max_size() - b.size()));
+ std::size_t pos = b.size();
+ b.grow(bytes_to_read);
+ std::size_t bytes_transferred = s.read_some(b.data(pos, bytes_to_read), ec);
+ b.shrink(bytes_to_read - bytes_transferred);
+ if (ec)
+ return 0;
+ }
+}
+
+#endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
+
+#if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
namespace detail
{
template <typename AsyncReadStream,
- typename DynamicBuffer, typename ReadHandler>
- class read_until_delim_op
+ typename DynamicBuffer_v1, typename ReadHandler>
+ class read_until_delim_op_v1
{
public:
template <typename BufferSequence>
- read_until_delim_op(AsyncReadStream& stream,
+ read_until_delim_op_v1(AsyncReadStream& stream,
BOOST_ASIO_MOVE_ARG(BufferSequence) buffers,
char delim, ReadHandler& handler)
: stream_(stream),
@@ -446,7 +797,7 @@ namespace detail
}
#if defined(BOOST_ASIO_HAS_MOVE)
- read_until_delim_op(const read_until_delim_op& other)
+ read_until_delim_op_v1(const read_until_delim_op_v1& other)
: stream_(other.stream_),
buffers_(other.buffers_),
delim_(other.delim_),
@@ -456,9 +807,9 @@ namespace detail
{
}
- read_until_delim_op(read_until_delim_op&& other)
+ read_until_delim_op_v1(read_until_delim_op_v1&& other)
: stream_(other.stream_),
- buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer)(other.buffers_)),
+ buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(other.buffers_)),
delim_(other.delim_),
start_(other.start_),
search_position_(other.search_position_),
@@ -479,7 +830,7 @@ namespace detail
{
{
// Determine the range of the data to be searched.
- typedef typename DynamicBuffer::const_buffers_type
+ typedef typename DynamicBuffer_v1::const_buffers_type
buffers_type;
typedef buffers_iterator<buffers_type> iterator;
buffers_type data_buffers = buffers_.data();
@@ -520,9 +871,9 @@ namespace detail
if (!start && bytes_to_read == 0)
break;
- // Start a new asynchronous read operation to obtain more data.
+ // Start a new asynchronous read op_v1eration to obtain more data.
stream_.async_read_some(buffers_.prepare(bytes_to_read),
- BOOST_ASIO_MOVE_CAST(read_until_delim_op)(*this));
+ BOOST_ASIO_MOVE_CAST(read_until_delim_op_v1)(*this));
return; default:
buffers_.commit(bytes_transferred);
if (ec || bytes_transferred == 0)
@@ -543,7 +894,7 @@ namespace detail
//private:
AsyncReadStream& stream_;
- DynamicBuffer buffers_;
+ DynamicBuffer_v1 buffers_;
char delim_;
int start_;
std::size_t search_position_;
@@ -551,30 +902,30 @@ namespace detail
};
template <typename AsyncReadStream,
- typename DynamicBuffer, typename ReadHandler>
+ typename DynamicBuffer_v1, typename ReadHandler>
inline void* asio_handler_allocate(std::size_t size,
- read_until_delim_op<AsyncReadStream,
- DynamicBuffer, ReadHandler>* this_handler)
+ read_until_delim_op_v1<AsyncReadStream,
+ DynamicBuffer_v1, ReadHandler>* this_handler)
{
return boost_asio_handler_alloc_helpers::allocate(
size, this_handler->handler_);
}
template <typename AsyncReadStream,
- typename DynamicBuffer, typename ReadHandler>
+ typename DynamicBuffer_v1, typename ReadHandler>
inline void asio_handler_deallocate(void* pointer, std::size_t size,
- read_until_delim_op<AsyncReadStream,
- DynamicBuffer, ReadHandler>* this_handler)
+ read_until_delim_op_v1<AsyncReadStream,
+ DynamicBuffer_v1, ReadHandler>* this_handler)
{
boost_asio_handler_alloc_helpers::deallocate(
pointer, size, this_handler->handler_);
}
template <typename AsyncReadStream,
- typename DynamicBuffer, typename ReadHandler>
+ typename DynamicBuffer_v1, typename ReadHandler>
inline bool asio_handler_is_continuation(
- read_until_delim_op<AsyncReadStream,
- DynamicBuffer, ReadHandler>* this_handler)
+ read_until_delim_op_v1<AsyncReadStream,
+ DynamicBuffer_v1, ReadHandler>* this_handler)
{
return this_handler->start_ == 0 ? true
: boost_asio_handler_cont_helpers::is_continuation(
@@ -582,58 +933,79 @@ namespace detail
}
template <typename Function, typename AsyncReadStream,
- typename DynamicBuffer, typename ReadHandler>
+ typename DynamicBuffer_v1, typename ReadHandler>
inline void asio_handler_invoke(Function& function,
- read_until_delim_op<AsyncReadStream,
- DynamicBuffer, ReadHandler>* this_handler)
+ read_until_delim_op_v1<AsyncReadStream,
+ DynamicBuffer_v1, ReadHandler>* this_handler)
{
boost_asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
}
template <typename Function, typename AsyncReadStream,
- typename DynamicBuffer, typename ReadHandler>
+ typename DynamicBuffer_v1, typename ReadHandler>
inline void asio_handler_invoke(const Function& function,
- read_until_delim_op<AsyncReadStream,
- DynamicBuffer, ReadHandler>* this_handler)
+ read_until_delim_op_v1<AsyncReadStream,
+ DynamicBuffer_v1, ReadHandler>* this_handler)
{
boost_asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
}
+
+ struct initiate_async_read_until_delim_v1
+ {
+ template <typename ReadHandler, typename AsyncReadStream,
+ typename DynamicBuffer_v1>
+ void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
+ AsyncReadStream* s, BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
+ char delim) const
+ {
+ // If you get an error on the following line it means that your handler
+ // does not meet the documented type requirements for a ReadHandler.
+ BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
+
+ non_const_lvalue<ReadHandler> handler2(handler);
+ read_until_delim_op_v1<AsyncReadStream,
+ typename decay<DynamicBuffer_v1>::type,
+ typename decay<ReadHandler>::type>(
+ *s, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),
+ delim, handler2.value)(boost::system::error_code(), 0, 1);
+ }
+ };
} // namespace detail
#if !defined(GENERATING_DOCUMENTATION)
-template <typename AsyncReadStream, typename DynamicBuffer,
+template <typename AsyncReadStream, typename DynamicBuffer_v1,
typename ReadHandler, typename Allocator>
struct associated_allocator<
- detail::read_until_delim_op<AsyncReadStream,
- DynamicBuffer, ReadHandler>,
+ detail::read_until_delim_op_v1<AsyncReadStream,
+ DynamicBuffer_v1, ReadHandler>,
Allocator>
{
typedef typename associated_allocator<ReadHandler, Allocator>::type type;
static type get(
- const detail::read_until_delim_op<AsyncReadStream,
- DynamicBuffer, ReadHandler>& h,
+ const detail::read_until_delim_op_v1<AsyncReadStream,
+ DynamicBuffer_v1, ReadHandler>& h,
const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
{
return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);
}
};
-template <typename AsyncReadStream, typename DynamicBuffer,
+template <typename AsyncReadStream, typename DynamicBuffer_v1,
typename ReadHandler, typename Executor>
struct associated_executor<
- detail::read_until_delim_op<AsyncReadStream,
- DynamicBuffer, ReadHandler>,
+ detail::read_until_delim_op_v1<AsyncReadStream,
+ DynamicBuffer_v1, ReadHandler>,
Executor>
{
typedef typename associated_executor<ReadHandler, Executor>::type type;
static type get(
- const detail::read_until_delim_op<AsyncReadStream,
- DynamicBuffer, ReadHandler>& h,
+ const detail::read_until_delim_op_v1<AsyncReadStream,
+ DynamicBuffer_v1, ReadHandler>& h,
const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
{
return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);
@@ -643,39 +1015,32 @@ struct associated_executor<
#endif // !defined(GENERATING_DOCUMENTATION)
template <typename AsyncReadStream,
- typename DynamicBuffer, typename ReadHandler>
+ typename DynamicBuffer_v1, typename ReadHandler>
BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
void (boost::system::error_code, std::size_t))
async_read_until(AsyncReadStream& s,
- BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
- char delim, BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
+ BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
+ char delim, BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
+ typename enable_if<
+ is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
+ && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
+ >::type*)
{
- // If you get an error on the following line it means that your handler does
- // not meet the documented type requirements for a ReadHandler.
- BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
-
- async_completion<ReadHandler,
- void (boost::system::error_code, std::size_t)> init(handler);
-
- detail::read_until_delim_op<AsyncReadStream,
- typename decay<DynamicBuffer>::type,
- BOOST_ASIO_HANDLER_TYPE(ReadHandler,
- void (boost::system::error_code, std::size_t))>(
- s, BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers),
- delim, init.completion_handler)(boost::system::error_code(), 0, 1);
-
- return init.result.get();
+ return async_initiate<ReadHandler,
+ void (boost::system::error_code, std::size_t)>(
+ detail::initiate_async_read_until_delim_v1(), handler,
+ &s, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), delim);
}
namespace detail
{
template <typename AsyncReadStream,
- typename DynamicBuffer, typename ReadHandler>
- class read_until_delim_string_op
+ typename DynamicBuffer_v1, typename ReadHandler>
+ class read_until_delim_string_op_v1
{
public:
template <typename BufferSequence>
- read_until_delim_string_op(AsyncReadStream& stream,
+ read_until_delim_string_op_v1(AsyncReadStream& stream,
BOOST_ASIO_MOVE_ARG(BufferSequence) buffers,
const std::string& delim, ReadHandler& handler)
: stream_(stream),
@@ -688,7 +1053,7 @@ namespace detail
}
#if defined(BOOST_ASIO_HAS_MOVE)
- read_until_delim_string_op(const read_until_delim_string_op& other)
+ read_until_delim_string_op_v1(const read_until_delim_string_op_v1& other)
: stream_(other.stream_),
buffers_(other.buffers_),
delim_(other.delim_),
@@ -698,9 +1063,9 @@ namespace detail
{
}
- read_until_delim_string_op(read_until_delim_string_op&& other)
+ read_until_delim_string_op_v1(read_until_delim_string_op_v1&& other)
: stream_(other.stream_),
- buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer)(other.buffers_)),
+ buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(other.buffers_)),
delim_(BOOST_ASIO_MOVE_CAST(std::string)(other.delim_)),
start_(other.start_),
search_position_(other.search_position_),
@@ -721,7 +1086,7 @@ namespace detail
{
{
// Determine the range of the data to be searched.
- typedef typename DynamicBuffer::const_buffers_type
+ typedef typename DynamicBuffer_v1::const_buffers_type
buffers_type;
typedef buffers_iterator<buffers_type> iterator;
buffers_type data_buffers = buffers_.data();
@@ -773,9 +1138,9 @@ namespace detail
if (!start && bytes_to_read == 0)
break;
- // Start a new asynchronous read operation to obtain more data.
+ // Start a new asynchronous read op_v1eration to obtain more data.
stream_.async_read_some(buffers_.prepare(bytes_to_read),
- BOOST_ASIO_MOVE_CAST(read_until_delim_string_op)(*this));
+ BOOST_ASIO_MOVE_CAST(read_until_delim_string_op_v1)(*this));
return; default:
buffers_.commit(bytes_transferred);
if (ec || bytes_transferred == 0)
@@ -796,7 +1161,7 @@ namespace detail
//private:
AsyncReadStream& stream_;
- DynamicBuffer buffers_;
+ DynamicBuffer_v1 buffers_;
std::string delim_;
int start_;
std::size_t search_position_;
@@ -804,30 +1169,30 @@ namespace detail
};
template <typename AsyncReadStream,
- typename DynamicBuffer, typename ReadHandler>
+ typename DynamicBuffer_v1, typename ReadHandler>
inline void* asio_handler_allocate(std::size_t size,
- read_until_delim_string_op<AsyncReadStream,
- DynamicBuffer, ReadHandler>* this_handler)
+ read_until_delim_string_op_v1<AsyncReadStream,
+ DynamicBuffer_v1, ReadHandler>* this_handler)
{
return boost_asio_handler_alloc_helpers::allocate(
size, this_handler->handler_);
}
template <typename AsyncReadStream,
- typename DynamicBuffer, typename ReadHandler>
+ typename DynamicBuffer_v1, typename ReadHandler>
inline void asio_handler_deallocate(void* pointer, std::size_t size,
- read_until_delim_string_op<AsyncReadStream,
- DynamicBuffer, ReadHandler>* this_handler)
+ read_until_delim_string_op_v1<AsyncReadStream,
+ DynamicBuffer_v1, ReadHandler>* this_handler)
{
boost_asio_handler_alloc_helpers::deallocate(
pointer, size, this_handler->handler_);
}
template <typename AsyncReadStream,
- typename DynamicBuffer, typename ReadHandler>
+ typename DynamicBuffer_v1, typename ReadHandler>
inline bool asio_handler_is_continuation(
- read_until_delim_string_op<AsyncReadStream,
- DynamicBuffer, ReadHandler>* this_handler)
+ read_until_delim_string_op_v1<AsyncReadStream,
+ DynamicBuffer_v1, ReadHandler>* this_handler)
{
return this_handler->start_ == 0 ? true
: boost_asio_handler_cont_helpers::is_continuation(
@@ -835,58 +1200,79 @@ namespace detail
}
template <typename Function, typename AsyncReadStream,
- typename DynamicBuffer, typename ReadHandler>
+ typename DynamicBuffer_v1, typename ReadHandler>
inline void asio_handler_invoke(Function& function,
- read_until_delim_string_op<AsyncReadStream,
- DynamicBuffer, ReadHandler>* this_handler)
+ read_until_delim_string_op_v1<AsyncReadStream,
+ DynamicBuffer_v1, ReadHandler>* this_handler)
{
boost_asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
}
template <typename Function, typename AsyncReadStream,
- typename DynamicBuffer, typename ReadHandler>
+ typename DynamicBuffer_v1, typename ReadHandler>
inline void asio_handler_invoke(const Function& function,
- read_until_delim_string_op<AsyncReadStream,
- DynamicBuffer, ReadHandler>* this_handler)
+ read_until_delim_string_op_v1<AsyncReadStream,
+ DynamicBuffer_v1, ReadHandler>* this_handler)
{
boost_asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
}
+
+ struct initiate_async_read_until_delim_string_v1
+ {
+ template <typename ReadHandler, typename AsyncReadStream,
+ typename DynamicBuffer_v1>
+ void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
+ AsyncReadStream* s, BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
+ const std::string& delim) const
+ {
+ // If you get an error on the following line it means that your handler
+ // does not meet the documented type requirements for a ReadHandler.
+ BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
+
+ non_const_lvalue<ReadHandler> handler2(handler);
+ read_until_delim_string_op_v1<AsyncReadStream,
+ typename decay<DynamicBuffer_v1>::type,
+ typename decay<ReadHandler>::type>(
+ *s, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),
+ delim, handler2.value)(boost::system::error_code(), 0, 1);
+ }
+ };
} // namespace detail
#if !defined(GENERATING_DOCUMENTATION)
-template <typename AsyncReadStream, typename DynamicBuffer,
+template <typename AsyncReadStream, typename DynamicBuffer_v1,
typename ReadHandler, typename Allocator>
struct associated_allocator<
- detail::read_until_delim_string_op<AsyncReadStream,
- DynamicBuffer, ReadHandler>,
+ detail::read_until_delim_string_op_v1<AsyncReadStream,
+ DynamicBuffer_v1, ReadHandler>,
Allocator>
{
typedef typename associated_allocator<ReadHandler, Allocator>::type type;
static type get(
- const detail::read_until_delim_string_op<AsyncReadStream,
- DynamicBuffer, ReadHandler>& h,
+ const detail::read_until_delim_string_op_v1<AsyncReadStream,
+ DynamicBuffer_v1, ReadHandler>& h,
const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
{
return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);
}
};
-template <typename AsyncReadStream, typename DynamicBuffer,
+template <typename AsyncReadStream, typename DynamicBuffer_v1,
typename ReadHandler, typename Executor>
struct associated_executor<
- detail::read_until_delim_string_op<AsyncReadStream,
- DynamicBuffer, ReadHandler>,
+ detail::read_until_delim_string_op_v1<AsyncReadStream,
+ DynamicBuffer_v1, ReadHandler>,
Executor>
{
typedef typename associated_executor<ReadHandler, Executor>::type type;
static type get(
- const detail::read_until_delim_string_op<AsyncReadStream,
- DynamicBuffer, ReadHandler>& h,
+ const detail::read_until_delim_string_op_v1<AsyncReadStream,
+ DynamicBuffer_v1, ReadHandler>& h,
const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
{
return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);
@@ -896,30 +1282,23 @@ struct associated_executor<
#endif // !defined(GENERATING_DOCUMENTATION)
template <typename AsyncReadStream,
- typename DynamicBuffer, typename ReadHandler>
+ typename DynamicBuffer_v1, typename ReadHandler>
BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
void (boost::system::error_code, std::size_t))
async_read_until(AsyncReadStream& s,
- BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
+ BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
BOOST_ASIO_STRING_VIEW_PARAM delim,
- BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
+ BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
+ typename enable_if<
+ is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
+ && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
+ >::type*)
{
- // If you get an error on the following line it means that your handler does
- // not meet the documented type requirements for a ReadHandler.
- BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
-
- async_completion<ReadHandler,
- void (boost::system::error_code, std::size_t)> init(handler);
-
- detail::read_until_delim_string_op<AsyncReadStream,
- typename decay<DynamicBuffer>::type,
- BOOST_ASIO_HANDLER_TYPE(ReadHandler,
- void (boost::system::error_code, std::size_t))>(
- s, BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers),
- static_cast<std::string>(delim),
- init.completion_handler)(boost::system::error_code(), 0, 1);
-
- return init.result.get();
+ return async_initiate<ReadHandler,
+ void (boost::system::error_code, std::size_t)>(
+ detail::initiate_async_read_until_delim_string_v1(),
+ handler, &s, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),
+ static_cast<std::string>(delim));
}
#if !defined(BOOST_ASIO_NO_EXTENSIONS)
@@ -927,13 +1306,13 @@ async_read_until(AsyncReadStream& s,
namespace detail
{
- template <typename AsyncReadStream, typename DynamicBuffer,
+ template <typename AsyncReadStream, typename DynamicBuffer_v1,
typename RegEx, typename ReadHandler>
- class read_until_expr_op
+ class read_until_expr_op_v1
{
public:
template <typename BufferSequence>
- read_until_expr_op(AsyncReadStream& stream,
+ read_until_expr_op_v1(AsyncReadStream& stream,
BOOST_ASIO_MOVE_ARG(BufferSequence) buffers,
const boost::regex& expr, ReadHandler& handler)
: stream_(stream),
@@ -946,7 +1325,7 @@ namespace detail
}
#if defined(BOOST_ASIO_HAS_MOVE)
- read_until_expr_op(const read_until_expr_op& other)
+ read_until_expr_op_v1(const read_until_expr_op_v1& other)
: stream_(other.stream_),
buffers_(other.buffers_),
expr_(other.expr_),
@@ -956,9 +1335,9 @@ namespace detail
{
}
- read_until_expr_op(read_until_expr_op&& other)
+ read_until_expr_op_v1(read_until_expr_op_v1&& other)
: stream_(other.stream_),
- buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer)(other.buffers_)),
+ buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(other.buffers_)),
expr_(other.expr_),
start_(other.start_),
search_position_(other.search_position_),
@@ -979,7 +1358,7 @@ namespace detail
{
{
// Determine the range of the data to be searched.
- typedef typename DynamicBuffer::const_buffers_type
+ typedef typename DynamicBuffer_v1::const_buffers_type
buffers_type;
typedef buffers_iterator<buffers_type> iterator;
buffers_type data_buffers = buffers_.data();
@@ -1034,9 +1413,9 @@ namespace detail
if (!start && bytes_to_read == 0)
break;
- // Start a new asynchronous read operation to obtain more data.
+ // Start a new asynchronous read op_v1eration to obtain more data.
stream_.async_read_some(buffers_.prepare(bytes_to_read),
- BOOST_ASIO_MOVE_CAST(read_until_expr_op)(*this));
+ BOOST_ASIO_MOVE_CAST(read_until_expr_op_v1)(*this));
return; default:
buffers_.commit(bytes_transferred);
if (ec || bytes_transferred == 0)
@@ -1057,38 +1436,38 @@ namespace detail
//private:
AsyncReadStream& stream_;
- DynamicBuffer buffers_;
+ DynamicBuffer_v1 buffers_;
RegEx expr_;
int start_;
std::size_t search_position_;
ReadHandler handler_;
};
- template <typename AsyncReadStream, typename DynamicBuffer,
+ template <typename AsyncReadStream, typename DynamicBuffer_v1,
typename RegEx, typename ReadHandler>
inline void* asio_handler_allocate(std::size_t size,
- read_until_expr_op<AsyncReadStream,
- DynamicBuffer, RegEx, ReadHandler>* this_handler)
+ read_until_expr_op_v1<AsyncReadStream,
+ DynamicBuffer_v1, RegEx, ReadHandler>* this_handler)
{
return boost_asio_handler_alloc_helpers::allocate(
size, this_handler->handler_);
}
- template <typename AsyncReadStream, typename DynamicBuffer,
+ template <typename AsyncReadStream, typename DynamicBuffer_v1,
typename RegEx, typename ReadHandler>
inline void asio_handler_deallocate(void* pointer, std::size_t size,
- read_until_expr_op<AsyncReadStream,
- DynamicBuffer, RegEx, ReadHandler>* this_handler)
+ read_until_expr_op_v1<AsyncReadStream,
+ DynamicBuffer_v1, RegEx, ReadHandler>* this_handler)
{
boost_asio_handler_alloc_helpers::deallocate(
pointer, size, this_handler->handler_);
}
- template <typename AsyncReadStream, typename DynamicBuffer,
+ template <typename AsyncReadStream, typename DynamicBuffer_v1,
typename RegEx, typename ReadHandler>
inline bool asio_handler_is_continuation(
- read_until_expr_op<AsyncReadStream,
- DynamicBuffer, RegEx, ReadHandler>* this_handler)
+ read_until_expr_op_v1<AsyncReadStream,
+ DynamicBuffer_v1, RegEx, ReadHandler>* this_handler)
{
return this_handler->start_ == 0 ? true
: boost_asio_handler_cont_helpers::is_continuation(
@@ -1096,58 +1475,79 @@ namespace detail
}
template <typename Function, typename AsyncReadStream,
- typename DynamicBuffer, typename RegEx, typename ReadHandler>
+ typename DynamicBuffer_v1, typename RegEx, typename ReadHandler>
inline void asio_handler_invoke(Function& function,
- read_until_expr_op<AsyncReadStream,
- DynamicBuffer, RegEx, ReadHandler>* this_handler)
+ read_until_expr_op_v1<AsyncReadStream,
+ DynamicBuffer_v1, RegEx, ReadHandler>* this_handler)
{
boost_asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
}
template <typename Function, typename AsyncReadStream,
- typename DynamicBuffer, typename RegEx, typename ReadHandler>
+ typename DynamicBuffer_v1, typename RegEx, typename ReadHandler>
inline void asio_handler_invoke(const Function& function,
- read_until_expr_op<AsyncReadStream,
- DynamicBuffer, RegEx, ReadHandler>* this_handler)
+ read_until_expr_op_v1<AsyncReadStream,
+ DynamicBuffer_v1, RegEx, ReadHandler>* this_handler)
{
boost_asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
}
+
+ struct initiate_async_read_until_expr_v1
+ {
+ template <typename ReadHandler, typename AsyncReadStream,
+ typename DynamicBuffer_v1, typename RegEx>
+ void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
+ AsyncReadStream* s, BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
+ const RegEx& expr) const
+ {
+ // If you get an error on the following line it means that your handler
+ // does not meet the documented type requirements for a ReadHandler.
+ BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
+
+ non_const_lvalue<ReadHandler> handler2(handler);
+ read_until_expr_op_v1<AsyncReadStream,
+ typename decay<DynamicBuffer_v1>::type,
+ RegEx, typename decay<ReadHandler>::type>(
+ *s, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),
+ expr, handler2.value)(boost::system::error_code(), 0, 1);
+ }
+ };
} // namespace detail
#if !defined(GENERATING_DOCUMENTATION)
-template <typename AsyncReadStream, typename DynamicBuffer,
+template <typename AsyncReadStream, typename DynamicBuffer_v1,
typename RegEx, typename ReadHandler, typename Allocator>
struct associated_allocator<
- detail::read_until_expr_op<AsyncReadStream,
- DynamicBuffer, RegEx, ReadHandler>,
+ detail::read_until_expr_op_v1<AsyncReadStream,
+ DynamicBuffer_v1, RegEx, ReadHandler>,
Allocator>
{
typedef typename associated_allocator<ReadHandler, Allocator>::type type;
static type get(
- const detail::read_until_expr_op<AsyncReadStream,
- DynamicBuffer, RegEx, ReadHandler>& h,
+ const detail::read_until_expr_op_v1<AsyncReadStream,
+ DynamicBuffer_v1, RegEx, ReadHandler>& h,
const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
{
return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);
}
};
-template <typename AsyncReadStream, typename DynamicBuffer,
+template <typename AsyncReadStream, typename DynamicBuffer_v1,
typename RegEx, typename ReadHandler, typename Executor>
struct associated_executor<
- detail::read_until_expr_op<AsyncReadStream,
- DynamicBuffer, RegEx, ReadHandler>,
+ detail::read_until_expr_op_v1<AsyncReadStream,
+ DynamicBuffer_v1, RegEx, ReadHandler>,
Executor>
{
typedef typename associated_executor<ReadHandler, Executor>::type type;
static type get(
- const detail::read_until_expr_op<AsyncReadStream,
- DynamicBuffer, RegEx, ReadHandler>& h,
+ const detail::read_until_expr_op_v1<AsyncReadStream,
+ DynamicBuffer_v1, RegEx, ReadHandler>& h,
const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
{
return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);
@@ -1157,42 +1557,35 @@ struct associated_executor<
#endif // !defined(GENERATING_DOCUMENTATION)
template <typename AsyncReadStream,
- typename DynamicBuffer, typename ReadHandler>
+ typename DynamicBuffer_v1, typename ReadHandler>
BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
void (boost::system::error_code, std::size_t))
async_read_until(AsyncReadStream& s,
- BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
+ BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
const boost::regex& expr,
- BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
+ BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
+ typename enable_if<
+ is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
+ && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
+ >::type*)
{
- // If you get an error on the following line it means that your handler does
- // not meet the documented type requirements for a ReadHandler.
- BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
-
- async_completion<ReadHandler,
- void (boost::system::error_code, std::size_t)> init(handler);
-
- detail::read_until_expr_op<AsyncReadStream,
- typename decay<DynamicBuffer>::type,
- boost::regex, BOOST_ASIO_HANDLER_TYPE(ReadHandler,
- void (boost::system::error_code, std::size_t))>(
- s, BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers),
- expr, init.completion_handler)(boost::system::error_code(), 0, 1);
-
- return init.result.get();
+ return async_initiate<ReadHandler,
+ void (boost::system::error_code, std::size_t)>(
+ detail::initiate_async_read_until_expr_v1(), handler,
+ &s, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), expr);
}
#endif // defined(BOOST_ASIO_HAS_BOOST_REGEX)
namespace detail
{
- template <typename AsyncReadStream, typename DynamicBuffer,
+ template <typename AsyncReadStream, typename DynamicBuffer_v1,
typename MatchCondition, typename ReadHandler>
- class read_until_match_op
+ class read_until_match_op_v1
{
public:
template <typename BufferSequence>
- read_until_match_op(AsyncReadStream& stream,
+ read_until_match_op_v1(AsyncReadStream& stream,
BOOST_ASIO_MOVE_ARG(BufferSequence) buffers,
MatchCondition match_condition, ReadHandler& handler)
: stream_(stream),
@@ -1205,7 +1598,7 @@ namespace detail
}
#if defined(BOOST_ASIO_HAS_MOVE)
- read_until_match_op(const read_until_match_op& other)
+ read_until_match_op_v1(const read_until_match_op_v1& other)
: stream_(other.stream_),
buffers_(other.buffers_),
match_condition_(other.match_condition_),
@@ -1215,9 +1608,9 @@ namespace detail
{
}
- read_until_match_op(read_until_match_op&& other)
+ read_until_match_op_v1(read_until_match_op_v1&& other)
: stream_(other.stream_),
- buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer)(other.buffers_)),
+ buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(other.buffers_)),
match_condition_(other.match_condition_),
start_(other.start_),
search_position_(other.search_position_),
@@ -1238,7 +1631,7 @@ namespace detail
{
{
// Determine the range of the data to be searched.
- typedef typename DynamicBuffer::const_buffers_type
+ typedef typename DynamicBuffer_v1::const_buffers_type
buffers_type;
typedef buffers_iterator<buffers_type> iterator;
buffers_type data_buffers = buffers_.data();
@@ -1289,9 +1682,9 @@ namespace detail
if (!start && bytes_to_read == 0)
break;
- // Start a new asynchronous read operation to obtain more data.
+ // Start a new asynchronous read op_v1eration to obtain more data.
stream_.async_read_some(buffers_.prepare(bytes_to_read),
- BOOST_ASIO_MOVE_CAST(read_until_match_op)(*this));
+ BOOST_ASIO_MOVE_CAST(read_until_match_op_v1)(*this));
return; default:
buffers_.commit(bytes_transferred);
if (ec || bytes_transferred == 0)
@@ -1312,37 +1705,37 @@ namespace detail
//private:
AsyncReadStream& stream_;
- DynamicBuffer buffers_;
+ DynamicBuffer_v1 buffers_;
MatchCondition match_condition_;
int start_;
std::size_t search_position_;
ReadHandler handler_;
};
- template <typename AsyncReadStream, typename DynamicBuffer,
+ template <typename AsyncReadStream, typename DynamicBuffer_v1,
typename MatchCondition, typename ReadHandler>
inline void* asio_handler_allocate(std::size_t size,
- read_until_match_op<AsyncReadStream, DynamicBuffer,
+ read_until_match_op_v1<AsyncReadStream, DynamicBuffer_v1,
MatchCondition, ReadHandler>* this_handler)
{
return boost_asio_handler_alloc_helpers::allocate(
size, this_handler->handler_);
}
- template <typename AsyncReadStream, typename DynamicBuffer,
+ template <typename AsyncReadStream, typename DynamicBuffer_v1,
typename MatchCondition, typename ReadHandler>
inline void asio_handler_deallocate(void* pointer, std::size_t size,
- read_until_match_op<AsyncReadStream, DynamicBuffer,
+ read_until_match_op_v1<AsyncReadStream, DynamicBuffer_v1,
MatchCondition, ReadHandler>* this_handler)
{
boost_asio_handler_alloc_helpers::deallocate(
pointer, size, this_handler->handler_);
}
- template <typename AsyncReadStream, typename DynamicBuffer,
+ template <typename AsyncReadStream, typename DynamicBuffer_v1,
typename MatchCondition, typename ReadHandler>
inline bool asio_handler_is_continuation(
- read_until_match_op<AsyncReadStream, DynamicBuffer,
+ read_until_match_op_v1<AsyncReadStream, DynamicBuffer_v1,
MatchCondition, ReadHandler>* this_handler)
{
return this_handler->start_ == 0 ? true
@@ -1351,10 +1744,10 @@ namespace detail
}
template <typename Function, typename AsyncReadStream,
- typename DynamicBuffer, typename MatchCondition,
+ typename DynamicBuffer_v1, typename MatchCondition,
typename ReadHandler>
inline void asio_handler_invoke(Function& function,
- read_until_match_op<AsyncReadStream, DynamicBuffer,
+ read_until_match_op_v1<AsyncReadStream, DynamicBuffer_v1,
MatchCondition, ReadHandler>* this_handler)
{
boost_asio_handler_invoke_helpers::invoke(
@@ -1362,49 +1755,70 @@ namespace detail
}
template <typename Function, typename AsyncReadStream,
- typename DynamicBuffer, typename MatchCondition,
+ typename DynamicBuffer_v1, typename MatchCondition,
typename ReadHandler>
inline void asio_handler_invoke(const Function& function,
- read_until_match_op<AsyncReadStream, DynamicBuffer,
+ read_until_match_op_v1<AsyncReadStream, DynamicBuffer_v1,
MatchCondition, ReadHandler>* this_handler)
{
boost_asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
}
+
+ struct initiate_async_read_until_match_v1
+ {
+ template <typename ReadHandler, typename AsyncReadStream,
+ typename DynamicBuffer_v1, typename MatchCondition>
+ void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
+ AsyncReadStream* s, BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
+ MatchCondition match_condition) const
+ {
+ // If you get an error on the following line it means that your handler
+ // does not meet the documented type requirements for a ReadHandler.
+ BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
+
+ non_const_lvalue<ReadHandler> handler2(handler);
+ read_until_match_op_v1<AsyncReadStream,
+ typename decay<DynamicBuffer_v1>::type,
+ MatchCondition, typename decay<ReadHandler>::type>(
+ *s, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),
+ match_condition, handler2.value)(boost::system::error_code(), 0, 1);
+ }
+ };
} // namespace detail
#if !defined(GENERATING_DOCUMENTATION)
-template <typename AsyncReadStream, typename DynamicBuffer,
+template <typename AsyncReadStream, typename DynamicBuffer_v1,
typename MatchCondition, typename ReadHandler, typename Allocator>
struct associated_allocator<
- detail::read_until_match_op<AsyncReadStream,
- DynamicBuffer, MatchCondition, ReadHandler>,
+ detail::read_until_match_op_v1<AsyncReadStream,
+ DynamicBuffer_v1, MatchCondition, ReadHandler>,
Allocator>
{
typedef typename associated_allocator<ReadHandler, Allocator>::type type;
static type get(
- const detail::read_until_match_op<AsyncReadStream,
- DynamicBuffer, MatchCondition, ReadHandler>& h,
+ const detail::read_until_match_op_v1<AsyncReadStream,
+ DynamicBuffer_v1, MatchCondition, ReadHandler>& h,
const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
{
return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);
}
};
-template <typename AsyncReadStream, typename DynamicBuffer,
+template <typename AsyncReadStream, typename DynamicBuffer_v1,
typename MatchCondition, typename ReadHandler, typename Executor>
struct associated_executor<
- detail::read_until_match_op<AsyncReadStream,
- DynamicBuffer, MatchCondition, ReadHandler>,
+ detail::read_until_match_op_v1<AsyncReadStream,
+ DynamicBuffer_v1, MatchCondition, ReadHandler>,
Executor>
{
typedef typename associated_executor<ReadHandler, Executor>::type type;
static type get(
- const detail::read_until_match_op<AsyncReadStream,
- DynamicBuffer, MatchCondition, ReadHandler>& h,
+ const detail::read_until_match_op_v1<AsyncReadStream,
+ DynamicBuffer_v1, MatchCondition, ReadHandler>& h,
const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
{
return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);
@@ -1413,31 +1827,23 @@ struct associated_executor<
#endif // !defined(GENERATING_DOCUMENTATION)
-template <typename AsyncReadStream, typename DynamicBuffer,
+template <typename AsyncReadStream, typename DynamicBuffer_v1,
typename MatchCondition, typename ReadHandler>
BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
void (boost::system::error_code, std::size_t))
async_read_until(AsyncReadStream& s,
- BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
+ BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
MatchCondition match_condition, BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
- typename enable_if<is_match_condition<MatchCondition>::value>::type*)
+ typename enable_if<
+ is_match_condition<MatchCondition>::value
+ && is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
+ && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
+ >::type*)
{
- // If you get an error on the following line it means that your handler does
- // not meet the documented type requirements for a ReadHandler.
- BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
-
- async_completion<ReadHandler,
- void (boost::system::error_code, std::size_t)> init(handler);
-
- detail::read_until_match_op<AsyncReadStream,
- typename decay<DynamicBuffer>::type,
- MatchCondition, BOOST_ASIO_HANDLER_TYPE(ReadHandler,
- void (boost::system::error_code, std::size_t))>(
- s, BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers),
- match_condition, init.completion_handler)(
- boost::system::error_code(), 0, 1);
-
- return init.result.get();
+ return async_initiate<ReadHandler,
+ void (boost::system::error_code, std::size_t)>(
+ detail::initiate_async_read_until_match_v1(), handler,
+ &s, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), match_condition);
}
#if !defined(BOOST_ASIO_NO_IOSTREAM)
@@ -1495,6 +1901,1102 @@ async_read_until(AsyncReadStream& s,
#endif // !defined(BOOST_ASIO_NO_IOSTREAM)
#endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
+#endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
+
+namespace detail
+{
+ template <typename AsyncReadStream,
+ typename DynamicBuffer_v2, typename ReadHandler>
+ class read_until_delim_op_v2
+ {
+ public:
+ template <typename BufferSequence>
+ read_until_delim_op_v2(AsyncReadStream& stream,
+ BOOST_ASIO_MOVE_ARG(BufferSequence) buffers,
+ char delim, ReadHandler& handler)
+ : stream_(stream),
+ buffers_(BOOST_ASIO_MOVE_CAST(BufferSequence)(buffers)),
+ delim_(delim),
+ start_(0),
+ search_position_(0),
+ bytes_to_read_(0),
+ handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
+ {
+ }
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+ read_until_delim_op_v2(const read_until_delim_op_v2& other)
+ : stream_(other.stream_),
+ buffers_(other.buffers_),
+ delim_(other.delim_),
+ start_(other.start_),
+ search_position_(other.search_position_),
+ bytes_to_read_(other.bytes_to_read_),
+ handler_(other.handler_)
+ {
+ }
+
+ read_until_delim_op_v2(read_until_delim_op_v2&& other)
+ : stream_(other.stream_),
+ buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(other.buffers_)),
+ delim_(other.delim_),
+ start_(other.start_),
+ search_position_(other.search_position_),
+ bytes_to_read_(other.bytes_to_read_),
+ handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
+ {
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+ void operator()(const boost::system::error_code& ec,
+ std::size_t bytes_transferred, int start = 0)
+ {
+ const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();
+ std::size_t pos;
+ switch (start_ = start)
+ {
+ case 1:
+ for (;;)
+ {
+ {
+ // Determine the range of the data to be searched.
+ typedef typename DynamicBuffer_v2::const_buffers_type
+ buffers_type;
+ typedef buffers_iterator<buffers_type> iterator;
+ buffers_type data_buffers =
+ const_cast<const DynamicBuffer_v2&>(buffers_).data(
+ 0, buffers_.size());
+ iterator begin = iterator::begin(data_buffers);
+ iterator start_pos = begin + search_position_;
+ iterator end = iterator::end(data_buffers);
+
+ // Look for a match.
+ iterator iter = std::find(start_pos, end, delim_);
+ if (iter != end)
+ {
+ // Found a match. We're done.
+ search_position_ = iter - begin + 1;
+ bytes_to_read_ = 0;
+ }
+
+ // No match yet. Check if buffer is full.
+ else if (buffers_.size() == buffers_.max_size())
+ {
+ search_position_ = not_found;
+ bytes_to_read_ = 0;
+ }
+
+ // Need to read some more data.
+ else
+ {
+ // Next search can start with the new data.
+ search_position_ = end - begin;
+ bytes_to_read_ = std::min<std::size_t>(
+ std::max<std::size_t>(512,
+ buffers_.capacity() - buffers_.size()),
+ std::min<std::size_t>(65536,
+ buffers_.max_size() - buffers_.size()));
+ }
+ }
+
+ // Check if we're done.
+ if (!start && bytes_to_read_ == 0)
+ break;
+
+ // Start a new asynchronous read op_v2eration to obtain more data.
+ pos = buffers_.size();
+ buffers_.grow(bytes_to_read_);
+ stream_.async_read_some(buffers_.data(pos, bytes_to_read_),
+ BOOST_ASIO_MOVE_CAST(read_until_delim_op_v2)(*this));
+ return; default:
+ buffers_.shrink(bytes_to_read_ - bytes_transferred);
+ if (ec || bytes_transferred == 0)
+ break;
+ }
+
+ const boost::system::error_code result_ec =
+ (search_position_ == not_found)
+ ? error::not_found : ec;
+
+ const std::size_t result_n =
+ (ec || search_position_ == not_found)
+ ? 0 : search_position_;
+
+ handler_(result_ec, result_n);
+ }
+ }
+
+ //private:
+ AsyncReadStream& stream_;
+ DynamicBuffer_v2 buffers_;
+ char delim_;
+ int start_;
+ std::size_t search_position_;
+ std::size_t bytes_to_read_;
+ ReadHandler handler_;
+ };
+
+ template <typename AsyncReadStream,
+ typename DynamicBuffer_v2, typename ReadHandler>
+ inline void* asio_handler_allocate(std::size_t size,
+ read_until_delim_op_v2<AsyncReadStream,
+ DynamicBuffer_v2, ReadHandler>* this_handler)
+ {
+ return boost_asio_handler_alloc_helpers::allocate(
+ size, this_handler->handler_);
+ }
+
+ template <typename AsyncReadStream,
+ typename DynamicBuffer_v2, typename ReadHandler>
+ inline void asio_handler_deallocate(void* pointer, std::size_t size,
+ read_until_delim_op_v2<AsyncReadStream,
+ DynamicBuffer_v2, ReadHandler>* this_handler)
+ {
+ boost_asio_handler_alloc_helpers::deallocate(
+ pointer, size, this_handler->handler_);
+ }
+
+ template <typename AsyncReadStream,
+ typename DynamicBuffer_v2, typename ReadHandler>
+ inline bool asio_handler_is_continuation(
+ read_until_delim_op_v2<AsyncReadStream,
+ DynamicBuffer_v2, ReadHandler>* this_handler)
+ {
+ return this_handler->start_ == 0 ? true
+ : boost_asio_handler_cont_helpers::is_continuation(
+ this_handler->handler_);
+ }
+
+ template <typename Function, typename AsyncReadStream,
+ typename DynamicBuffer_v2, typename ReadHandler>
+ inline void asio_handler_invoke(Function& function,
+ read_until_delim_op_v2<AsyncReadStream,
+ DynamicBuffer_v2, ReadHandler>* this_handler)
+ {
+ boost_asio_handler_invoke_helpers::invoke(
+ function, this_handler->handler_);
+ }
+
+ template <typename Function, typename AsyncReadStream,
+ typename DynamicBuffer_v2, typename ReadHandler>
+ inline void asio_handler_invoke(const Function& function,
+ read_until_delim_op_v2<AsyncReadStream,
+ DynamicBuffer_v2, ReadHandler>* this_handler)
+ {
+ boost_asio_handler_invoke_helpers::invoke(
+ function, this_handler->handler_);
+ }
+
+ struct initiate_async_read_until_delim_v2
+ {
+ template <typename ReadHandler, typename AsyncReadStream,
+ typename DynamicBuffer_v2>
+ void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
+ AsyncReadStream* s, BOOST_ASIO_MOVE_ARG(DynamicBuffer_v2) buffers,
+ char delim) const
+ {
+ // If you get an error on the following line it means that your handler
+ // does not meet the documented type requirements for a ReadHandler.
+ BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
+
+ non_const_lvalue<ReadHandler> handler2(handler);
+ read_until_delim_op_v2<AsyncReadStream,
+ typename decay<DynamicBuffer_v2>::type,
+ typename decay<ReadHandler>::type>(
+ *s, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),
+ delim, handler2.value)(boost::system::error_code(), 0, 1);
+ }
+ };
+} // namespace detail
+
+#if !defined(GENERATING_DOCUMENTATION)
+
+template <typename AsyncReadStream, typename DynamicBuffer_v2,
+ typename ReadHandler, typename Allocator>
+struct associated_allocator<
+ detail::read_until_delim_op_v2<AsyncReadStream,
+ DynamicBuffer_v2, ReadHandler>,
+ Allocator>
+{
+ typedef typename associated_allocator<ReadHandler, Allocator>::type type;
+
+ static type get(
+ const detail::read_until_delim_op_v2<AsyncReadStream,
+ DynamicBuffer_v2, ReadHandler>& h,
+ const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
+ {
+ return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);
+ }
+};
+
+template <typename AsyncReadStream, typename DynamicBuffer_v2,
+ typename ReadHandler, typename Executor>
+struct associated_executor<
+ detail::read_until_delim_op_v2<AsyncReadStream,
+ DynamicBuffer_v2, ReadHandler>,
+ Executor>
+{
+ typedef typename associated_executor<ReadHandler, Executor>::type type;
+
+ static type get(
+ const detail::read_until_delim_op_v2<AsyncReadStream,
+ DynamicBuffer_v2, ReadHandler>& h,
+ const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
+ {
+ return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);
+ }
+};
+
+#endif // !defined(GENERATING_DOCUMENTATION)
+
+template <typename AsyncReadStream,
+ typename DynamicBuffer_v2, typename ReadHandler>
+BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
+ void (boost::system::error_code, std::size_t))
+async_read_until(AsyncReadStream& s, DynamicBuffer_v2 buffers,
+ char delim, BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
+ typename enable_if<
+ is_dynamic_buffer_v2<DynamicBuffer_v2>::value
+ >::type*)
+{
+ return async_initiate<ReadHandler,
+ void (boost::system::error_code, std::size_t)>(
+ detail::initiate_async_read_until_delim_v2(), handler,
+ &s, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), delim);
+}
+
+namespace detail
+{
+ template <typename AsyncReadStream,
+ typename DynamicBuffer_v2, typename ReadHandler>
+ class read_until_delim_string_op_v2
+ {
+ public:
+ template <typename BufferSequence>
+ read_until_delim_string_op_v2(AsyncReadStream& stream,
+ BOOST_ASIO_MOVE_ARG(BufferSequence) buffers,
+ const std::string& delim, ReadHandler& handler)
+ : stream_(stream),
+ buffers_(BOOST_ASIO_MOVE_CAST(BufferSequence)(buffers)),
+ delim_(delim),
+ start_(0),
+ search_position_(0),
+ bytes_to_read_(0),
+ handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
+ {
+ }
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+ read_until_delim_string_op_v2(const read_until_delim_string_op_v2& other)
+ : stream_(other.stream_),
+ buffers_(other.buffers_),
+ delim_(other.delim_),
+ start_(other.start_),
+ search_position_(other.search_position_),
+ bytes_to_read_(other.bytes_to_read_),
+ handler_(other.handler_)
+ {
+ }
+
+ read_until_delim_string_op_v2(read_until_delim_string_op_v2&& other)
+ : stream_(other.stream_),
+ buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(other.buffers_)),
+ delim_(BOOST_ASIO_MOVE_CAST(std::string)(other.delim_)),
+ start_(other.start_),
+ search_position_(other.search_position_),
+ bytes_to_read_(other.bytes_to_read_),
+ handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
+ {
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+ void operator()(const boost::system::error_code& ec,
+ std::size_t bytes_transferred, int start = 0)
+ {
+ const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();
+ std::size_t pos;
+ switch (start_ = start)
+ {
+ case 1:
+ for (;;)
+ {
+ {
+ // Determine the range of the data to be searched.
+ typedef typename DynamicBuffer_v2::const_buffers_type
+ buffers_type;
+ typedef buffers_iterator<buffers_type> iterator;
+ buffers_type data_buffers =
+ const_cast<const DynamicBuffer_v2&>(buffers_).data(
+ 0, buffers_.size());
+ iterator begin = iterator::begin(data_buffers);
+ iterator start_pos = begin + search_position_;
+ iterator end = iterator::end(data_buffers);
+
+ // Look for a match.
+ std::pair<iterator, bool> result = detail::partial_search(
+ start_pos, end, delim_.begin(), delim_.end());
+ if (result.first != end && result.second)
+ {
+ // Full match. We're done.
+ search_position_ = result.first - begin + delim_.length();
+ bytes_to_read_ = 0;
+ }
+
+ // No match yet. Check if buffer is full.
+ else if (buffers_.size() == buffers_.max_size())
+ {
+ search_position_ = not_found;
+ bytes_to_read_ = 0;
+ }
+
+ // Need to read some more data.
+ else
+ {
+ if (result.first != end)
+ {
+ // Partial match. Next search needs to start from beginning of
+ // match.
+ search_position_ = result.first - begin;
+ }
+ else
+ {
+ // Next search can start with the new data.
+ search_position_ = end - begin;
+ }
+
+ bytes_to_read_ = std::min<std::size_t>(
+ std::max<std::size_t>(512,
+ buffers_.capacity() - buffers_.size()),
+ std::min<std::size_t>(65536,
+ buffers_.max_size() - buffers_.size()));
+ }
+ }
+
+ // Check if we're done.
+ if (!start && bytes_to_read_ == 0)
+ break;
+
+ // Start a new asynchronous read op_v2eration to obtain more data.
+ pos = buffers_.size();
+ buffers_.grow(bytes_to_read_);
+ stream_.async_read_some(buffers_.data(pos, bytes_to_read_),
+ BOOST_ASIO_MOVE_CAST(read_until_delim_string_op_v2)(*this));
+ return; default:
+ buffers_.shrink(bytes_to_read_ - bytes_transferred);
+ if (ec || bytes_transferred == 0)
+ break;
+ }
+
+ const boost::system::error_code result_ec =
+ (search_position_ == not_found)
+ ? error::not_found : ec;
+
+ const std::size_t result_n =
+ (ec || search_position_ == not_found)
+ ? 0 : search_position_;
+
+ handler_(result_ec, result_n);
+ }
+ }
+
+ //private:
+ AsyncReadStream& stream_;
+ DynamicBuffer_v2 buffers_;
+ std::string delim_;
+ int start_;
+ std::size_t search_position_;
+ std::size_t bytes_to_read_;
+ ReadHandler handler_;
+ };
+
+ template <typename AsyncReadStream,
+ typename DynamicBuffer_v2, typename ReadHandler>
+ inline void* asio_handler_allocate(std::size_t size,
+ read_until_delim_string_op_v2<AsyncReadStream,
+ DynamicBuffer_v2, ReadHandler>* this_handler)
+ {
+ return boost_asio_handler_alloc_helpers::allocate(
+ size, this_handler->handler_);
+ }
+
+ template <typename AsyncReadStream,
+ typename DynamicBuffer_v2, typename ReadHandler>
+ inline void asio_handler_deallocate(void* pointer, std::size_t size,
+ read_until_delim_string_op_v2<AsyncReadStream,
+ DynamicBuffer_v2, ReadHandler>* this_handler)
+ {
+ boost_asio_handler_alloc_helpers::deallocate(
+ pointer, size, this_handler->handler_);
+ }
+
+ template <typename AsyncReadStream,
+ typename DynamicBuffer_v2, typename ReadHandler>
+ inline bool asio_handler_is_continuation(
+ read_until_delim_string_op_v2<AsyncReadStream,
+ DynamicBuffer_v2, ReadHandler>* this_handler)
+ {
+ return this_handler->start_ == 0 ? true
+ : boost_asio_handler_cont_helpers::is_continuation(
+ this_handler->handler_);
+ }
+
+ template <typename Function, typename AsyncReadStream,
+ typename DynamicBuffer_v2, typename ReadHandler>
+ inline void asio_handler_invoke(Function& function,
+ read_until_delim_string_op_v2<AsyncReadStream,
+ DynamicBuffer_v2, ReadHandler>* this_handler)
+ {
+ boost_asio_handler_invoke_helpers::invoke(
+ function, this_handler->handler_);
+ }
+
+ template <typename Function, typename AsyncReadStream,
+ typename DynamicBuffer_v2, typename ReadHandler>
+ inline void asio_handler_invoke(const Function& function,
+ read_until_delim_string_op_v2<AsyncReadStream,
+ DynamicBuffer_v2, ReadHandler>* this_handler)
+ {
+ boost_asio_handler_invoke_helpers::invoke(
+ function, this_handler->handler_);
+ }
+
+ struct initiate_async_read_until_delim_string_v2
+ {
+ template <typename ReadHandler, typename AsyncReadStream,
+ typename DynamicBuffer_v2>
+ void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
+ AsyncReadStream* s, BOOST_ASIO_MOVE_ARG(DynamicBuffer_v2) buffers,
+ const std::string& delim) const
+ {
+ // If you get an error on the following line it means that your handler
+ // does not meet the documented type requirements for a ReadHandler.
+ BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
+
+ non_const_lvalue<ReadHandler> handler2(handler);
+ read_until_delim_string_op_v2<AsyncReadStream,
+ typename decay<DynamicBuffer_v2>::type,
+ typename decay<ReadHandler>::type>(
+ *s, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),
+ delim, handler2.value)(boost::system::error_code(), 0, 1);
+ }
+ };
+} // namespace detail
+
+#if !defined(GENERATING_DOCUMENTATION)
+
+template <typename AsyncReadStream, typename DynamicBuffer_v2,
+ typename ReadHandler, typename Allocator>
+struct associated_allocator<
+ detail::read_until_delim_string_op_v2<AsyncReadStream,
+ DynamicBuffer_v2, ReadHandler>,
+ Allocator>
+{
+ typedef typename associated_allocator<ReadHandler, Allocator>::type type;
+
+ static type get(
+ const detail::read_until_delim_string_op_v2<AsyncReadStream,
+ DynamicBuffer_v2, ReadHandler>& h,
+ const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
+ {
+ return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);
+ }
+};
+
+template <typename AsyncReadStream, typename DynamicBuffer_v2,
+ typename ReadHandler, typename Executor>
+struct associated_executor<
+ detail::read_until_delim_string_op_v2<AsyncReadStream,
+ DynamicBuffer_v2, ReadHandler>,
+ Executor>
+{
+ typedef typename associated_executor<ReadHandler, Executor>::type type;
+
+ static type get(
+ const detail::read_until_delim_string_op_v2<AsyncReadStream,
+ DynamicBuffer_v2, ReadHandler>& h,
+ const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
+ {
+ return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);
+ }
+};
+
+#endif // !defined(GENERATING_DOCUMENTATION)
+
+template <typename AsyncReadStream,
+ typename DynamicBuffer_v2, typename ReadHandler>
+BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
+ void (boost::system::error_code, std::size_t))
+async_read_until(AsyncReadStream& s,
+ DynamicBuffer_v2 buffers, BOOST_ASIO_STRING_VIEW_PARAM delim,
+ BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
+ typename enable_if<
+ is_dynamic_buffer_v2<DynamicBuffer_v2>::value
+ >::type*)
+{
+ return async_initiate<ReadHandler,
+ void (boost::system::error_code, std::size_t)>(
+ detail::initiate_async_read_until_delim_string_v2(),
+ handler, &s, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),
+ static_cast<std::string>(delim));
+}
+
+#if !defined(BOOST_ASIO_NO_EXTENSIONS)
+#if defined(BOOST_ASIO_HAS_BOOST_REGEX)
+
+namespace detail
+{
+ template <typename AsyncReadStream, typename DynamicBuffer_v2,
+ typename RegEx, typename ReadHandler>
+ class read_until_expr_op_v2
+ {
+ public:
+ template <typename BufferSequence>
+ read_until_expr_op_v2(AsyncReadStream& stream,
+ BOOST_ASIO_MOVE_ARG(BufferSequence) buffers,
+ const boost::regex& expr, ReadHandler& handler)
+ : stream_(stream),
+ buffers_(BOOST_ASIO_MOVE_CAST(BufferSequence)(buffers)),
+ expr_(expr),
+ start_(0),
+ search_position_(0),
+ bytes_to_read_(0),
+ handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
+ {
+ }
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+ read_until_expr_op_v2(const read_until_expr_op_v2& other)
+ : stream_(other.stream_),
+ buffers_(other.buffers_),
+ expr_(other.expr_),
+ start_(other.start_),
+ search_position_(other.search_position_),
+ bytes_to_read_(other.bytes_to_read_),
+ handler_(other.handler_)
+ {
+ }
+
+ read_until_expr_op_v2(read_until_expr_op_v2&& other)
+ : stream_(other.stream_),
+ buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(other.buffers_)),
+ expr_(other.expr_),
+ start_(other.start_),
+ search_position_(other.search_position_),
+ bytes_to_read_(other.bytes_to_read_),
+ handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
+ {
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+ void operator()(const boost::system::error_code& ec,
+ std::size_t bytes_transferred, int start = 0)
+ {
+ const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();
+ std::size_t pos;
+ switch (start_ = start)
+ {
+ case 1:
+ for (;;)
+ {
+ {
+ // Determine the range of the data to be searched.
+ typedef typename DynamicBuffer_v2::const_buffers_type
+ buffers_type;
+ typedef buffers_iterator<buffers_type> iterator;
+ buffers_type data_buffers =
+ const_cast<const DynamicBuffer_v2&>(buffers_).data(
+ 0, buffers_.size());
+ iterator begin = iterator::begin(data_buffers);
+ iterator start_pos = begin + search_position_;
+ iterator end = iterator::end(data_buffers);
+
+ // Look for a match.
+ boost::match_results<iterator,
+ typename std::vector<boost::sub_match<iterator> >::allocator_type>
+ match_results;
+ bool match = regex_search(start_pos, end, match_results, expr_,
+ boost::match_default | boost::match_partial);
+ if (match && match_results[0].matched)
+ {
+ // Full match. We're done.
+ search_position_ = match_results[0].second - begin;
+ bytes_to_read_ = 0;
+ }
+
+ // No match yet. Check if buffer is full.
+ else if (buffers_.size() == buffers_.max_size())
+ {
+ search_position_ = not_found;
+ bytes_to_read_ = 0;
+ }
+
+ // Need to read some more data.
+ else
+ {
+ if (match)
+ {
+ // Partial match. Next search needs to start from beginning of
+ // match.
+ search_position_ = match_results[0].first - begin;
+ }
+ else
+ {
+ // Next search can start with the new data.
+ search_position_ = end - begin;
+ }
+
+ bytes_to_read_ = std::min<std::size_t>(
+ std::max<std::size_t>(512,
+ buffers_.capacity() - buffers_.size()),
+ std::min<std::size_t>(65536,
+ buffers_.max_size() - buffers_.size()));
+ }
+ }
+
+ // Check if we're done.
+ if (!start && bytes_to_read_ == 0)
+ break;
+
+ // Start a new asynchronous read op_v2eration to obtain more data.
+ pos = buffers_.size();
+ buffers_.grow(bytes_to_read_);
+ stream_.async_read_some(buffers_.data(pos, bytes_to_read_),
+ BOOST_ASIO_MOVE_CAST(read_until_expr_op_v2)(*this));
+ return; default:
+ buffers_.shrink(bytes_to_read_ - bytes_transferred);
+ if (ec || bytes_transferred == 0)
+ break;
+ }
+
+ const boost::system::error_code result_ec =
+ (search_position_ == not_found)
+ ? error::not_found : ec;
+
+ const std::size_t result_n =
+ (ec || search_position_ == not_found)
+ ? 0 : search_position_;
+
+ handler_(result_ec, result_n);
+ }
+ }
+
+ //private:
+ AsyncReadStream& stream_;
+ DynamicBuffer_v2 buffers_;
+ RegEx expr_;
+ int start_;
+ std::size_t search_position_;
+ std::size_t bytes_to_read_;
+ ReadHandler handler_;
+ };
+
+ template <typename AsyncReadStream, typename DynamicBuffer_v2,
+ typename RegEx, typename ReadHandler>
+ inline void* asio_handler_allocate(std::size_t size,
+ read_until_expr_op_v2<AsyncReadStream,
+ DynamicBuffer_v2, RegEx, ReadHandler>* this_handler)
+ {
+ return boost_asio_handler_alloc_helpers::allocate(
+ size, this_handler->handler_);
+ }
+
+ template <typename AsyncReadStream, typename DynamicBuffer_v2,
+ typename RegEx, typename ReadHandler>
+ inline void asio_handler_deallocate(void* pointer, std::size_t size,
+ read_until_expr_op_v2<AsyncReadStream,
+ DynamicBuffer_v2, RegEx, ReadHandler>* this_handler)
+ {
+ boost_asio_handler_alloc_helpers::deallocate(
+ pointer, size, this_handler->handler_);
+ }
+
+ template <typename AsyncReadStream, typename DynamicBuffer_v2,
+ typename RegEx, typename ReadHandler>
+ inline bool asio_handler_is_continuation(
+ read_until_expr_op_v2<AsyncReadStream,
+ DynamicBuffer_v2, RegEx, ReadHandler>* this_handler)
+ {
+ return this_handler->start_ == 0 ? true
+ : boost_asio_handler_cont_helpers::is_continuation(
+ this_handler->handler_);
+ }
+
+ template <typename Function, typename AsyncReadStream,
+ typename DynamicBuffer_v2, typename RegEx, typename ReadHandler>
+ inline void asio_handler_invoke(Function& function,
+ read_until_expr_op_v2<AsyncReadStream,
+ DynamicBuffer_v2, RegEx, ReadHandler>* this_handler)
+ {
+ boost_asio_handler_invoke_helpers::invoke(
+ function, this_handler->handler_);
+ }
+
+ template <typename Function, typename AsyncReadStream,
+ typename DynamicBuffer_v2, typename RegEx, typename ReadHandler>
+ inline void asio_handler_invoke(const Function& function,
+ read_until_expr_op_v2<AsyncReadStream,
+ DynamicBuffer_v2, RegEx, ReadHandler>* this_handler)
+ {
+ boost_asio_handler_invoke_helpers::invoke(
+ function, this_handler->handler_);
+ }
+
+ struct initiate_async_read_until_expr_v2
+ {
+ template <typename ReadHandler, typename AsyncReadStream,
+ typename DynamicBuffer_v2, typename RegEx>
+ void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
+ AsyncReadStream* s, BOOST_ASIO_MOVE_ARG(DynamicBuffer_v2) buffers,
+ const RegEx& expr) const
+ {
+ // If you get an error on the following line it means that your handler
+ // does not meet the documented type requirements for a ReadHandler.
+ BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
+
+ non_const_lvalue<ReadHandler> handler2(handler);
+ read_until_expr_op_v2<AsyncReadStream,
+ typename decay<DynamicBuffer_v2>::type,
+ RegEx, typename decay<ReadHandler>::type>(
+ *s, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),
+ expr, handler2.value)(boost::system::error_code(), 0, 1);
+ }
+ };
+} // namespace detail
+
+#if !defined(GENERATING_DOCUMENTATION)
+
+template <typename AsyncReadStream, typename DynamicBuffer_v2,
+ typename RegEx, typename ReadHandler, typename Allocator>
+struct associated_allocator<
+ detail::read_until_expr_op_v2<AsyncReadStream,
+ DynamicBuffer_v2, RegEx, ReadHandler>,
+ Allocator>
+{
+ typedef typename associated_allocator<ReadHandler, Allocator>::type type;
+
+ static type get(
+ const detail::read_until_expr_op_v2<AsyncReadStream,
+ DynamicBuffer_v2, RegEx, ReadHandler>& h,
+ const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
+ {
+ return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);
+ }
+};
+
+template <typename AsyncReadStream, typename DynamicBuffer_v2,
+ typename RegEx, typename ReadHandler, typename Executor>
+struct associated_executor<
+ detail::read_until_expr_op_v2<AsyncReadStream,
+ DynamicBuffer_v2, RegEx, ReadHandler>,
+ Executor>
+{
+ typedef typename associated_executor<ReadHandler, Executor>::type type;
+
+ static type get(
+ const detail::read_until_expr_op_v2<AsyncReadStream,
+ DynamicBuffer_v2, RegEx, ReadHandler>& h,
+ const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
+ {
+ return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);
+ }
+};
+
+#endif // !defined(GENERATING_DOCUMENTATION)
+
+template <typename AsyncReadStream,
+ typename DynamicBuffer_v2, typename ReadHandler>
+BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
+ void (boost::system::error_code, std::size_t))
+async_read_until(AsyncReadStream& s, DynamicBuffer_v2 buffers,
+ const boost::regex& expr, BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
+ typename enable_if<
+ is_dynamic_buffer_v2<DynamicBuffer_v2>::value
+ >::type*)
+{
+ return async_initiate<ReadHandler,
+ void (boost::system::error_code, std::size_t)>(
+ detail::initiate_async_read_until_expr_v2(), handler,
+ &s, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), expr);
+}
+
+#endif // defined(BOOST_ASIO_HAS_BOOST_REGEX)
+
+namespace detail
+{
+ template <typename AsyncReadStream, typename DynamicBuffer_v2,
+ typename MatchCondition, typename ReadHandler>
+ class read_until_match_op_v2
+ {
+ public:
+ template <typename BufferSequence>
+ read_until_match_op_v2(AsyncReadStream& stream,
+ BOOST_ASIO_MOVE_ARG(BufferSequence) buffers,
+ MatchCondition match_condition, ReadHandler& handler)
+ : stream_(stream),
+ buffers_(BOOST_ASIO_MOVE_CAST(BufferSequence)(buffers)),
+ match_condition_(match_condition),
+ start_(0),
+ search_position_(0),
+ bytes_to_read_(0),
+ handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
+ {
+ }
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+ read_until_match_op_v2(const read_until_match_op_v2& other)
+ : stream_(other.stream_),
+ buffers_(other.buffers_),
+ match_condition_(other.match_condition_),
+ start_(other.start_),
+ search_position_(other.search_position_),
+ bytes_to_read_(other.bytes_to_read_),
+ handler_(other.handler_)
+ {
+ }
+
+ read_until_match_op_v2(read_until_match_op_v2&& other)
+ : stream_(other.stream_),
+ buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(other.buffers_)),
+ match_condition_(other.match_condition_),
+ start_(other.start_),
+ search_position_(other.search_position_),
+ bytes_to_read_(other.bytes_to_read_),
+ handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
+ {
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+ void operator()(const boost::system::error_code& ec,
+ std::size_t bytes_transferred, int start = 0)
+ {
+ const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();
+ std::size_t pos;
+ switch (start_ = start)
+ {
+ case 1:
+ for (;;)
+ {
+ {
+ // Determine the range of the data to be searched.
+ typedef typename DynamicBuffer_v2::const_buffers_type
+ buffers_type;
+ typedef buffers_iterator<buffers_type> iterator;
+ buffers_type data_buffers =
+ const_cast<const DynamicBuffer_v2&>(buffers_).data(
+ 0, buffers_.size());
+ iterator begin = iterator::begin(data_buffers);
+ iterator start_pos = begin + search_position_;
+ iterator end = iterator::end(data_buffers);
+
+ // Look for a match.
+ std::pair<iterator, bool> result = match_condition_(start_pos, end);
+ if (result.second)
+ {
+ // Full match. We're done.
+ search_position_ = result.first - begin;
+ bytes_to_read_ = 0;
+ }
+
+ // No match yet. Check if buffer is full.
+ else if (buffers_.size() == buffers_.max_size())
+ {
+ search_position_ = not_found;
+ bytes_to_read_ = 0;
+ }
+
+ // Need to read some more data.
+ else
+ {
+ if (result.first != end)
+ {
+ // Partial match. Next search needs to start from beginning of
+ // match.
+ search_position_ = result.first - begin;
+ }
+ else
+ {
+ // Next search can start with the new data.
+ search_position_ = end - begin;
+ }
+
+ bytes_to_read_ = std::min<std::size_t>(
+ std::max<std::size_t>(512,
+ buffers_.capacity() - buffers_.size()),
+ std::min<std::size_t>(65536,
+ buffers_.max_size() - buffers_.size()));
+ }
+ }
+
+ // Check if we're done.
+ if (!start && bytes_to_read_ == 0)
+ break;
+
+ // Start a new asynchronous read op_v2eration to obtain more data.
+ pos = buffers_.size();
+ buffers_.grow(bytes_to_read_);
+ stream_.async_read_some(buffers_.data(pos, bytes_to_read_),
+ BOOST_ASIO_MOVE_CAST(read_until_match_op_v2)(*this));
+ return; default:
+ buffers_.shrink(bytes_to_read_ - bytes_transferred);
+ if (ec || bytes_transferred == 0)
+ break;
+ }
+
+ const boost::system::error_code result_ec =
+ (search_position_ == not_found)
+ ? error::not_found : ec;
+
+ const std::size_t result_n =
+ (ec || search_position_ == not_found)
+ ? 0 : search_position_;
+
+ handler_(result_ec, result_n);
+ }
+ }
+
+ //private:
+ AsyncReadStream& stream_;
+ DynamicBuffer_v2 buffers_;
+ MatchCondition match_condition_;
+ int start_;
+ std::size_t search_position_;
+ std::size_t bytes_to_read_;
+ ReadHandler handler_;
+ };
+
+ template <typename AsyncReadStream, typename DynamicBuffer_v2,
+ typename MatchCondition, typename ReadHandler>
+ inline void* asio_handler_allocate(std::size_t size,
+ read_until_match_op_v2<AsyncReadStream, DynamicBuffer_v2,
+ MatchCondition, ReadHandler>* this_handler)
+ {
+ return boost_asio_handler_alloc_helpers::allocate(
+ size, this_handler->handler_);
+ }
+
+ template <typename AsyncReadStream, typename DynamicBuffer_v2,
+ typename MatchCondition, typename ReadHandler>
+ inline void asio_handler_deallocate(void* pointer, std::size_t size,
+ read_until_match_op_v2<AsyncReadStream, DynamicBuffer_v2,
+ MatchCondition, ReadHandler>* this_handler)
+ {
+ boost_asio_handler_alloc_helpers::deallocate(
+ pointer, size, this_handler->handler_);
+ }
+
+ template <typename AsyncReadStream, typename DynamicBuffer_v2,
+ typename MatchCondition, typename ReadHandler>
+ inline bool asio_handler_is_continuation(
+ read_until_match_op_v2<AsyncReadStream, DynamicBuffer_v2,
+ MatchCondition, ReadHandler>* this_handler)
+ {
+ return this_handler->start_ == 0 ? true
+ : boost_asio_handler_cont_helpers::is_continuation(
+ this_handler->handler_);
+ }
+
+ template <typename Function, typename AsyncReadStream,
+ typename DynamicBuffer_v2, typename MatchCondition,
+ typename ReadHandler>
+ inline void asio_handler_invoke(Function& function,
+ read_until_match_op_v2<AsyncReadStream, DynamicBuffer_v2,
+ MatchCondition, ReadHandler>* this_handler)
+ {
+ boost_asio_handler_invoke_helpers::invoke(
+ function, this_handler->handler_);
+ }
+
+ template <typename Function, typename AsyncReadStream,
+ typename DynamicBuffer_v2, typename MatchCondition,
+ typename ReadHandler>
+ inline void asio_handler_invoke(const Function& function,
+ read_until_match_op_v2<AsyncReadStream, DynamicBuffer_v2,
+ MatchCondition, ReadHandler>* this_handler)
+ {
+ boost_asio_handler_invoke_helpers::invoke(
+ function, this_handler->handler_);
+ }
+
+ struct initiate_async_read_until_match_v2
+ {
+ template <typename ReadHandler, typename AsyncReadStream,
+ typename DynamicBuffer_v2, typename MatchCondition>
+ void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
+ AsyncReadStream* s, BOOST_ASIO_MOVE_ARG(DynamicBuffer_v2) buffers,
+ MatchCondition match_condition) const
+ {
+ // If you get an error on the following line it means that your handler
+ // does not meet the documented type requirements for a ReadHandler.
+ BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
+
+ non_const_lvalue<ReadHandler> handler2(handler);
+ read_until_match_op_v2<AsyncReadStream,
+ typename decay<DynamicBuffer_v2>::type,
+ MatchCondition, typename decay<ReadHandler>::type>(
+ *s, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),
+ match_condition, handler2.value)(boost::system::error_code(), 0, 1);
+ }
+ };
+} // namespace detail
+
+#if !defined(GENERATING_DOCUMENTATION)
+
+template <typename AsyncReadStream, typename DynamicBuffer_v2,
+ typename MatchCondition, typename ReadHandler, typename Allocator>
+struct associated_allocator<
+ detail::read_until_match_op_v2<AsyncReadStream,
+ DynamicBuffer_v2, MatchCondition, ReadHandler>,
+ Allocator>
+{
+ typedef typename associated_allocator<ReadHandler, Allocator>::type type;
+
+ static type get(
+ const detail::read_until_match_op_v2<AsyncReadStream,
+ DynamicBuffer_v2, MatchCondition, ReadHandler>& h,
+ const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
+ {
+ return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);
+ }
+};
+
+template <typename AsyncReadStream, typename DynamicBuffer_v2,
+ typename MatchCondition, typename ReadHandler, typename Executor>
+struct associated_executor<
+ detail::read_until_match_op_v2<AsyncReadStream,
+ DynamicBuffer_v2, MatchCondition, ReadHandler>,
+ Executor>
+{
+ typedef typename associated_executor<ReadHandler, Executor>::type type;
+
+ static type get(
+ const detail::read_until_match_op_v2<AsyncReadStream,
+ DynamicBuffer_v2, MatchCondition, ReadHandler>& h,
+ const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
+ {
+ return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);
+ }
+};
+
+#endif // !defined(GENERATING_DOCUMENTATION)
+
+template <typename AsyncReadStream, typename DynamicBuffer_v2,
+ typename MatchCondition, typename ReadHandler>
+BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
+ void (boost::system::error_code, std::size_t))
+async_read_until(AsyncReadStream& s, DynamicBuffer_v2 buffers,
+ MatchCondition match_condition, BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
+ typename enable_if<
+ is_match_condition<MatchCondition>::value
+ && is_dynamic_buffer_v2<DynamicBuffer_v2>::value
+ >::type*)
+{
+ return async_initiate<ReadHandler,
+ void (boost::system::error_code, std::size_t)>(
+ detail::initiate_async_read_until_match_v2(), handler,
+ &s, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), match_condition);
+}
+
+#endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
} // namespace asio
} // namespace boost
diff --git a/boost/asio/impl/redirect_error.hpp b/boost/asio/impl/redirect_error.hpp
new file mode 100644
index 0000000000..eb0d82998a
--- /dev/null
+++ b/boost/asio/impl/redirect_error.hpp
@@ -0,0 +1,374 @@
+
+// impl/redirect_error.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_IMPL_REDIRECT_ERROR_HPP
+#define BOOST_ASIO_IMPL_REDIRECT_ERROR_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <boost/asio/associated_executor.hpp>
+#include <boost/asio/associated_allocator.hpp>
+#include <boost/asio/async_result.hpp>
+#include <boost/asio/detail/handler_alloc_helpers.hpp>
+#include <boost/asio/detail/handler_cont_helpers.hpp>
+#include <boost/asio/detail/handler_invoke_helpers.hpp>
+#include <boost/asio/detail/type_traits.hpp>
+#include <boost/asio/detail/variadic_templates.hpp>
+#include <boost/system/system_error.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+// Class to adapt a redirect_error_t as a completion handler.
+template <typename Handler>
+class redirect_error_handler
+{
+public:
+ typedef void result_type;
+
+ template <typename CompletionToken>
+ redirect_error_handler(redirect_error_t<CompletionToken> e)
+ : ec_(e.ec_),
+ handler_(BOOST_ASIO_MOVE_CAST(CompletionToken)(e.token_))
+ {
+ }
+
+ template <typename RedirectedHandler>
+ redirect_error_handler(boost::system::error_code& ec,
+ BOOST_ASIO_MOVE_ARG(RedirectedHandler) h)
+ : ec_(ec),
+ handler_(BOOST_ASIO_MOVE_CAST(RedirectedHandler)(h))
+ {
+ }
+
+ void operator()()
+ {
+ handler_();
+ }
+
+#if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
+
+ template <typename Arg, typename... Args>
+ typename enable_if<
+ !is_same<typename decay<Arg>::type, boost::system::error_code>::value
+ >::type
+ operator()(BOOST_ASIO_MOVE_ARG(Arg) arg, BOOST_ASIO_MOVE_ARG(Args)... args)
+ {
+ handler_(BOOST_ASIO_MOVE_CAST(Arg)(arg),
+ BOOST_ASIO_MOVE_CAST(Args)(args)...);
+ }
+
+ template <typename... Args>
+ void operator()(const boost::system::error_code& ec,
+ BOOST_ASIO_MOVE_ARG(Args)... args)
+ {
+ ec_ = ec;
+ handler_(BOOST_ASIO_MOVE_CAST(Args)(args)...);
+ }
+
+#else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
+
+ template <typename Arg>
+ typename enable_if<
+ !is_same<typename decay<Arg>::type, boost::system::error_code>::value
+ >::type
+ operator()(BOOST_ASIO_MOVE_ARG(Arg) arg)
+ {
+ handler_(BOOST_ASIO_MOVE_CAST(Arg)(arg));
+ }
+
+ void operator()(const boost::system::error_code& ec)
+ {
+ ec_ = ec;
+ handler_();
+ }
+
+#define BOOST_ASIO_PRIVATE_REDIRECT_ERROR_DEF(n) \
+ template <typename Arg, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
+ typename enable_if< \
+ !is_same<typename decay<Arg>::type, boost::system::error_code>::value \
+ >::type \
+ operator()(BOOST_ASIO_MOVE_ARG(Arg) arg, BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
+ { \
+ handler_(BOOST_ASIO_MOVE_CAST(Arg)(arg), \
+ BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \
+ } \
+ \
+ template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \
+ void operator()(const boost::system::error_code& ec, \
+ BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
+ { \
+ ec_ = ec; \
+ handler_(BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \
+ } \
+ /**/
+ BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_REDIRECT_ERROR_DEF)
+#undef BOOST_ASIO_PRIVATE_REDIRECT_ERROR_DEF
+
+#endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
+
+//private:
+ boost::system::error_code& ec_;
+ Handler handler_;
+};
+
+template <typename Handler>
+inline void* asio_handler_allocate(std::size_t size,
+ redirect_error_handler<Handler>* this_handler)
+{
+ return boost_asio_handler_alloc_helpers::allocate(
+ size, this_handler->handler_);
+}
+
+template <typename Handler>
+inline void asio_handler_deallocate(void* pointer, std::size_t size,
+ redirect_error_handler<Handler>* this_handler)
+{
+ boost_asio_handler_alloc_helpers::deallocate(
+ pointer, size, this_handler->handler_);
+}
+
+template <typename Handler>
+inline bool asio_handler_is_continuation(
+ redirect_error_handler<Handler>* this_handler)
+{
+ return boost_asio_handler_cont_helpers::is_continuation(
+ this_handler->handler_);
+}
+
+template <typename Function, typename Handler>
+inline void asio_handler_invoke(Function& function,
+ redirect_error_handler<Handler>* this_handler)
+{
+ boost_asio_handler_invoke_helpers::invoke(
+ function, this_handler->handler_);
+}
+
+template <typename Function, typename Handler>
+inline void asio_handler_invoke(const Function& function,
+ redirect_error_handler<Handler>* this_handler)
+{
+ boost_asio_handler_invoke_helpers::invoke(
+ function, this_handler->handler_);
+}
+
+template <typename Signature>
+struct redirect_error_signature
+{
+ typedef Signature type;
+};
+
+#if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
+
+template <typename R, typename... Args>
+struct redirect_error_signature<R(boost::system::error_code, Args...)>
+{
+ typedef R type(Args...);
+};
+
+template <typename R, typename... Args>
+struct redirect_error_signature<R(const boost::system::error_code&, Args...)>
+{
+ typedef R type(Args...);
+};
+
+#else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
+
+template <typename R>
+struct redirect_error_signature<R(boost::system::error_code)>
+{
+ typedef R type();
+};
+
+template <typename R>
+struct redirect_error_signature<R(const boost::system::error_code&)>
+{
+ typedef R type();
+};
+
+#define BOOST_ASIO_PRIVATE_REDIRECT_ERROR_DEF(n) \
+ template <typename R, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
+ struct redirect_error_signature< \
+ R(boost::system::error_code, BOOST_ASIO_VARIADIC_TARGS(n))> \
+ { \
+ typedef R type(BOOST_ASIO_VARIADIC_TARGS(n)); \
+ }; \
+ \
+ template <typename R, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
+ struct redirect_error_signature< \
+ R(const boost::system::error_code&, BOOST_ASIO_VARIADIC_TARGS(n))> \
+ { \
+ typedef R type(BOOST_ASIO_VARIADIC_TARGS(n)); \
+ }; \
+ /**/
+ BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_REDIRECT_ERROR_DEF)
+#undef BOOST_ASIO_PRIVATE_REDIRECT_ERROR_DEF
+
+#endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
+
+} // namespace detail
+
+#if !defined(GENERATING_DOCUMENTATION)
+
+template <typename CompletionToken, typename Signature>
+struct async_result<redirect_error_t<CompletionToken>, Signature>
+{
+ typedef typename async_result<CompletionToken,
+ typename detail::redirect_error_signature<Signature>::type>
+ ::return_type return_type;
+
+ template <typename Initiation>
+ struct init_wrapper
+ {
+ template <typename Init>
+ init_wrapper(boost::system::error_code& ec, BOOST_ASIO_MOVE_ARG(Init) init)
+ : ec_(ec),
+ initiation_(BOOST_ASIO_MOVE_CAST(Init)(init))
+ {
+ }
+
+#if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
+
+ template <typename Handler, typename... Args>
+ void operator()(
+ BOOST_ASIO_MOVE_ARG(Handler) handler,
+ BOOST_ASIO_MOVE_ARG(Args)... args)
+ {
+ BOOST_ASIO_MOVE_CAST(Initiation)(initiation_)(
+ detail::redirect_error_handler<
+ typename decay<Handler>::type>(
+ ec_, BOOST_ASIO_MOVE_CAST(Handler)(handler)),
+ BOOST_ASIO_MOVE_CAST(Args)(args)...);
+ }
+
+#else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
+
+ template <typename Handler>
+ void operator()(
+ BOOST_ASIO_MOVE_ARG(Handler) handler)
+ {
+ BOOST_ASIO_MOVE_CAST(Initiation)(initiation_)(
+ detail::redirect_error_handler<
+ typename decay<Handler>::type>(
+ ec_, BOOST_ASIO_MOVE_CAST(Handler)(handler)));
+ }
+
+#define BOOST_ASIO_PRIVATE_INIT_WRAPPER_DEF(n) \
+ template <typename Handler, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
+ void operator()( \
+ BOOST_ASIO_MOVE_ARG(Handler) handler, \
+ BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
+ { \
+ BOOST_ASIO_MOVE_CAST(Initiation)(initiation_)( \
+ detail::redirect_error_handler< \
+ typename decay<Handler>::type>( \
+ ec_, BOOST_ASIO_MOVE_CAST(Handler)(handler)), \
+ BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \
+ } \
+ /**/
+ BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_INIT_WRAPPER_DEF)
+#undef BOOST_ASIO_PRIVATE_INIT_WRAPPER_DEF
+
+#endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
+
+ boost::system::error_code& ec_;
+ Initiation initiation_;
+ };
+
+#if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
+
+ template <typename Initiation, typename RawCompletionToken, typename... Args>
+ static return_type initiate(
+ BOOST_ASIO_MOVE_ARG(Initiation) initiation,
+ BOOST_ASIO_MOVE_ARG(RawCompletionToken) token,
+ BOOST_ASIO_MOVE_ARG(Args)... args)
+ {
+ return async_initiate<CompletionToken,
+ typename detail::redirect_error_signature<Signature>::type>(
+ init_wrapper<typename decay<Initiation>::type>(
+ token.ec_, BOOST_ASIO_MOVE_CAST(Initiation)(initiation)),
+ token.token_, BOOST_ASIO_MOVE_CAST(Args)(args)...);
+ }
+
+#else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
+
+ template <typename Initiation, typename RawCompletionToken>
+ static return_type initiate(
+ BOOST_ASIO_MOVE_ARG(Initiation) initiation,
+ BOOST_ASIO_MOVE_ARG(RawCompletionToken) token)
+ {
+ return async_initiate<CompletionToken,
+ typename detail::redirect_error_signature<Signature>::type>(
+ init_wrapper<typename decay<Initiation>::type>(
+ token.ec_, BOOST_ASIO_MOVE_CAST(Initiation)(initiation)),
+ token.token_);
+ }
+
+#define BOOST_ASIO_PRIVATE_INITIATE_DEF(n) \
+ template <typename Initiation, typename RawCompletionToken, \
+ BOOST_ASIO_VARIADIC_TPARAMS(n)> \
+ static return_type initiate( \
+ BOOST_ASIO_MOVE_ARG(Initiation) initiation, \
+ BOOST_ASIO_MOVE_ARG(RawCompletionToken) token, \
+ BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
+ { \
+ return async_initiate<CompletionToken, \
+ typename detail::redirect_error_signature<Signature>::type>( \
+ init_wrapper<typename decay<Initiation>::type>( \
+ token.ec_, BOOST_ASIO_MOVE_CAST(Initiation)(initiation)), \
+ token.token_, BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \
+ } \
+ /**/
+ BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_INITIATE_DEF)
+#undef BOOST_ASIO_PRIVATE_INITIATE_DEF
+
+#endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
+};
+
+template <typename Handler, typename Executor>
+struct associated_executor<detail::redirect_error_handler<Handler>, Executor>
+{
+ typedef typename associated_executor<Handler, Executor>::type type;
+
+ static type get(
+ const detail::redirect_error_handler<Handler>& h,
+ const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
+ {
+ return associated_executor<Handler, Executor>::get(h.handler_, ex);
+ }
+};
+
+template <typename Handler, typename Allocator>
+struct associated_allocator<detail::redirect_error_handler<Handler>, Allocator>
+{
+ typedef typename associated_allocator<Handler, Allocator>::type type;
+
+ static type get(
+ const detail::redirect_error_handler<Handler>& h,
+ const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
+ {
+ return associated_allocator<Handler, Allocator>::get(h.handler_, a);
+ }
+};
+
+#endif // !defined(GENERATING_DOCUMENTATION)
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_IMPL_REDIRECT_ERROR_HPP
diff --git a/boost/asio/impl/serial_port_base.hpp b/boost/asio/impl/serial_port_base.hpp
index 7f2dfe88df..c456e30800 100644
--- a/boost/asio/impl/serial_port_base.hpp
+++ b/boost/asio/impl/serial_port_base.hpp
@@ -2,7 +2,7 @@
// impl/serial_port_base.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
diff --git a/boost/asio/impl/serial_port_base.ipp b/boost/asio/impl/serial_port_base.ipp
index 9954f77d2e..c7ff51876a 100644
--- a/boost/asio/impl/serial_port_base.ipp
+++ b/boost/asio/impl/serial_port_base.ipp
@@ -2,7 +2,7 @@
// impl/serial_port_base.ipp
// ~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
diff --git a/boost/asio/impl/spawn.hpp b/boost/asio/impl/spawn.hpp
index c2da5ce09a..cf4ce5622f 100644
--- a/boost/asio/impl/spawn.hpp
+++ b/boost/asio/impl/spawn.hpp
@@ -2,7 +2,7 @@
// impl/spawn.hpp
// ~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -278,51 +278,6 @@ public:
}
};
-#if !defined(BOOST_ASIO_NO_DEPRECATED)
-
-template <typename Handler, typename ReturnType>
-struct handler_type<basic_yield_context<Handler>, ReturnType()>
-{
- typedef detail::coro_handler<Handler, void> type;
-};
-
-template <typename Handler, typename ReturnType, typename Arg1>
-struct handler_type<basic_yield_context<Handler>, ReturnType(Arg1)>
-{
- typedef detail::coro_handler<Handler, typename decay<Arg1>::type> type;
-};
-
-template <typename Handler, typename ReturnType>
-struct handler_type<basic_yield_context<Handler>,
- ReturnType(boost::system::error_code)>
-{
- typedef detail::coro_handler<Handler, void> type;
-};
-
-template <typename Handler, typename ReturnType, typename Arg2>
-struct handler_type<basic_yield_context<Handler>,
- ReturnType(boost::system::error_code, Arg2)>
-{
- typedef detail::coro_handler<Handler, typename decay<Arg2>::type> type;
-};
-
-template <typename Handler, typename T>
-class async_result<detail::coro_handler<Handler, T> >
- : public detail::coro_async_result<Handler, T>
-{
-public:
- typedef typename detail::coro_async_result<Handler, T>::return_type type;
-
- explicit async_result(
- typename detail::coro_async_result<Handler,
- T>::completion_handler_type& h)
- : detail::coro_async_result<Handler, T>(h)
- {
- }
-};
-
-#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
-
template <typename Handler, typename T, typename Allocator>
struct associated_allocator<detail::coro_handler<Handler, T>, Allocator>
{
diff --git a/boost/asio/impl/src.cpp b/boost/asio/impl/src.cpp
index 3823acfaf3..8f43dbf0ca 100644
--- a/boost/asio/impl/src.cpp
+++ b/boost/asio/impl/src.cpp
@@ -2,7 +2,7 @@
// impl/src.cpp
// ~~~~~~~~~~~~
//
-// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/impl/src.hpp b/boost/asio/impl/src.hpp
index b891a453fe..7f155ad25c 100644
--- a/boost/asio/impl/src.hpp
+++ b/boost/asio/impl/src.hpp
@@ -2,7 +2,7 @@
// impl/src.hpp
// ~~~~~~~~~~~~
//
-// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/impl/system_context.hpp b/boost/asio/impl/system_context.hpp
index dab5d4d085..2a6b61f312 100644
--- a/boost/asio/impl/system_context.hpp
+++ b/boost/asio/impl/system_context.hpp
@@ -2,7 +2,7 @@
// impl/system_context.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/impl/system_context.ipp b/boost/asio/impl/system_context.ipp
index e56632c816..0ec6fad171 100644
--- a/boost/asio/impl/system_context.ipp
+++ b/boost/asio/impl/system_context.ipp
@@ -2,7 +2,7 @@
// impl/system_context.ipp
// ~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -35,7 +35,7 @@ struct system_context::thread_function
};
system_context::system_context()
- : scheduler_(use_service<detail::scheduler>(*this))
+ : scheduler_(add_scheduler(new detail::scheduler(*this, 0, false)))
{
scheduler_.work_started();
@@ -67,6 +67,13 @@ void system_context::join()
threads_.join();
}
+detail::scheduler& system_context::add_scheduler(detail::scheduler* s)
+{
+ detail::scoped_ptr<detail::scheduler> scoped_impl(s);
+ boost::asio::add_service<detail::scheduler>(*this, scoped_impl.get());
+ return *scoped_impl.release();
+}
+
} // namespace asio
} // namespace boost
diff --git a/boost/asio/impl/system_executor.hpp b/boost/asio/impl/system_executor.hpp
index c59e780d3f..25c51a6560 100644
--- a/boost/asio/impl/system_executor.hpp
+++ b/boost/asio/impl/system_executor.hpp
@@ -2,7 +2,7 @@
// impl/system_executor.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/impl/thread_pool.hpp b/boost/asio/impl/thread_pool.hpp
index ed8d768cd0..31d8b37ee0 100644
--- a/boost/asio/impl/thread_pool.hpp
+++ b/boost/asio/impl/thread_pool.hpp
@@ -2,7 +2,7 @@
// impl/thread_pool.hpp
// ~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/boost/asio/impl/thread_pool.ipp b/boost/asio/impl/thread_pool.ipp
index e0952eb657..d59b6ef15f 100644
--- a/boost/asio/impl/thread_pool.ipp
+++ b/boost/asio/impl/thread_pool.ipp
@@ -2,7 +2,7 @@
// impl/thread_pool.ipp
// ~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -35,7 +35,7 @@ struct thread_pool::thread_function
};
thread_pool::thread_pool()
- : scheduler_(use_service<detail::scheduler>(*this))
+ : scheduler_(add_scheduler(new detail::scheduler(*this, 0, false)))
{
scheduler_.work_started();
@@ -45,7 +45,8 @@ thread_pool::thread_pool()
}
thread_pool::thread_pool(std::size_t num_threads)
- : scheduler_(use_service<detail::scheduler>(*this))
+ : scheduler_(add_scheduler(new detail::scheduler(
+ *this, num_threads == 1 ? 1 : 0, false)))
{
scheduler_.work_started();
@@ -66,8 +67,18 @@ void thread_pool::stop()
void thread_pool::join()
{
- scheduler_.work_finished();
- threads_.join();
+ if (!threads_.empty())
+ {
+ scheduler_.work_finished();
+ threads_.join();
+ }
+}
+
+detail::scheduler& thread_pool::add_scheduler(detail::scheduler* s)
+{
+ detail::scoped_ptr<detail::scheduler> scoped_impl(s);
+ boost::asio::add_service<detail::scheduler>(*this, scoped_impl.get());
+ return *scoped_impl.release();
}
} // namespace asio
diff --git a/boost/asio/impl/use_awaitable.hpp b/boost/asio/impl/use_awaitable.hpp
new file mode 100644
index 0000000000..0d7ad0a42b
--- /dev/null
+++ b/boost/asio/impl/use_awaitable.hpp
@@ -0,0 +1,278 @@
+//
+// impl/use_awaitable.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_IMPL_USE_AWAITABLE_HPP
+#define BOOST_ASIO_IMPL_USE_AWAITABLE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <boost/asio/async_result.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+template <typename Executor, typename T>
+class awaitable_handler_base
+ : public awaitable_thread<Executor>
+{
+public:
+ typedef void result_type;
+ typedef awaitable<T, Executor> awaitable_type;
+
+ // Construct from the entry point of a new thread of execution.
+ awaitable_handler_base(awaitable<void, Executor> a, const Executor& ex)
+ : awaitable_thread<Executor>(std::move(a), ex)
+ {
+ }
+
+ // Transfer ownership from another awaitable_thread.
+ explicit awaitable_handler_base(awaitable_thread<Executor>* h)
+ : awaitable_thread<Executor>(std::move(*h))
+ {
+ }
+
+protected:
+ awaitable_frame<T, Executor>* frame() noexcept
+ {
+ return static_cast<awaitable_frame<T, Executor>*>(this->top_of_stack_);
+ }
+};
+
+template <typename, typename...>
+class awaitable_handler;
+
+template <typename Executor>
+class awaitable_handler<Executor, void>
+ : public awaitable_handler_base<Executor, void>
+{
+public:
+ using awaitable_handler_base<Executor, void>::awaitable_handler_base;
+
+ void operator()()
+ {
+ this->frame()->attach_thread(this);
+ this->frame()->return_void();
+ this->frame()->pop_frame();
+ this->pump();
+ }
+};
+
+template <typename Executor>
+class awaitable_handler<Executor, boost::system::error_code>
+ : public awaitable_handler_base<Executor, void>
+{
+public:
+ using awaitable_handler_base<Executor, void>::awaitable_handler_base;
+
+ void operator()(const boost::system::error_code& ec)
+ {
+ this->frame()->attach_thread(this);
+ if (ec)
+ this->frame()->set_error(ec);
+ else
+ this->frame()->return_void();
+ this->frame()->pop_frame();
+ this->pump();
+ }
+};
+
+template <typename Executor>
+class awaitable_handler<Executor, std::exception_ptr>
+ : public awaitable_handler_base<Executor, void>
+{
+public:
+ using awaitable_handler_base<Executor, void>::awaitable_handler_base;
+
+ void operator()(std::exception_ptr ex)
+ {
+ this->frame()->attach_thread(this);
+ if (ex)
+ this->frame()->set_except(ex);
+ else
+ this->frame()->return_void();
+ this->frame()->pop_frame();
+ this->pump();
+ }
+};
+
+template <typename Executor, typename T>
+class awaitable_handler<Executor, T>
+ : public awaitable_handler_base<Executor, T>
+{
+public:
+ using awaitable_handler_base<Executor, T>::awaitable_handler_base;
+
+ template <typename Arg>
+ void operator()(Arg&& arg)
+ {
+ this->frame()->attach_thread(this);
+ this->frame()->return_value(std::forward<Arg>(arg));
+ this->frame()->pop_frame();
+ this->pump();
+ }
+};
+
+template <typename Executor, typename T>
+class awaitable_handler<Executor, boost::system::error_code, T>
+ : public awaitable_handler_base<Executor, T>
+{
+public:
+ using awaitable_handler_base<Executor, T>::awaitable_handler_base;
+
+ template <typename Arg>
+ void operator()(const boost::system::error_code& ec, Arg&& arg)
+ {
+ this->frame()->attach_thread(this);
+ if (ec)
+ this->frame()->set_error(ec);
+ else
+ this->frame()->return_value(std::forward<Arg>(arg));
+ this->frame()->pop_frame();
+ this->pump();
+ }
+};
+
+template <typename Executor, typename T>
+class awaitable_handler<Executor, std::exception_ptr, T>
+ : public awaitable_handler_base<Executor, T>
+{
+public:
+ using awaitable_handler_base<Executor, T>::awaitable_handler_base;
+
+ template <typename Arg>
+ void operator()(std::exception_ptr ex, Arg&& arg)
+ {
+ this->frame()->attach_thread(this);
+ if (ex)
+ this->frame()->set_except(ex);
+ else
+ this->frame()->return_value(std::forward<Arg>(arg));
+ this->frame()->pop_frame();
+ this->pump();
+ }
+};
+
+template <typename Executor, typename... Ts>
+class awaitable_handler
+ : public awaitable_handler_base<Executor, std::tuple<Ts...>>
+{
+public:
+ using awaitable_handler_base<Executor,
+ std::tuple<Ts...>>::awaitable_handler_base;
+
+ template <typename... Args>
+ void operator()(Args&&... args)
+ {
+ this->frame()->attach_thread(this);
+ this->frame()->return_values(std::forward<Args>(args)...);
+ this->frame()->pop_frame();
+ this->pump();
+ }
+};
+
+template <typename Executor, typename... Ts>
+class awaitable_handler<Executor, boost::system::error_code, Ts...>
+ : public awaitable_handler_base<Executor, std::tuple<Ts...>>
+{
+public:
+ using awaitable_handler_base<Executor,
+ std::tuple<Ts...>>::awaitable_handler_base;
+
+ template <typename... Args>
+ void operator()(const boost::system::error_code& ec, Args&&... args)
+ {
+ this->frame()->attach_thread(this);
+ if (ec)
+ this->frame()->set_error(ec);
+ else
+ this->frame()->return_values(std::forward<Args>(args)...);
+ this->frame()->pop_frame();
+ this->pump();
+ }
+};
+
+template <typename Executor, typename... Ts>
+class awaitable_handler<Executor, std::exception_ptr, Ts...>
+ : public awaitable_handler_base<Executor, std::tuple<Ts...>>
+{
+public:
+ using awaitable_handler_base<Executor,
+ std::tuple<Ts...>>::awaitable_handler_base;
+
+ template <typename... Args>
+ void operator()(std::exception_ptr ex, Args&&... args)
+ {
+ this->frame()->attach_thread(this);
+ if (ex)
+ this->frame()->set_except(ex);
+ else
+ this->frame()->return_values(std::forward<Args>(args)...);
+ this->frame()->pop_frame();
+ this->pump();
+ }
+};
+
+} // namespace detail
+
+#if !defined(GENERATING_DOCUMENTATION)
+
+template <typename Executor, typename R, typename... Args>
+class async_result<use_awaitable_t<Executor>, R(Args...)>
+{
+public:
+ typedef typename detail::awaitable_handler<
+ Executor, typename decay<Args>::type...> handler_type;
+ typedef typename handler_type::awaitable_type return_type;
+
+#if defined(_MSC_VER)
+ template <typename T>
+ static T dummy_return()
+ {
+ return std::move(*static_cast<T*>(nullptr));
+ }
+
+ template <>
+ static void dummy_return()
+ {
+ }
+#endif // defined(_MSC_VER)
+
+ template <typename Initiation, typename... InitArgs>
+ static return_type initiate(Initiation initiation,
+ use_awaitable_t<Executor>, InitArgs... args)
+ {
+ co_await [&](auto* frame)
+ {
+ handler_type handler(frame->detach_thread());
+ std::move(initiation)(std::move(handler), std::move(args)...);
+ return static_cast<handler_type*>(nullptr);
+ };
+
+ for (;;) {} // Never reached.
+#if defined(_MSC_VER)
+ co_return dummy_return<typename return_type::value_type>();
+#endif // defined(_MSC_VER)
+ }
+};
+
+#endif // !defined(GENERATING_DOCUMENTATION)
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_IMPL_USE_AWAITABLE_HPP
diff --git a/boost/asio/impl/use_future.hpp b/boost/asio/impl/use_future.hpp
index fd75a7c8e8..83fb74aecb 100644
--- a/boost/asio/impl/use_future.hpp
+++ b/boost/asio/impl/use_future.hpp
@@ -2,7 +2,7 @@
// impl/use_future.hpp
// ~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -879,56 +879,6 @@ public:
#endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
-#if !defined(BOOST_ASIO_NO_DEPRECATED)
-
-template <typename Allocator, typename Signature>
-struct handler_type<use_future_t<Allocator>, Signature>
-{
- typedef typename async_result<use_future_t<Allocator>,
- Signature>::completion_handler_type type;
-};
-
-template <typename Signature, typename Allocator>
-class async_result<detail::promise_handler<Signature, Allocator> >
- : public detail::promise_async_result<Signature, Allocator>
-{
-public:
- typedef typename detail::promise_async_result<
- Signature, Allocator>::return_type type;
-
- explicit async_result(
- typename detail::promise_async_result<
- Signature, Allocator>::completion_handler_type& h)
- : detail::promise_async_result<Signature, Allocator>(h)
- {
- }
-};
-
-template <typename Function, typename Allocator, typename Signature>
-struct handler_type<detail::packaged_token<Function, Allocator>, Signature>
-{
- typedef typename async_result<detail::packaged_token<Function, Allocator>,
- Signature>::completion_handler_type type;
-};
-
-template <typename Function, typename Allocator, typename Result>
-class async_result<detail::packaged_handler<Function, Allocator, Result> >
- : public detail::packaged_async_result<Function, Allocator, Result>
-{
-public:
- typedef typename detail::packaged_async_result<
- Function, Allocator, Result>::return_type type;
-
- explicit async_result(
- typename detail::packaged_async_result<
- Function, Allocator, Result>::completion_handler_type& h)
- : detail::packaged_async_result<Function, Allocator, Result>(h)
- {
- }
-};
-
-#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
-
#endif // !defined(GENERATING_DOCUMENTATION)
} // namespace asio
diff --git a/boost/asio/impl/write.hpp b/boost/asio/impl/write.hpp
index 0be48b89f4..96243591ec 100644
--- a/boost/asio/impl/write.hpp
+++ b/boost/asio/impl/write.hpp
@@ -2,7 +2,7 @@
// impl/write.hpp
// ~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -28,6 +28,7 @@
#include <boost/asio/detail/handler_cont_helpers.hpp>
#include <boost/asio/detail/handler_invoke_helpers.hpp>
#include <boost/asio/detail/handler_type_requirements.hpp>
+#include <boost/asio/detail/non_const_lvalue.hpp>
#include <boost/asio/detail/throw_error.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -67,7 +68,8 @@ inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,
>::type*)
{
return detail::write_buffer_sequence(s, buffers,
- boost::asio::buffer_sequence_begin(buffers), completion_condition, ec);
+ boost::asio::buffer_sequence_begin(buffers),
+ BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);
}
template <typename SyncWriteStream, typename ConstBufferSequence>
@@ -101,68 +103,76 @@ inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,
>::type*)
{
boost::system::error_code ec;
- std::size_t bytes_transferred = write(s, buffers, completion_condition, ec);
+ std::size_t bytes_transferred = write(s, buffers,
+ BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);
boost::asio::detail::throw_error(ec, "write");
return bytes_transferred;
}
-template <typename SyncWriteStream, typename DynamicBuffer,
+#if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
+
+template <typename SyncWriteStream, typename DynamicBuffer_v1,
typename CompletionCondition>
std::size_t write(SyncWriteStream& s,
- BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
+ BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
CompletionCondition completion_condition, boost::system::error_code& ec,
typename enable_if<
- is_dynamic_buffer<typename decay<DynamicBuffer>::type>::value
+ is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
+ && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
>::type*)
{
- typename decay<DynamicBuffer>::type b(
- BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers));
+ typename decay<DynamicBuffer_v1>::type b(
+ BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers));
- std::size_t bytes_transferred = write(s, b.data(), completion_condition, ec);
+ std::size_t bytes_transferred = write(s, b.data(),
+ BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);
b.consume(bytes_transferred);
return bytes_transferred;
}
-template <typename SyncWriteStream, typename DynamicBuffer>
+template <typename SyncWriteStream, typename DynamicBuffer_v1>
inline std::size_t write(SyncWriteStream& s,
- BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
+ BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
typename enable_if<
- is_dynamic_buffer<typename decay<DynamicBuffer>::type>::value
+ is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
+ && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
>::type*)
{
boost::system::error_code ec;
std::size_t bytes_transferred = write(s,
- BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers),
+ BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),
transfer_all(), ec);
boost::asio::detail::throw_error(ec, "write");
return bytes_transferred;
}
-template <typename SyncWriteStream, typename DynamicBuffer>
+template <typename SyncWriteStream, typename DynamicBuffer_v1>
inline std::size_t write(SyncWriteStream& s,
- BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
+ BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
boost::system::error_code& ec,
typename enable_if<
- is_dynamic_buffer<typename decay<DynamicBuffer>::type>::value
+ is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
+ && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
>::type*)
{
- return write(s, BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers),
+ return write(s, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),
transfer_all(), ec);
}
-template <typename SyncWriteStream, typename DynamicBuffer,
+template <typename SyncWriteStream, typename DynamicBuffer_v1,
typename CompletionCondition>
inline std::size_t write(SyncWriteStream& s,
- BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
+ BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
CompletionCondition completion_condition,
typename enable_if<
- is_dynamic_buffer<typename decay<DynamicBuffer>::type>::value
+ is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
+ && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
>::type*)
{
boost::system::error_code ec;
std::size_t bytes_transferred = write(s,
- BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers),
- completion_condition, ec);
+ BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),
+ BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);
boost::asio::detail::throw_error(ec, "write");
return bytes_transferred;
}
@@ -176,7 +186,8 @@ inline std::size_t write(SyncWriteStream& s,
boost::asio::basic_streambuf<Allocator>& b,
CompletionCondition completion_condition, boost::system::error_code& ec)
{
- return write(s, basic_streambuf_ref<Allocator>(b), completion_condition, ec);
+ return write(s, basic_streambuf_ref<Allocator>(b),
+ BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);
}
template <typename SyncWriteStream, typename Allocator>
@@ -200,11 +211,68 @@ inline std::size_t write(SyncWriteStream& s,
boost::asio::basic_streambuf<Allocator>& b,
CompletionCondition completion_condition)
{
- return write(s, basic_streambuf_ref<Allocator>(b), completion_condition);
+ return write(s, basic_streambuf_ref<Allocator>(b),
+ BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition));
}
#endif // !defined(BOOST_ASIO_NO_IOSTREAM)
#endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
+#endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
+
+template <typename SyncWriteStream, typename DynamicBuffer_v2,
+ typename CompletionCondition>
+std::size_t write(SyncWriteStream& s, DynamicBuffer_v2 buffers,
+ CompletionCondition completion_condition, boost::system::error_code& ec,
+ typename enable_if<
+ is_dynamic_buffer_v2<DynamicBuffer_v2>::value
+ >::type*)
+{
+ std::size_t bytes_transferred = write(s, buffers.data(0, buffers.size()),
+ BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);
+ buffers.consume(bytes_transferred);
+ return bytes_transferred;
+}
+
+template <typename SyncWriteStream, typename DynamicBuffer_v2>
+inline std::size_t write(SyncWriteStream& s, DynamicBuffer_v2 buffers,
+ typename enable_if<
+ is_dynamic_buffer_v2<DynamicBuffer_v2>::value
+ >::type*)
+{
+ boost::system::error_code ec;
+ std::size_t bytes_transferred = write(s,
+ BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),
+ transfer_all(), ec);
+ boost::asio::detail::throw_error(ec, "write");
+ return bytes_transferred;
+}
+
+template <typename SyncWriteStream, typename DynamicBuffer_v2>
+inline std::size_t write(SyncWriteStream& s, DynamicBuffer_v2 buffers,
+ boost::system::error_code& ec,
+ typename enable_if<
+ is_dynamic_buffer_v2<DynamicBuffer_v2>::value
+ >::type*)
+{
+ return write(s, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),
+ transfer_all(), ec);
+}
+
+template <typename SyncWriteStream, typename DynamicBuffer_v2,
+ typename CompletionCondition>
+inline std::size_t write(SyncWriteStream& s, DynamicBuffer_v2 buffers,
+ CompletionCondition completion_condition,
+ typename enable_if<
+ is_dynamic_buffer_v2<DynamicBuffer_v2>::value
+ >::type*)
+{
+ boost::system::error_code ec;
+ std::size_t bytes_transferred = write(s,
+ BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),
+ BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);
+ boost::asio::detail::throw_error(ec, "write");
+ return bytes_transferred;
+}
namespace detail
{
@@ -216,7 +284,7 @@ namespace detail
{
public:
write_op(AsyncWriteStream& stream, const ConstBufferSequence& buffers,
- CompletionCondition completion_condition, WriteHandler& handler)
+ CompletionCondition& completion_condition, WriteHandler& handler)
: detail::base_from_completion_cond<
CompletionCondition>(completion_condition),
stream_(stream),
@@ -237,9 +305,11 @@ namespace detail
}
write_op(write_op&& other)
- : detail::base_from_completion_cond<CompletionCondition>(other),
+ : detail::base_from_completion_cond<CompletionCondition>(
+ BOOST_ASIO_MOVE_CAST(detail::base_from_completion_cond<
+ CompletionCondition>)(other)),
stream_(other.stream_),
- buffers_(other.buffers_),
+ buffers_(BOOST_ASIO_MOVE_CAST(buffers_type)(other.buffers_)),
start_(other.start_),
handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(other.handler_))
{
@@ -270,9 +340,11 @@ namespace detail
}
//private:
+ typedef boost::asio::detail::consuming_buffers<const_buffer,
+ ConstBufferSequence, ConstBufferIterator> buffers_type;
+
AsyncWriteStream& stream_;
- boost::asio::detail::consuming_buffers<const_buffer,
- ConstBufferSequence, ConstBufferIterator> buffers_;
+ buffers_type buffers_;
int start_;
WriteHandler handler_;
};
@@ -338,7 +410,7 @@ namespace detail
typename WriteHandler>
inline void start_write_buffer_sequence_op(AsyncWriteStream& stream,
const ConstBufferSequence& buffers, const ConstBufferIterator&,
- CompletionCondition completion_condition, WriteHandler& handler)
+ CompletionCondition& completion_condition, WriteHandler& handler)
{
detail::write_op<AsyncWriteStream, ConstBufferSequence,
ConstBufferIterator, CompletionCondition, WriteHandler>(
@@ -346,6 +418,25 @@ namespace detail
boost::system::error_code(), 0, 1);
}
+ struct initiate_async_write_buffer_sequence
+ {
+ template <typename WriteHandler, typename AsyncWriteStream,
+ typename ConstBufferSequence, typename CompletionCondition>
+ void operator()(BOOST_ASIO_MOVE_ARG(WriteHandler) handler,
+ AsyncWriteStream* s, const ConstBufferSequence& buffers,
+ BOOST_ASIO_MOVE_ARG(CompletionCondition) completion_cond) const
+ {
+ // If you get an error on the following line it means that your handler
+ // does not meet the documented type requirements for a WriteHandler.
+ BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
+
+ non_const_lvalue<WriteHandler> handler2(handler);
+ non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);
+ start_write_buffer_sequence_op(*s, buffers,
+ boost::asio::buffer_sequence_begin(buffers),
+ completion_cond2.value, handler2.value);
+ }
+ };
} // namespace detail
#if !defined(GENERATING_DOCUMENTATION)
@@ -401,18 +492,10 @@ async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers,
is_const_buffer_sequence<ConstBufferSequence>::value
>::type*)
{
- // If you get an error on the following line it means that your handler does
- // not meet the documented type requirements for a WriteHandler.
- BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
-
- async_completion<WriteHandler,
- void (boost::system::error_code, std::size_t)> init(handler);
-
- detail::start_write_buffer_sequence_op(s, buffers,
- boost::asio::buffer_sequence_begin(buffers), completion_condition,
- init.completion_handler);
-
- return init.result.get();
+ return async_initiate<WriteHandler,
+ void (boost::system::error_code, std::size_t)>(
+ detail::initiate_async_write_buffer_sequence(), handler, &s, buffers,
+ BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition));
}
template <typename AsyncWriteStream, typename ConstBufferSequence,
@@ -425,31 +508,25 @@ async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers,
is_const_buffer_sequence<ConstBufferSequence>::value
>::type*)
{
- // If you get an error on the following line it means that your handler does
- // not meet the documented type requirements for a WriteHandler.
- BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
-
- async_completion<WriteHandler,
- void (boost::system::error_code, std::size_t)> init(handler);
-
- detail::start_write_buffer_sequence_op(s, buffers,
- boost::asio::buffer_sequence_begin(buffers), transfer_all(),
- init.completion_handler);
-
- return init.result.get();
+ return async_initiate<WriteHandler,
+ void (boost::system::error_code, std::size_t)>(
+ detail::initiate_async_write_buffer_sequence(),
+ handler, &s, buffers, transfer_all());
}
+#if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
+
namespace detail
{
- template <typename AsyncWriteStream, typename DynamicBuffer,
+ template <typename AsyncWriteStream, typename DynamicBuffer_v1,
typename CompletionCondition, typename WriteHandler>
- class write_dynbuf_op
+ class write_dynbuf_v1_op
{
public:
template <typename BufferSequence>
- write_dynbuf_op(AsyncWriteStream& stream,
+ write_dynbuf_v1_op(AsyncWriteStream& stream,
BOOST_ASIO_MOVE_ARG(BufferSequence) buffers,
- CompletionCondition completion_condition, WriteHandler& handler)
+ CompletionCondition& completion_condition, WriteHandler& handler)
: stream_(stream),
buffers_(BOOST_ASIO_MOVE_CAST(BufferSequence)(buffers)),
completion_condition_(
@@ -459,7 +536,7 @@ namespace detail
}
#if defined(BOOST_ASIO_HAS_MOVE)
- write_dynbuf_op(const write_dynbuf_op& other)
+ write_dynbuf_v1_op(const write_dynbuf_v1_op& other)
: stream_(other.stream_),
buffers_(other.buffers_),
completion_condition_(other.completion_condition_),
@@ -467,9 +544,9 @@ namespace detail
{
}
- write_dynbuf_op(write_dynbuf_op&& other)
+ write_dynbuf_v1_op(write_dynbuf_v1_op&& other)
: stream_(other.stream_),
- buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer)(other.buffers_)),
+ buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(other.buffers_)),
completion_condition_(
BOOST_ASIO_MOVE_CAST(CompletionCondition)(
other.completion_condition_)),
@@ -484,8 +561,9 @@ namespace detail
switch (start)
{
case 1:
- async_write(stream_, buffers_.data(), completion_condition_,
- BOOST_ASIO_MOVE_CAST(write_dynbuf_op)(*this));
+ async_write(stream_, buffers_.data(),
+ BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition_),
+ BOOST_ASIO_MOVE_CAST(write_dynbuf_v1_op)(*this));
return; default:
buffers_.consume(bytes_transferred);
handler_(ec, static_cast<const std::size_t&>(bytes_transferred));
@@ -494,35 +572,35 @@ namespace detail
//private:
AsyncWriteStream& stream_;
- DynamicBuffer buffers_;
+ DynamicBuffer_v1 buffers_;
CompletionCondition completion_condition_;
WriteHandler handler_;
};
- template <typename AsyncWriteStream, typename DynamicBuffer,
+ template <typename AsyncWriteStream, typename DynamicBuffer_v1,
typename CompletionCondition, typename WriteHandler>
inline void* asio_handler_allocate(std::size_t size,
- write_dynbuf_op<AsyncWriteStream, DynamicBuffer,
+ write_dynbuf_v1_op<AsyncWriteStream, DynamicBuffer_v1,
CompletionCondition, WriteHandler>* this_handler)
{
return boost_asio_handler_alloc_helpers::allocate(
size, this_handler->handler_);
}
- template <typename AsyncWriteStream, typename DynamicBuffer,
+ template <typename AsyncWriteStream, typename DynamicBuffer_v1,
typename CompletionCondition, typename WriteHandler>
inline void asio_handler_deallocate(void* pointer, std::size_t size,
- write_dynbuf_op<AsyncWriteStream, DynamicBuffer,
+ write_dynbuf_v1_op<AsyncWriteStream, DynamicBuffer_v1,
CompletionCondition, WriteHandler>* this_handler)
{
boost_asio_handler_alloc_helpers::deallocate(
pointer, size, this_handler->handler_);
}
- template <typename AsyncWriteStream, typename DynamicBuffer,
+ template <typename AsyncWriteStream, typename DynamicBuffer_v1,
typename CompletionCondition, typename WriteHandler>
inline bool asio_handler_is_continuation(
- write_dynbuf_op<AsyncWriteStream, DynamicBuffer,
+ write_dynbuf_v1_op<AsyncWriteStream, DynamicBuffer_v1,
CompletionCondition, WriteHandler>* this_handler)
{
return boost_asio_handler_cont_helpers::is_continuation(
@@ -530,10 +608,10 @@ namespace detail
}
template <typename Function, typename AsyncWriteStream,
- typename DynamicBuffer, typename CompletionCondition,
+ typename DynamicBuffer_v1, typename CompletionCondition,
typename WriteHandler>
inline void asio_handler_invoke(Function& function,
- write_dynbuf_op<AsyncWriteStream, DynamicBuffer,
+ write_dynbuf_v1_op<AsyncWriteStream, DynamicBuffer_v1,
CompletionCondition, WriteHandler>* this_handler)
{
boost_asio_handler_invoke_helpers::invoke(
@@ -541,49 +619,72 @@ namespace detail
}
template <typename Function, typename AsyncWriteStream,
- typename DynamicBuffer, typename CompletionCondition,
+ typename DynamicBuffer_v1, typename CompletionCondition,
typename WriteHandler>
inline void asio_handler_invoke(const Function& function,
- write_dynbuf_op<AsyncWriteStream, DynamicBuffer,
+ write_dynbuf_v1_op<AsyncWriteStream, DynamicBuffer_v1,
CompletionCondition, WriteHandler>* this_handler)
{
boost_asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
}
+
+ struct initiate_async_write_dynbuf_v1
+ {
+ template <typename WriteHandler, typename AsyncWriteStream,
+ typename DynamicBuffer_v1, typename CompletionCondition>
+ void operator()(BOOST_ASIO_MOVE_ARG(WriteHandler) handler,
+ AsyncWriteStream* s, BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
+ BOOST_ASIO_MOVE_ARG(CompletionCondition) completion_cond) const
+ {
+ // If you get an error on the following line it means that your handler
+ // does not meet the documented type requirements for a WriteHandler.
+ BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
+
+ non_const_lvalue<WriteHandler> handler2(handler);
+ non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);
+ write_dynbuf_v1_op<AsyncWriteStream,
+ typename decay<DynamicBuffer_v1>::type,
+ CompletionCondition, typename decay<WriteHandler>::type>(
+ *s, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),
+ completion_cond2.value, handler2.value)(
+ boost::system::error_code(), 0, 1);
+ }
+ };
} // namespace detail
#if !defined(GENERATING_DOCUMENTATION)
-template <typename AsyncWriteStream, typename DynamicBuffer,
+template <typename AsyncWriteStream, typename DynamicBuffer_v1,
typename CompletionCondition, typename WriteHandler, typename Allocator>
struct associated_allocator<
- detail::write_dynbuf_op<AsyncWriteStream,
- DynamicBuffer, CompletionCondition, WriteHandler>,
+ detail::write_dynbuf_v1_op<AsyncWriteStream,
+ DynamicBuffer_v1, CompletionCondition, WriteHandler>,
Allocator>
{
typedef typename associated_allocator<WriteHandler, Allocator>::type type;
static type get(
- const detail::write_dynbuf_op<AsyncWriteStream,
- DynamicBuffer, CompletionCondition, WriteHandler>& h,
+ const detail::write_dynbuf_v1_op<AsyncWriteStream,
+ DynamicBuffer_v1, CompletionCondition, WriteHandler>& h,
const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
{
return associated_allocator<WriteHandler, Allocator>::get(h.handler_, a);
}
};
-template <typename AsyncWriteStream, typename DynamicBuffer,
+template <typename AsyncWriteStream, typename DynamicBuffer_v1,
typename CompletionCondition, typename WriteHandler, typename Executor>
struct associated_executor<
- detail::write_dynbuf_op<AsyncWriteStream,
- DynamicBuffer, CompletionCondition, WriteHandler>,
+ detail::write_dynbuf_v1_op<AsyncWriteStream,
+ DynamicBuffer_v1, CompletionCondition, WriteHandler>,
Executor>
{
typedef typename associated_executor<WriteHandler, Executor>::type type;
static type get(
- const detail::write_dynbuf_op<AsyncWriteStream,
- DynamicBuffer, CompletionCondition, WriteHandler>& h,
+ const detail::write_dynbuf_v1_op<AsyncWriteStream,
+ DynamicBuffer_v1, CompletionCondition, WriteHandler>& h,
const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
{
return associated_executor<WriteHandler, Executor>::get(h.handler_, ex);
@@ -593,49 +694,40 @@ struct associated_executor<
#endif // !defined(GENERATING_DOCUMENTATION)
template <typename AsyncWriteStream,
- typename DynamicBuffer, typename WriteHandler>
+ typename DynamicBuffer_v1, typename WriteHandler>
inline BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
void (boost::system::error_code, std::size_t))
async_write(AsyncWriteStream& s,
- BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
+ BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
BOOST_ASIO_MOVE_ARG(WriteHandler) handler,
typename enable_if<
- is_dynamic_buffer<typename decay<DynamicBuffer>::type>::value
+ is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
+ && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
>::type*)
{
return async_write(s,
- BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers),
+ BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),
transfer_all(), BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
}
-template <typename AsyncWriteStream, typename DynamicBuffer,
+template <typename AsyncWriteStream, typename DynamicBuffer_v1,
typename CompletionCondition, typename WriteHandler>
inline BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
void (boost::system::error_code, std::size_t))
async_write(AsyncWriteStream& s,
- BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
+ BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
CompletionCondition completion_condition,
BOOST_ASIO_MOVE_ARG(WriteHandler) handler,
typename enable_if<
- is_dynamic_buffer<typename decay<DynamicBuffer>::type>::value
+ is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
+ && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
>::type*)
{
- // If you get an error on the following line it means that your handler does
- // not meet the documented type requirements for a WriteHandler.
- BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
-
- async_completion<WriteHandler,
- void (boost::system::error_code, std::size_t)> init(handler);
-
- detail::write_dynbuf_op<AsyncWriteStream,
- typename decay<DynamicBuffer>::type,
- CompletionCondition, BOOST_ASIO_HANDLER_TYPE(
- WriteHandler, void (boost::system::error_code, std::size_t))>(
- s, BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers),
- completion_condition, init.completion_handler)(
- boost::system::error_code(), 0, 1);
-
- return init.result.get();
+ return async_initiate<WriteHandler,
+ void (boost::system::error_code, std::size_t)>(
+ detail::initiate_async_write_dynbuf_v1(), handler, &s,
+ BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),
+ BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition));
}
#if !defined(BOOST_ASIO_NO_EXTENSIONS)
@@ -662,11 +754,223 @@ async_write(AsyncWriteStream& s,
BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
{
return async_write(s, basic_streambuf_ref<Allocator>(b),
- completion_condition, BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
+ BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition),
+ BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
}
#endif // !defined(BOOST_ASIO_NO_IOSTREAM)
#endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
+#endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
+
+namespace detail
+{
+ template <typename AsyncWriteStream, typename DynamicBuffer_v2,
+ typename CompletionCondition, typename WriteHandler>
+ class write_dynbuf_v2_op
+ {
+ public:
+ template <typename BufferSequence>
+ write_dynbuf_v2_op(AsyncWriteStream& stream,
+ BOOST_ASIO_MOVE_ARG(BufferSequence) buffers,
+ CompletionCondition& completion_condition, WriteHandler& handler)
+ : stream_(stream),
+ buffers_(BOOST_ASIO_MOVE_CAST(BufferSequence)(buffers)),
+ completion_condition_(
+ BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition)),
+ handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(handler))
+ {
+ }
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+ write_dynbuf_v2_op(const write_dynbuf_v2_op& other)
+ : stream_(other.stream_),
+ buffers_(other.buffers_),
+ completion_condition_(other.completion_condition_),
+ handler_(other.handler_)
+ {
+ }
+
+ write_dynbuf_v2_op(write_dynbuf_v2_op&& other)
+ : stream_(other.stream_),
+ buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(other.buffers_)),
+ completion_condition_(
+ BOOST_ASIO_MOVE_CAST(CompletionCondition)(
+ other.completion_condition_)),
+ handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(other.handler_))
+ {
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+ void operator()(const boost::system::error_code& ec,
+ std::size_t bytes_transferred, int start = 0)
+ {
+ switch (start)
+ {
+ case 1:
+ async_write(stream_, buffers_.data(0, buffers_.size()),
+ BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition_),
+ BOOST_ASIO_MOVE_CAST(write_dynbuf_v2_op)(*this));
+ return; default:
+ buffers_.consume(bytes_transferred);
+ handler_(ec, static_cast<const std::size_t&>(bytes_transferred));
+ }
+ }
+
+ //private:
+ AsyncWriteStream& stream_;
+ DynamicBuffer_v2 buffers_;
+ CompletionCondition completion_condition_;
+ WriteHandler handler_;
+ };
+
+ template <typename AsyncWriteStream, typename DynamicBuffer_v2,
+ typename CompletionCondition, typename WriteHandler>
+ inline void* asio_handler_allocate(std::size_t size,
+ write_dynbuf_v2_op<AsyncWriteStream, DynamicBuffer_v2,
+ CompletionCondition, WriteHandler>* this_handler)
+ {
+ return boost_asio_handler_alloc_helpers::allocate(
+ size, this_handler->handler_);
+ }
+
+ template <typename AsyncWriteStream, typename DynamicBuffer_v2,
+ typename CompletionCondition, typename WriteHandler>
+ inline void asio_handler_deallocate(void* pointer, std::size_t size,
+ write_dynbuf_v2_op<AsyncWriteStream, DynamicBuffer_v2,
+ CompletionCondition, WriteHandler>* this_handler)
+ {
+ boost_asio_handler_alloc_helpers::deallocate(
+ pointer, size, this_handler->handler_);
+ }
+
+ template <typename AsyncWriteStream, typename DynamicBuffer_v2,
+ typename CompletionCondition, typename WriteHandler>
+ inline bool asio_handler_is_continuation(
+ write_dynbuf_v2_op<AsyncWriteStream, DynamicBuffer_v2,
+ CompletionCondition, WriteHandler>* this_handler)
+ {
+ return boost_asio_handler_cont_helpers::is_continuation(
+ this_handler->handler_);
+ }
+
+ template <typename Function, typename AsyncWriteStream,
+ typename DynamicBuffer_v2, typename CompletionCondition,
+ typename WriteHandler>
+ inline void asio_handler_invoke(Function& function,
+ write_dynbuf_v2_op<AsyncWriteStream, DynamicBuffer_v2,
+ CompletionCondition, WriteHandler>* this_handler)
+ {
+ boost_asio_handler_invoke_helpers::invoke(
+ function, this_handler->handler_);
+ }
+
+ template <typename Function, typename AsyncWriteStream,
+ typename DynamicBuffer_v2, typename CompletionCondition,
+ typename WriteHandler>
+ inline void asio_handler_invoke(const Function& function,
+ write_dynbuf_v2_op<AsyncWriteStream, DynamicBuffer_v2,
+ CompletionCondition, WriteHandler>* this_handler)
+ {
+ boost_asio_handler_invoke_helpers::invoke(
+ function, this_handler->handler_);
+ }
+
+ struct initiate_async_write_dynbuf_v2
+ {
+ template <typename WriteHandler, typename AsyncWriteStream,
+ typename DynamicBuffer_v2, typename CompletionCondition>
+ void operator()(BOOST_ASIO_MOVE_ARG(WriteHandler) handler,
+ AsyncWriteStream* s, BOOST_ASIO_MOVE_ARG(DynamicBuffer_v2) buffers,
+ BOOST_ASIO_MOVE_ARG(CompletionCondition) completion_cond) const
+ {
+ // If you get an error on the following line it means that your handler
+ // does not meet the documented type requirements for a WriteHandler.
+ BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
+
+ non_const_lvalue<WriteHandler> handler2(handler);
+ non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);
+ write_dynbuf_v2_op<AsyncWriteStream,
+ typename decay<DynamicBuffer_v2>::type,
+ CompletionCondition, typename decay<WriteHandler>::type>(
+ *s, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),
+ completion_cond2.value, handler2.value)(
+ boost::system::error_code(), 0, 1);
+ }
+ };
+} // namespace detail
+
+#if !defined(GENERATING_DOCUMENTATION)
+
+template <typename AsyncWriteStream, typename DynamicBuffer_v2,
+ typename CompletionCondition, typename WriteHandler, typename Allocator>
+struct associated_allocator<
+ detail::write_dynbuf_v2_op<AsyncWriteStream,
+ DynamicBuffer_v2, CompletionCondition, WriteHandler>,
+ Allocator>
+{
+ typedef typename associated_allocator<WriteHandler, Allocator>::type type;
+
+ static type get(
+ const detail::write_dynbuf_v2_op<AsyncWriteStream,
+ DynamicBuffer_v2, CompletionCondition, WriteHandler>& h,
+ const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
+ {
+ return associated_allocator<WriteHandler, Allocator>::get(h.handler_, a);
+ }
+};
+
+template <typename AsyncWriteStream, typename DynamicBuffer_v2,
+ typename CompletionCondition, typename WriteHandler, typename Executor>
+struct associated_executor<
+ detail::write_dynbuf_v2_op<AsyncWriteStream,
+ DynamicBuffer_v2, CompletionCondition, WriteHandler>,
+ Executor>
+{
+ typedef typename associated_executor<WriteHandler, Executor>::type type;
+
+ static type get(
+ const detail::write_dynbuf_v2_op<AsyncWriteStream,
+ DynamicBuffer_v2, CompletionCondition, WriteHandler>& h,
+ const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
+ {
+ return associated_executor<WriteHandler, Executor>::get(h.handler_, ex);
+ }
+};
+
+#endif // !defined(GENERATING_DOCUMENTATION)
+
+template <typename AsyncWriteStream,
+ typename DynamicBuffer_v2, typename WriteHandler>
+inline BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
+ void (boost::system::error_code, std::size_t))
+async_write(AsyncWriteStream& s, DynamicBuffer_v2 buffers,
+ BOOST_ASIO_MOVE_ARG(WriteHandler) handler,
+ typename enable_if<
+ is_dynamic_buffer_v2<DynamicBuffer_v2>::value
+ >::type*)
+{
+ return async_write(s,
+ BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),
+ transfer_all(), BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
+}
+
+template <typename AsyncWriteStream, typename DynamicBuffer_v2,
+ typename CompletionCondition, typename WriteHandler>
+inline BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
+ void (boost::system::error_code, std::size_t))
+async_write(AsyncWriteStream& s, DynamicBuffer_v2 buffers,
+ CompletionCondition completion_condition,
+ BOOST_ASIO_MOVE_ARG(WriteHandler) handler,
+ typename enable_if<
+ is_dynamic_buffer_v2<DynamicBuffer_v2>::value
+ >::type*)
+{
+ return async_initiate<WriteHandler,
+ void (boost::system::error_code, std::size_t)>(
+ detail::initiate_async_write_dynbuf_v2(), handler, &s,
+ BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),
+ BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition));
+}
} // namespace asio
} // namespace boost
diff --git a/boost/asio/impl/write_at.hpp b/boost/asio/impl/write_at.hpp
index 6b597d2085..3cad9c5b50 100644
--- a/boost/asio/impl/write_at.hpp
+++ b/boost/asio/impl/write_at.hpp
@@ -2,7 +2,7 @@
// impl/write_at.hpp
// ~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -28,6 +28,7 @@
#include <boost/asio/detail/handler_cont_helpers.hpp>
#include <boost/asio/detail/handler_invoke_helpers.hpp>
#include <boost/asio/detail/handler_type_requirements.hpp>
+#include <boost/asio/detail/non_const_lvalue.hpp>
#include <boost/asio/detail/throw_error.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -69,7 +70,8 @@ std::size_t write_at(SyncRandomAccessWriteDevice& d,
CompletionCondition completion_condition, boost::system::error_code& ec)
{
return detail::write_at_buffer_sequence(d, offset, buffers,
- boost::asio::buffer_sequence_begin(buffers), completion_condition, ec);
+ boost::asio::buffer_sequence_begin(buffers),
+ BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);
}
template <typename SyncRandomAccessWriteDevice, typename ConstBufferSequence>
@@ -98,8 +100,8 @@ inline std::size_t write_at(SyncRandomAccessWriteDevice& d,
CompletionCondition completion_condition)
{
boost::system::error_code ec;
- std::size_t bytes_transferred = write_at(
- d, offset, buffers, completion_condition, ec);
+ std::size_t bytes_transferred = write_at(d, offset, buffers,
+ BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);
boost::asio::detail::throw_error(ec, "write_at");
return bytes_transferred;
}
@@ -113,8 +115,8 @@ std::size_t write_at(SyncRandomAccessWriteDevice& d,
uint64_t offset, boost::asio::basic_streambuf<Allocator>& b,
CompletionCondition completion_condition, boost::system::error_code& ec)
{
- std::size_t bytes_transferred = write_at(
- d, offset, b.data(), completion_condition, ec);
+ std::size_t bytes_transferred = write_at(d, offset, b.data(),
+ BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);
b.consume(bytes_transferred);
return bytes_transferred;
}
@@ -144,8 +146,8 @@ inline std::size_t write_at(SyncRandomAccessWriteDevice& d,
CompletionCondition completion_condition)
{
boost::system::error_code ec;
- std::size_t bytes_transferred = write_at(
- d, offset, b, completion_condition, ec);
+ std::size_t bytes_transferred = write_at(d, offset, b,
+ BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);
boost::asio::detail::throw_error(ec, "write_at");
return bytes_transferred;
}
@@ -164,7 +166,7 @@ namespace detail
public:
write_at_op(AsyncRandomAccessWriteDevice& device,
uint64_t offset, const ConstBufferSequence& buffers,
- CompletionCondition completion_condition, WriteHandler& handler)
+ CompletionCondition& completion_condition, WriteHandler& handler)
: detail::base_from_completion_cond<
CompletionCondition>(completion_condition),
device_(device),
@@ -187,10 +189,12 @@ namespace detail
}
write_at_op(write_at_op&& other)
- : detail::base_from_completion_cond<CompletionCondition>(other),
+ : detail::base_from_completion_cond<CompletionCondition>(
+ BOOST_ASIO_MOVE_CAST(detail::base_from_completion_cond<
+ CompletionCondition>)(other)),
device_(other.device_),
offset_(other.offset_),
- buffers_(other.buffers_),
+ buffers_(BOOST_ASIO_MOVE_CAST(buffers_type)(other.buffers_)),
start_(other.start_),
handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(other.handler_))
{
@@ -222,10 +226,12 @@ namespace detail
}
//private:
+ typedef boost::asio::detail::consuming_buffers<const_buffer,
+ ConstBufferSequence, ConstBufferIterator> buffers_type;
+
AsyncRandomAccessWriteDevice& device_;
uint64_t offset_;
- boost::asio::detail::consuming_buffers<const_buffer,
- ConstBufferSequence, ConstBufferIterator> buffers_;
+ buffers_type buffers_;
int start_;
WriteHandler handler_;
};
@@ -291,7 +297,7 @@ namespace detail
typename CompletionCondition, typename WriteHandler>
inline void start_write_at_buffer_sequence_op(AsyncRandomAccessWriteDevice& d,
uint64_t offset, const ConstBufferSequence& buffers,
- const ConstBufferIterator&, CompletionCondition completion_condition,
+ const ConstBufferIterator&, CompletionCondition& completion_condition,
WriteHandler& handler)
{
detail::write_at_op<AsyncRandomAccessWriteDevice, ConstBufferSequence,
@@ -299,6 +305,27 @@ namespace detail
d, offset, buffers, completion_condition, handler)(
boost::system::error_code(), 0, 1);
}
+
+ struct initiate_async_write_at_buffer_sequence
+ {
+ template <typename WriteHandler, typename AsyncRandomAccessWriteDevice,
+ typename ConstBufferSequence, typename CompletionCondition>
+ void operator()(BOOST_ASIO_MOVE_ARG(WriteHandler) handler,
+ AsyncRandomAccessWriteDevice* d, uint64_t offset,
+ const ConstBufferSequence& buffers,
+ BOOST_ASIO_MOVE_ARG(CompletionCondition) completion_cond) const
+ {
+ // If you get an error on the following line it means that your handler
+ // does not meet the documented type requirements for a WriteHandler.
+ BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
+
+ non_const_lvalue<WriteHandler> handler2(handler);
+ non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);
+ start_write_at_buffer_sequence_op(*d, offset, buffers,
+ boost::asio::buffer_sequence_begin(buffers),
+ completion_cond2.value, handler2.value);
+ }
+ };
} // namespace detail
#if !defined(GENERATING_DOCUMENTATION)
@@ -354,18 +381,10 @@ async_write_at(AsyncRandomAccessWriteDevice& d,
CompletionCondition completion_condition,
BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
{
- // If you get an error on the following line it means that your handler does
- // not meet the documented type requirements for a WriteHandler.
- BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
-
- async_completion<WriteHandler,
- void (boost::system::error_code, std::size_t)> init(handler);
-
- detail::start_write_at_buffer_sequence_op(d, offset, buffers,
- boost::asio::buffer_sequence_begin(buffers), completion_condition,
- init.completion_handler);
-
- return init.result.get();
+ return async_initiate<WriteHandler,
+ void (boost::system::error_code, std::size_t)>(
+ detail::initiate_async_write_at_buffer_sequence(), handler, &d, offset,
+ buffers, BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition));
}
template <typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence,
@@ -376,18 +395,10 @@ async_write_at(AsyncRandomAccessWriteDevice& d,
uint64_t offset, const ConstBufferSequence& buffers,
BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
{
- // If you get an error on the following line it means that your handler does
- // not meet the documented type requirements for a WriteHandler.
- BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
-
- async_completion<WriteHandler,
- void (boost::system::error_code, std::size_t)> init(handler);
-
- detail::start_write_at_buffer_sequence_op(d, offset, buffers,
- boost::asio::buffer_sequence_begin(buffers), transfer_all(),
- init.completion_handler);
-
- return init.result.get();
+ return async_initiate<WriteHandler,
+ void (boost::system::error_code, std::size_t)>(
+ detail::initiate_async_write_at_buffer_sequence(),
+ handler, &d, offset, buffers, transfer_all());
}
#if !defined(BOOST_ASIO_NO_EXTENSIONS)
@@ -473,13 +484,26 @@ namespace detail
function, this_handler->handler_);
}
- template <typename Allocator, typename WriteHandler>
- inline write_at_streambuf_op<Allocator, WriteHandler>
- make_write_at_streambuf_op(
- boost::asio::basic_streambuf<Allocator>& b, WriteHandler handler)
+ struct initiate_async_write_at_streambuf
{
- return write_at_streambuf_op<Allocator, WriteHandler>(b, handler);
- }
+ template <typename WriteHandler, typename AsyncRandomAccessWriteDevice,
+ typename Allocator, typename CompletionCondition>
+ void operator()(BOOST_ASIO_MOVE_ARG(WriteHandler) handler,
+ AsyncRandomAccessWriteDevice* d, uint64_t offset,
+ basic_streambuf<Allocator>* b,
+ BOOST_ASIO_MOVE_ARG(CompletionCondition) completion_condition) const
+ {
+ // If you get an error on the following line it means that your handler
+ // does not meet the documented type requirements for a WriteHandler.
+ BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
+
+ non_const_lvalue<WriteHandler> handler2(handler);
+ async_write_at(*d, offset, b->data(),
+ BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition),
+ write_at_streambuf_op<Allocator, typename decay<WriteHandler>::type>(
+ *b, handler2.value));
+ }
+ };
} // namespace detail
#if !defined(GENERATING_DOCUMENTATION)
@@ -525,19 +549,10 @@ async_write_at(AsyncRandomAccessWriteDevice& d,
CompletionCondition completion_condition,
BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
{
- // If you get an error on the following line it means that your handler does
- // not meet the documented type requirements for a WriteHandler.
- BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
-
- async_completion<WriteHandler,
- void (boost::system::error_code, std::size_t)> init(handler);
-
- async_write_at(d, offset, b.data(), completion_condition,
- detail::write_at_streambuf_op<Allocator, BOOST_ASIO_HANDLER_TYPE(
- WriteHandler, void (boost::system::error_code, std::size_t))>(
- b, init.completion_handler));
-
- return init.result.get();
+ return async_initiate<WriteHandler,
+ void (boost::system::error_code, std::size_t)>(
+ detail::initiate_async_write_at_streambuf(), handler, &d, offset,
+ &b, BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition));
}
template <typename AsyncRandomAccessWriteDevice, typename Allocator,
@@ -548,19 +563,10 @@ async_write_at(AsyncRandomAccessWriteDevice& d,
uint64_t offset, boost::asio::basic_streambuf<Allocator>& b,
BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
{
- // If you get an error on the following line it means that your handler does
- // not meet the documented type requirements for a WriteHandler.
- BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
-
- async_completion<WriteHandler,
- void (boost::system::error_code, std::size_t)> init(handler);
-
- async_write_at(d, offset, b.data(), transfer_all(),
- detail::write_at_streambuf_op<Allocator, BOOST_ASIO_HANDLER_TYPE(
- WriteHandler, void (boost::system::error_code, std::size_t))>(
- b, init.completion_handler));
-
- return init.result.get();
+ return async_initiate<WriteHandler,
+ void (boost::system::error_code, std::size_t)>(
+ detail::initiate_async_write_at_streambuf(),
+ handler, &d, offset, &b, transfer_all());
}
#endif // !defined(BOOST_ASIO_NO_IOSTREAM)