summaryrefslogtreecommitdiff
path: root/boost/beast/experimental/core/impl/timeout_socket.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/beast/experimental/core/impl/timeout_socket.hpp')
-rw-r--r--boost/beast/experimental/core/impl/timeout_socket.hpp207
1 files changed, 207 insertions, 0 deletions
diff --git a/boost/beast/experimental/core/impl/timeout_socket.hpp b/boost/beast/experimental/core/impl/timeout_socket.hpp
new file mode 100644
index 0000000000..8c5a7d7427
--- /dev/null
+++ b/boost/beast/experimental/core/impl/timeout_socket.hpp
@@ -0,0 +1,207 @@
+//
+// Copyright (c) 2018 Vinnie Falco (vinnie dot falco at gmail 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)
+//
+// Official repository: https://github.com/boostorg/beast
+//
+
+#ifndef BOOST_BEAST_CORE_IMPL_TIMOUT_SOCKET_HPP
+#define BOOST_BEAST_CORE_IMPL_TIMOUT_SOCKET_HPP
+
+#include <boost/beast/core/bind_handler.hpp>
+#include <boost/beast/core/type_traits.hpp>
+#include <boost/beast/experimental/core/detail/timeout_work_guard.hpp>
+#include <boost/asio/executor_work_guard.hpp>
+#include <memory>
+#include <utility>
+
+namespace boost {
+namespace beast {
+
+template<class Protocol, class Executor>
+template<class Handler>
+class basic_timeout_socket<Protocol, Executor>::async_op
+{
+ Handler h_;
+ basic_timeout_socket& s_;
+ detail::timeout_work_guard work_;
+
+public:
+ async_op(async_op&&) = default;
+ async_op(async_op const&) = delete;
+
+ template<class Buffers, class DeducedHandler>
+ async_op(
+ Buffers const& b,
+ DeducedHandler&& h,
+ basic_timeout_socket& s,
+ std::true_type)
+ : h_(std::forward<DeducedHandler>(h))
+ , s_(s)
+ , work_(s.rd_timer_)
+ {
+ s_.sock_.async_read_some(b, std::move(*this));
+ }
+
+ template<class Buffers, class DeducedHandler>
+ async_op(
+ Buffers const& b,
+ DeducedHandler&& h,
+ basic_timeout_socket& s,
+ std::false_type)
+ : h_(std::forward<DeducedHandler>(h))
+ , s_(s)
+ , work_(s.wr_timer_)
+ {
+ s_.sock_.async_write_some(b, std::move(*this));
+ }
+
+ using allocator_type =
+ boost::asio::associated_allocator_t<Handler>;
+
+ allocator_type
+ get_allocator() const noexcept
+ {
+ return (boost::asio::get_associated_allocator)(h_);
+ }
+
+ using executor_type =
+ boost::asio::associated_executor_t<Handler, decltype(
+ std::declval<basic_timeout_socket<Protocol>&>().get_executor())>;
+
+ executor_type
+ get_executor() const noexcept
+ {
+ return (boost::asio::get_associated_executor)(
+ h_, s_.get_executor());
+ }
+
+ friend
+ bool asio_handler_is_continuation(async_op* op)
+ {
+ using boost::asio::asio_handler_is_continuation;
+ return asio_handler_is_continuation(
+ std::addressof(op->h_));
+ }
+
+ template<class Function>
+ friend
+ void asio_handler_invoke(Function&& f, async_op* op)
+ {
+ using boost::asio::asio_handler_invoke;
+ asio_handler_invoke(f, std::addressof(op->h_));
+ }
+
+ void
+ operator()(error_code ec, std::size_t bytes_transferred)
+ {
+ if(s_.expired_)
+ {
+ BOOST_ASSERT(ec == boost::asio::error::operation_aborted);
+ ec = boost::asio::error::timed_out;
+ }
+ else
+ {
+ work_.complete();
+ }
+ h_(ec, bytes_transferred);
+ }
+};
+
+//------------------------------------------------------------------------------
+
+template<class Protocol, class Executor>
+basic_timeout_socket<Protocol, Executor>::
+timer::
+timer(basic_timeout_socket& s)
+ : detail::timeout_object(s.ex_.context())
+ , s_(s)
+{
+}
+
+template<class Protocol, class Executor>
+auto
+basic_timeout_socket<Protocol, Executor>::
+timer::
+operator=(timer&&)
+ -> timer&
+{
+ return *this;
+}
+
+template<class Protocol, class Executor>
+void
+basic_timeout_socket<Protocol, Executor>::
+timer::
+on_timeout()
+{
+ boost::asio::post(
+ s_.ex_,
+ [this]()
+ {
+ s_.expired_ = true;
+ s_.sock_.cancel();
+ });
+}
+
+//------------------------------------------------------------------------------
+
+template<class Protocol, class Executor>
+template<class ExecutionContext, class>
+basic_timeout_socket<Protocol, Executor>::
+basic_timeout_socket(ExecutionContext& ctx)
+ : ex_(ctx.get_executor())
+ , rd_timer_(*this)
+ , wr_timer_(*this)
+ , sock_(ctx)
+{
+}
+
+template<class Protocol, class Executor>
+template<class MutableBufferSequence, class ReadHandler>
+BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
+ void(boost::system::error_code, std::size_t))
+basic_timeout_socket<Protocol, Executor>::
+async_read_some(
+ MutableBufferSequence const& buffers,
+ ReadHandler&& handler)
+{
+ static_assert(boost::asio::is_mutable_buffer_sequence<
+ MutableBufferSequence>::value,
+ "MutableBufferSequence requirements not met");
+ BOOST_BEAST_HANDLER_INIT(
+ ReadHandler, void(error_code, std::size_t));
+ async_op<BOOST_ASIO_HANDLER_TYPE(ReadHandler,
+ void(error_code, std::size_t))>(buffers,
+ std::forward<ReadHandler>(handler), *this,
+ std::true_type{});
+ return init.result.get();
+}
+
+template<class Protocol, class Executor>
+template<class ConstBufferSequence, class WriteHandler>
+BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
+ void(boost::system::error_code, std::size_t))
+basic_timeout_socket<Protocol, Executor>::
+async_write_some(
+ ConstBufferSequence const& buffers,
+ WriteHandler&& handler)
+{
+ static_assert(boost::asio::is_const_buffer_sequence<
+ ConstBufferSequence>::value,
+ "ConstBufferSequence requirements not met");
+ BOOST_BEAST_HANDLER_INIT(
+ WriteHandler, void(error_code, std::size_t));
+ async_op<BOOST_ASIO_HANDLER_TYPE(WriteHandler,
+ void(error_code, std::size_t))>(buffers,
+ std::forward<WriteHandler>(handler), *this,
+ std::false_type{});
+ return init.result.get();
+}
+
+} // beast
+} // boost
+
+#endif