summaryrefslogtreecommitdiffstatshomepage
path: root/3rdparty/asio/include/asio/detail/handler_work.hpp
diff options
context:
space:
mode:
Diffstat (limited to '3rdparty/asio/include/asio/detail/handler_work.hpp')
-rw-r--r--3rdparty/asio/include/asio/detail/handler_work.hpp511
1 files changed, 511 insertions, 0 deletions
diff --git a/3rdparty/asio/include/asio/detail/handler_work.hpp b/3rdparty/asio/include/asio/detail/handler_work.hpp
new file mode 100644
index 00000000000..596d076327a
--- /dev/null
+++ b/3rdparty/asio/include/asio/detail/handler_work.hpp
@@ -0,0 +1,511 @@
+//
+// detail/handler_work.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2024 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 ASIO_DETAIL_HANDLER_WORK_HPP
+#define ASIO_DETAIL_HANDLER_WORK_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+#include "asio/associated_allocator.hpp"
+#include "asio/associated_executor.hpp"
+#include "asio/associated_immediate_executor.hpp"
+#include "asio/detail/initiate_dispatch.hpp"
+#include "asio/detail/type_traits.hpp"
+#include "asio/detail/work_dispatcher.hpp"
+#include "asio/execution/allocator.hpp"
+#include "asio/execution/blocking.hpp"
+#include "asio/execution/executor.hpp"
+#include "asio/execution/outstanding_work.hpp"
+#include "asio/executor_work_guard.hpp"
+#include "asio/prefer.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+
+class executor;
+class io_context;
+
+#if !defined(ASIO_USE_TS_EXECUTOR_AS_DEFAULT)
+
+class any_completion_executor;
+class any_io_executor;
+
+#endif // !defined(ASIO_USE_TS_EXECUTOR_AS_DEFAULT)
+
+namespace execution {
+
+template <typename...> class any_executor;
+
+} // namespace execution
+namespace detail {
+
+template <typename Executor, typename CandidateExecutor = void,
+ typename IoContext = io_context,
+ typename PolymorphicExecutor = executor, typename = void>
+class handler_work_base
+{
+public:
+ explicit handler_work_base(int, int, const Executor& ex) noexcept
+ : executor_(asio::prefer(ex, execution::outstanding_work.tracked))
+ {
+ }
+
+ template <typename OtherExecutor>
+ handler_work_base(bool /*base1_owns_work*/, const Executor& ex,
+ const OtherExecutor& /*candidate*/) noexcept
+ : executor_(asio::prefer(ex, execution::outstanding_work.tracked))
+ {
+ }
+
+ handler_work_base(const handler_work_base& other) noexcept
+ : executor_(other.executor_)
+ {
+ }
+
+ handler_work_base(handler_work_base&& other) noexcept
+ : executor_(static_cast<executor_type&&>(other.executor_))
+ {
+ }
+
+ bool owns_work() const noexcept
+ {
+ return true;
+ }
+
+ template <typename Function, typename Handler>
+ void dispatch(Function& function, Handler& handler)
+ {
+ asio::prefer(executor_,
+ execution::allocator((get_associated_allocator)(handler))
+ ).execute(static_cast<Function&&>(function));
+ }
+
+private:
+ typedef decay_t<
+ prefer_result_t<Executor, execution::outstanding_work_t::tracked_t>
+ > executor_type;
+
+ executor_type executor_;
+};
+
+template <typename Executor, typename CandidateExecutor,
+ typename IoContext, typename PolymorphicExecutor>
+class handler_work_base<Executor, CandidateExecutor,
+ IoContext, PolymorphicExecutor,
+ enable_if_t<
+ !execution::is_executor<Executor>::value
+ && (!is_same<Executor, PolymorphicExecutor>::value
+ || !is_same<CandidateExecutor, void>::value)
+ >
+ >
+{
+public:
+ explicit handler_work_base(int, int, const Executor& ex) noexcept
+ : executor_(ex),
+ owns_work_(true)
+ {
+ executor_.on_work_started();
+ }
+
+ handler_work_base(bool /*base1_owns_work*/, const Executor& ex,
+ const Executor& candidate) noexcept
+ : executor_(ex),
+ owns_work_(ex != candidate)
+ {
+ if (owns_work_)
+ executor_.on_work_started();
+ }
+
+ template <typename OtherExecutor>
+ handler_work_base(bool /*base1_owns_work*/, const Executor& ex,
+ const OtherExecutor& /*candidate*/) noexcept
+ : executor_(ex),
+ owns_work_(true)
+ {
+ executor_.on_work_started();
+ }
+
+ handler_work_base(const handler_work_base& other) noexcept
+ : executor_(other.executor_),
+ owns_work_(other.owns_work_)
+ {
+ if (owns_work_)
+ executor_.on_work_started();
+ }
+
+ handler_work_base(handler_work_base&& other) noexcept
+ : executor_(static_cast<Executor&&>(other.executor_)),
+ owns_work_(other.owns_work_)
+ {
+ other.owns_work_ = false;
+ }
+
+ ~handler_work_base()
+ {
+ if (owns_work_)
+ executor_.on_work_finished();
+ }
+
+ bool owns_work() const noexcept
+ {
+ return owns_work_;
+ }
+
+ template <typename Function, typename Handler>
+ void dispatch(Function& function, Handler& handler)
+ {
+ executor_.dispatch(static_cast<Function&&>(function),
+ asio::get_associated_allocator(handler));
+ }
+
+private:
+ Executor executor_;
+ bool owns_work_;
+};
+
+template <typename Executor, typename IoContext, typename PolymorphicExecutor>
+class handler_work_base<Executor, void, IoContext, PolymorphicExecutor,
+ enable_if_t<
+ is_same<
+ Executor,
+ typename IoContext::executor_type
+ >::value
+ >
+ >
+{
+public:
+ explicit handler_work_base(int, int, const Executor&)
+ {
+ }
+
+ bool owns_work() const noexcept
+ {
+ return false;
+ }
+
+ template <typename Function, typename Handler>
+ void dispatch(Function& function, Handler&)
+ {
+ // When using a native implementation, I/O completion handlers are
+ // already dispatched according to the execution context's executor's
+ // rules. We can call the function directly.
+ static_cast<Function&&>(function)();
+ }
+};
+
+template <typename Executor, typename IoContext>
+class handler_work_base<Executor, void, IoContext, Executor>
+{
+public:
+ explicit handler_work_base(int, int, const Executor& ex) noexcept
+#if !defined(ASIO_NO_TYPEID)
+ : executor_(
+ ex.target_type() == typeid(typename IoContext::executor_type)
+ ? Executor() : ex)
+#else // !defined(ASIO_NO_TYPEID)
+ : executor_(ex)
+#endif // !defined(ASIO_NO_TYPEID)
+ {
+ if (executor_)
+ executor_.on_work_started();
+ }
+
+ handler_work_base(bool /*base1_owns_work*/, const Executor& ex,
+ const Executor& candidate) noexcept
+ : executor_(ex != candidate ? ex : Executor())
+ {
+ if (executor_)
+ executor_.on_work_started();
+ }
+
+ template <typename OtherExecutor>
+ handler_work_base(const Executor& ex,
+ const OtherExecutor&) noexcept
+ : executor_(ex)
+ {
+ executor_.on_work_started();
+ }
+
+ handler_work_base(const handler_work_base& other) noexcept
+ : executor_(other.executor_)
+ {
+ if (executor_)
+ executor_.on_work_started();
+ }
+
+ handler_work_base(handler_work_base&& other) noexcept
+ : executor_(static_cast<Executor&&>(other.executor_))
+ {
+ }
+
+ ~handler_work_base()
+ {
+ if (executor_)
+ executor_.on_work_finished();
+ }
+
+ bool owns_work() const noexcept
+ {
+ return !!executor_;
+ }
+
+ template <typename Function, typename Handler>
+ void dispatch(Function& function, Handler& handler)
+ {
+ executor_.dispatch(static_cast<Function&&>(function),
+ asio::get_associated_allocator(handler));
+ }
+
+private:
+ Executor executor_;
+};
+
+template <typename... SupportableProperties, typename CandidateExecutor,
+ typename IoContext, typename PolymorphicExecutor>
+class handler_work_base<execution::any_executor<SupportableProperties...>,
+ CandidateExecutor, IoContext, PolymorphicExecutor>
+{
+public:
+ typedef execution::any_executor<SupportableProperties...> executor_type;
+
+ explicit handler_work_base(int, int, const executor_type& ex) noexcept
+#if !defined(ASIO_NO_TYPEID)
+ : executor_(
+ ex.target_type() == typeid(typename IoContext::executor_type)
+ ? executor_type()
+ : asio::prefer(ex, execution::outstanding_work.tracked))
+#else // !defined(ASIO_NO_TYPEID)
+ : executor_(asio::prefer(ex, execution::outstanding_work.tracked))
+#endif // !defined(ASIO_NO_TYPEID)
+ {
+ }
+
+ handler_work_base(bool base1_owns_work, const executor_type& ex,
+ const executor_type& candidate) noexcept
+ : executor_(
+ !base1_owns_work && ex == candidate
+ ? executor_type()
+ : asio::prefer(ex, execution::outstanding_work.tracked))
+ {
+ }
+
+ template <typename OtherExecutor>
+ handler_work_base(bool /*base1_owns_work*/, const executor_type& ex,
+ const OtherExecutor& /*candidate*/) noexcept
+ : executor_(asio::prefer(ex, execution::outstanding_work.tracked))
+ {
+ }
+
+ handler_work_base(const handler_work_base& other) noexcept
+ : executor_(other.executor_)
+ {
+ }
+
+ handler_work_base(handler_work_base&& other) noexcept
+ : executor_(static_cast<executor_type&&>(other.executor_))
+ {
+ }
+
+ bool owns_work() const noexcept
+ {
+ return !!executor_;
+ }
+
+ template <typename Function, typename Handler>
+ void dispatch(Function& function, Handler&)
+ {
+ executor_.execute(static_cast<Function&&>(function));
+ }
+
+private:
+ executor_type executor_;
+};
+
+#if !defined(ASIO_USE_TS_EXECUTOR_AS_DEFAULT)
+
+template <typename Executor, typename CandidateExecutor,
+ typename IoContext, typename PolymorphicExecutor>
+class handler_work_base<
+ Executor, CandidateExecutor,
+ IoContext, PolymorphicExecutor,
+ enable_if_t<
+ is_same<Executor, any_completion_executor>::value
+ || is_same<Executor, any_io_executor>::value
+ >
+ >
+{
+public:
+ typedef Executor executor_type;
+
+ explicit handler_work_base(int, int,
+ const executor_type& ex) noexcept
+#if !defined(ASIO_NO_TYPEID)
+ : executor_(
+ ex.target_type() == typeid(typename IoContext::executor_type)
+ ? executor_type()
+ : asio::prefer(ex, execution::outstanding_work.tracked))
+#else // !defined(ASIO_NO_TYPEID)
+ : executor_(asio::prefer(ex, execution::outstanding_work.tracked))
+#endif // !defined(ASIO_NO_TYPEID)
+ {
+ }
+
+ handler_work_base(bool base1_owns_work, const executor_type& ex,
+ const executor_type& candidate) noexcept
+ : executor_(
+ !base1_owns_work && ex == candidate
+ ? executor_type()
+ : asio::prefer(ex, execution::outstanding_work.tracked))
+ {
+ }
+
+ template <typename OtherExecutor>
+ handler_work_base(bool /*base1_owns_work*/, const executor_type& ex,
+ const OtherExecutor& /*candidate*/) noexcept
+ : executor_(asio::prefer(ex, execution::outstanding_work.tracked))
+ {
+ }
+
+ handler_work_base(const handler_work_base& other) noexcept
+ : executor_(other.executor_)
+ {
+ }
+
+ handler_work_base(handler_work_base&& other) noexcept
+ : executor_(static_cast<executor_type&&>(other.executor_))
+ {
+ }
+
+ bool owns_work() const noexcept
+ {
+ return !!executor_;
+ }
+
+ template <typename Function, typename Handler>
+ void dispatch(Function& function, Handler&)
+ {
+ executor_.execute(static_cast<Function&&>(function));
+ }
+
+private:
+ executor_type executor_;
+};
+
+#endif // !defined(ASIO_USE_TS_EXECUTOR_AS_DEFAULT)
+
+template <typename Handler, typename IoExecutor, typename = void>
+class handler_work :
+ handler_work_base<IoExecutor>,
+ handler_work_base<associated_executor_t<Handler, IoExecutor>, IoExecutor>
+{
+public:
+ typedef handler_work_base<IoExecutor> base1_type;
+ typedef handler_work_base<associated_executor_t<Handler, IoExecutor>,
+ IoExecutor> base2_type;
+
+ handler_work(Handler& handler, const IoExecutor& io_ex) noexcept
+ : base1_type(0, 0, io_ex),
+ base2_type(base1_type::owns_work(),
+ asio::get_associated_executor(handler, io_ex), io_ex)
+ {
+ }
+
+ template <typename Function>
+ void complete(Function& function, Handler& handler)
+ {
+ if (!base1_type::owns_work() && !base2_type::owns_work())
+ {
+ // When using a native implementation, I/O completion handlers are
+ // already dispatched according to the execution context's executor's
+ // rules. We can call the function directly.
+ static_cast<Function&&>(function)();
+ }
+ else
+ {
+ base2_type::dispatch(function, handler);
+ }
+ }
+};
+
+template <typename Handler, typename IoExecutor>
+class handler_work<
+ Handler, IoExecutor,
+ enable_if_t<
+ is_same<
+ typename associated_executor<Handler,
+ IoExecutor>::asio_associated_executor_is_unspecialised,
+ void
+ >::value
+ >
+ > : handler_work_base<IoExecutor>
+{
+public:
+ typedef handler_work_base<IoExecutor> base1_type;
+
+ handler_work(Handler&, const IoExecutor& io_ex) noexcept
+ : base1_type(0, 0, io_ex)
+ {
+ }
+
+ template <typename Function>
+ void complete(Function& function, Handler& handler)
+ {
+ if (!base1_type::owns_work())
+ {
+ // When using a native implementation, I/O completion handlers are
+ // already dispatched according to the execution context's executor's
+ // rules. We can call the function directly.
+ static_cast<Function&&>(function)();
+ }
+ else
+ {
+ base1_type::dispatch(function, handler);
+ }
+ }
+};
+
+template <typename Handler, typename IoExecutor>
+class immediate_handler_work
+{
+public:
+ typedef handler_work<Handler, IoExecutor> handler_work_type;
+
+ explicit immediate_handler_work(handler_work_type&& w)
+ : handler_work_(static_cast<handler_work_type&&>(w))
+ {
+ }
+
+ template <typename Function>
+ void complete(Function& function, Handler& handler, const void* io_ex)
+ {
+ typedef associated_immediate_executor_t<Handler, IoExecutor>
+ immediate_ex_type;
+
+ immediate_ex_type immediate_ex = (get_associated_immediate_executor)(
+ handler, *static_cast<const IoExecutor*>(io_ex));
+
+ (initiate_dispatch_with_executor<immediate_ex_type>(immediate_ex))(
+ static_cast<Function&&>(function));
+ }
+
+private:
+ handler_work_type handler_work_;
+};
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_HANDLER_WORK_HPP