summaryrefslogtreecommitdiffstatshomepage
path: root/3rdparty/asio/include/asio/system_executor.hpp
diff options
context:
space:
mode:
Diffstat (limited to '3rdparty/asio/include/asio/system_executor.hpp')
-rw-r--r--3rdparty/asio/include/asio/system_executor.hpp625
1 files changed, 578 insertions, 47 deletions
diff --git a/3rdparty/asio/include/asio/system_executor.hpp b/3rdparty/asio/include/asio/system_executor.hpp
index f23e35f04b6..84025f0d519 100644
--- a/3rdparty/asio/include/asio/system_executor.hpp
+++ b/3rdparty/asio/include/asio/system_executor.hpp
@@ -2,7 +2,7 @@
// system_executor.hpp
// ~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2021 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)
@@ -16,26 +16,328 @@
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/config.hpp"
-#include "asio/detail/scheduler.hpp"
-#include "asio/detail/thread_group.hpp"
-#include "asio/execution_context.hpp"
+#include "asio/detail/memory.hpp"
+#include "asio/execution.hpp"
#include "asio/detail/push_options.hpp"
namespace asio {
+class system_context;
+
/// An executor that uses arbitrary threads.
/**
* The system executor represents an execution context where functions are
- * permitted to run on arbitrary threads. The post() and defer() functions
- * schedule the function to run on an unspecified system thread pool, and
- * dispatch() invokes the function immediately.
+ * permitted to run on arbitrary threads. When the blocking.never property is
+ * established, the system executor will schedule the function to run on an
+ * unspecified system thread pool. When either blocking.possibly or
+ * blocking.always is established, the executor invokes the function
+ * immediately.
*/
-class system_executor
+template <typename Blocking, typename Relationship, typename Allocator>
+class basic_system_executor
{
public:
+ /// Default constructor.
+ basic_system_executor() ASIO_NOEXCEPT
+ : allocator_(Allocator())
+ {
+ }
+
+#if !defined(GENERATING_DOCUMENTATION)
+private:
+ friend struct asio_require_fn::impl;
+ friend struct asio_prefer_fn::impl;
+#endif // !defined(GENERATING_DOCUMENTATION)
+
+ /// Obtain an executor with the @c blocking.possibly property.
+ /**
+ * Do not call this function directly. It is intended for use with the
+ * asio::require customisation point.
+ *
+ * For example:
+ * @code asio::system_executor ex1;
+ * auto ex2 = asio::require(ex1,
+ * asio::execution::blocking.possibly); @endcode
+ */
+ basic_system_executor<execution::blocking_t::possibly_t,
+ Relationship, Allocator>
+ require(execution::blocking_t::possibly_t) const
+ {
+ return basic_system_executor<execution::blocking_t::possibly_t,
+ Relationship, Allocator>(allocator_);
+ }
+
+ /// Obtain an executor with the @c blocking.always property.
+ /**
+ * Do not call this function directly. It is intended for use with the
+ * asio::require customisation point.
+ *
+ * For example:
+ * @code asio::system_executor ex1;
+ * auto ex2 = asio::require(ex1,
+ * asio::execution::blocking.always); @endcode
+ */
+ basic_system_executor<execution::blocking_t::always_t,
+ Relationship, Allocator>
+ require(execution::blocking_t::always_t) const
+ {
+ return basic_system_executor<execution::blocking_t::always_t,
+ Relationship, Allocator>(allocator_);
+ }
+
+ /// Obtain an executor with the @c blocking.never property.
+ /**
+ * Do not call this function directly. It is intended for use with the
+ * asio::require customisation point.
+ *
+ * For example:
+ * @code asio::system_executor ex1;
+ * auto ex2 = asio::require(ex1,
+ * asio::execution::blocking.never); @endcode
+ */
+ basic_system_executor<execution::blocking_t::never_t,
+ Relationship, Allocator>
+ require(execution::blocking_t::never_t) const
+ {
+ return basic_system_executor<execution::blocking_t::never_t,
+ Relationship, Allocator>(allocator_);
+ }
+
+ /// Obtain an executor with the @c relationship.continuation property.
+ /**
+ * Do not call this function directly. It is intended for use with the
+ * asio::require customisation point.
+ *
+ * For example:
+ * @code asio::system_executor ex1;
+ * auto ex2 = asio::require(ex1,
+ * asio::execution::relationship.continuation); @endcode
+ */
+ basic_system_executor<Blocking,
+ execution::relationship_t::continuation_t, Allocator>
+ require(execution::relationship_t::continuation_t) const
+ {
+ return basic_system_executor<Blocking,
+ execution::relationship_t::continuation_t, Allocator>(allocator_);
+ }
+
+ /// Obtain an executor with the @c relationship.fork property.
+ /**
+ * Do not call this function directly. It is intended for use with the
+ * asio::require customisation point.
+ *
+ * For example:
+ * @code asio::system_executor ex1;
+ * auto ex2 = asio::require(ex1,
+ * asio::execution::relationship.fork); @endcode
+ */
+ basic_system_executor<Blocking,
+ execution::relationship_t::fork_t, Allocator>
+ require(execution::relationship_t::fork_t) const
+ {
+ return basic_system_executor<Blocking,
+ execution::relationship_t::fork_t, Allocator>(allocator_);
+ }
+
+ /// Obtain an executor with the specified @c allocator property.
+ /**
+ * Do not call this function directly. It is intended for use with the
+ * asio::require customisation point.
+ *
+ * For example:
+ * @code asio::system_executor ex1;
+ * auto ex2 = asio::require(ex1,
+ * asio::execution::allocator(my_allocator)); @endcode
+ */
+ template <typename OtherAllocator>
+ basic_system_executor<Blocking, Relationship, OtherAllocator>
+ require(execution::allocator_t<OtherAllocator> a) const
+ {
+ return basic_system_executor<Blocking,
+ Relationship, OtherAllocator>(a.value());
+ }
+
+ /// Obtain an executor with the default @c allocator property.
+ /**
+ * Do not call this function directly. It is intended for use with the
+ * asio::require customisation point.
+ *
+ * For example:
+ * @code asio::system_executor ex1;
+ * auto ex2 = asio::require(ex1,
+ * asio::execution::allocator); @endcode
+ */
+ basic_system_executor<Blocking, Relationship, std::allocator<void> >
+ require(execution::allocator_t<void>) const
+ {
+ return basic_system_executor<Blocking,
+ Relationship, std::allocator<void> >();
+ }
+
+#if !defined(GENERATING_DOCUMENTATION)
+private:
+ friend struct asio_query_fn::impl;
+ friend struct asio::execution::detail::blocking_t<0>;
+ friend struct asio::execution::detail::mapping_t<0>;
+ friend struct asio::execution::detail::outstanding_work_t<0>;
+ friend struct asio::execution::detail::relationship_t<0>;
+#endif // !defined(GENERATING_DOCUMENTATION)
+
+ /// Query the current value of the @c mapping property.
+ /**
+ * Do not call this function directly. It is intended for use with the
+ * asio::query customisation point.
+ *
+ * For example:
+ * @code asio::system_executor ex;
+ * if (asio::query(ex, asio::execution::mapping)
+ * == asio::execution::mapping.thread)
+ * ... @endcode
+ */
+ static ASIO_CONSTEXPR execution::mapping_t query(
+ execution::mapping_t) ASIO_NOEXCEPT
+ {
+ return execution::mapping.thread;
+ }
+
+ /// Query the current value of the @c context property.
+ /**
+ * Do not call this function directly. It is intended for use with the
+ * asio::query customisation point.
+ *
+ * For example:
+ * @code asio::system_executor ex;
+ * asio::system_context& pool = asio::query(
+ * ex, asio::execution::context); @endcode
+ */
+ static system_context& query(execution::context_t) ASIO_NOEXCEPT;
+
+ /// Query the current value of the @c blocking property.
+ /**
+ * Do not call this function directly. It is intended for use with the
+ * asio::query customisation point.
+ *
+ * For example:
+ * @code asio::system_executor ex;
+ * if (asio::query(ex, asio::execution::blocking)
+ * == asio::execution::blocking.always)
+ * ... @endcode
+ */
+ static ASIO_CONSTEXPR execution::blocking_t query(
+ execution::blocking_t) ASIO_NOEXCEPT
+ {
+ return Blocking();
+ }
+
+ /// Query the current value of the @c relationship property.
+ /**
+ * Do not call this function directly. It is intended for use with the
+ * asio::query customisation point.
+ *
+ * For example:
+ * @code asio::system_executor ex;
+ * if (asio::query(ex, asio::execution::relationship)
+ * == asio::execution::relationship.continuation)
+ * ... @endcode
+ */
+ static ASIO_CONSTEXPR execution::relationship_t query(
+ execution::relationship_t) ASIO_NOEXCEPT
+ {
+ return Relationship();
+ }
+
+ /// Query the current value of the @c allocator property.
+ /**
+ * Do not call this function directly. It is intended for use with the
+ * asio::query customisation point.
+ *
+ * For example:
+ * @code asio::system_executor ex;
+ * auto alloc = asio::query(ex,
+ * asio::execution::allocator); @endcode
+ */
+ template <typename OtherAllocator>
+ ASIO_CONSTEXPR Allocator query(
+ execution::allocator_t<OtherAllocator>) const ASIO_NOEXCEPT
+ {
+ return allocator_;
+ }
+
+ /// Query the current value of the @c allocator property.
+ /**
+ * Do not call this function directly. It is intended for use with the
+ * asio::query customisation point.
+ *
+ * For example:
+ * @code asio::system_executor ex;
+ * auto alloc = asio::query(ex,
+ * asio::execution::allocator); @endcode
+ */
+ ASIO_CONSTEXPR Allocator query(
+ execution::allocator_t<void>) const ASIO_NOEXCEPT
+ {
+ return allocator_;
+ }
+
+ /// Query the occupancy (recommended number of work items) for the system
+ /// context.
+ /**
+ * Do not call this function directly. It is intended for use with the
+ * asio::query customisation point.
+ *
+ * For example:
+ * @code asio::system_executor ex;
+ * std::size_t occupancy = asio::query(
+ * ex, asio::execution::occupancy); @endcode
+ */
+ std::size_t query(execution::occupancy_t) const ASIO_NOEXCEPT;
+
+public:
+ /// Compare two executors for equality.
+ /**
+ * Two executors are equal if they refer to the same underlying io_context.
+ */
+ friend bool operator==(const basic_system_executor&,
+ const basic_system_executor&) ASIO_NOEXCEPT
+ {
+ return true;
+ }
+
+ /// Compare two executors for inequality.
+ /**
+ * Two executors are equal if they refer to the same underlying io_context.
+ */
+ friend bool operator!=(const basic_system_executor&,
+ const basic_system_executor&) ASIO_NOEXCEPT
+ {
+ return false;
+ }
+
+#if !defined(GENERATING_DOCUMENTATION)
+private:
+ friend struct asio_execution_execute_fn::impl;
+#endif // !defined(GENERATING_DOCUMENTATION)
+
+ /// Execution function.
+ /**
+ * Do not call this function directly. It is intended for use with the
+ * execution::execute customisation point.
+ *
+ * For example:
+ * @code asio::system_executor ex;
+ * execution::execute(ex, my_function_object); @endcode
+ */
+ template <typename Function>
+ void execute(ASIO_MOVE_ARG(Function) f) const
+ {
+ this->do_execute(ASIO_MOVE_CAST(Function)(f), Blocking());
+ }
+
+#if !defined(ASIO_NO_TS_EXECUTORS)
+public:
/// Obtain the underlying execution context.
- execution_context& context() const ASIO_NOEXCEPT;
+ system_context& context() const ASIO_NOEXCEPT;
/// Inform the executor that it has some outstanding work to do.
/**
@@ -65,8 +367,8 @@ public:
* @param a An allocator that may be used by the executor to allocate the
* internal storage needed for function invocation.
*/
- template <typename Function, typename Allocator>
- void dispatch(ASIO_MOVE_ARG(Function) f, const Allocator& a) const;
+ template <typename Function, typename OtherAllocator>
+ void dispatch(ASIO_MOVE_ARG(Function) f, const OtherAllocator& a) const;
/// Request the system executor to invoke the given function object.
/**
@@ -81,8 +383,8 @@ public:
* @param a An allocator that may be used by the executor to allocate the
* internal storage needed for function invocation.
*/
- template <typename Function, typename Allocator>
- void post(ASIO_MOVE_ARG(Function) f, const Allocator& a) const;
+ template <typename Function, typename OtherAllocator>
+ void post(ASIO_MOVE_ARG(Function) f, const OtherAllocator& a) const;
/// Request the system executor to invoke the given function object.
/**
@@ -97,57 +399,286 @@ public:
* @param a An allocator that may be used by the executor to allocate the
* internal storage needed for function invocation.
*/
- template <typename Function, typename Allocator>
- void defer(ASIO_MOVE_ARG(Function) f, const Allocator& a) const;
+ template <typename Function, typename OtherAllocator>
+ void defer(ASIO_MOVE_ARG(Function) f, const OtherAllocator& a) const;
+#endif // !defined(ASIO_NO_TS_EXECUTORS)
- /// Compare two executors for equality.
- /**
- * System executors always compare equal.
- */
- friend bool operator==(const system_executor&,
- const system_executor&) ASIO_NOEXCEPT
+private:
+ template <typename, typename, typename> friend class basic_system_executor;
+
+ // Constructor used by require().
+ basic_system_executor(const Allocator& a)
+ : allocator_(a)
{
- return true;
}
- /// Compare two executors for inequality.
- /**
- * System executors always compare equal.
- */
- friend bool operator!=(const system_executor&,
- const system_executor&) ASIO_NOEXCEPT
+ /// Execution helper implementation for the possibly blocking property.
+ template <typename Function>
+ void do_execute(ASIO_MOVE_ARG(Function) f,
+ execution::blocking_t::possibly_t) const;
+
+ /// Execution helper implementation for the always blocking property.
+ template <typename Function>
+ void do_execute(ASIO_MOVE_ARG(Function) f,
+ execution::blocking_t::always_t) const;
+
+ /// Execution helper implementation for the never blocking property.
+ template <typename Function>
+ void do_execute(ASIO_MOVE_ARG(Function) f,
+ execution::blocking_t::never_t) const;
+
+ // The allocator used for execution functions.
+ Allocator allocator_;
+};
+
+/// An executor that uses arbitrary threads.
+/**
+ * The system executor represents an execution context where functions are
+ * permitted to run on arbitrary threads. When the blocking.never property is
+ * established, the system executor will schedule the function to run on an
+ * unspecified system thread pool. When either blocking.possibly or
+ * blocking.always is established, the executor invokes the function
+ * immediately.
+ */
+typedef basic_system_executor<execution::blocking_t::possibly_t,
+ execution::relationship_t::fork_t, std::allocator<void> >
+ system_executor;
+
+#if !defined(GENERATING_DOCUMENTATION)
+
+namespace traits {
+
+#if !defined(ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)
+
+template <typename Blocking, typename Relationship, typename Allocator>
+struct equality_comparable<
+ asio::basic_system_executor<Blocking, Relationship, Allocator>
+ >
+{
+ ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
+ ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
+};
+
+#endif // !defined(ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)
+
+#if !defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)
+
+template <typename Blocking, typename Relationship,
+ typename Allocator, typename Function>
+struct execute_member<
+ asio::basic_system_executor<Blocking, Relationship, Allocator>,
+ Function
+ >
+{
+ ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
+ ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);
+ typedef void result_type;
+};
+
+#endif // !defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)
+
+#if !defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)
+
+template <typename Blocking, typename Relationship, typename Allocator>
+struct require_member<
+ asio::basic_system_executor<Blocking, Relationship, Allocator>,
+ asio::execution::blocking_t::possibly_t
+ >
+{
+ ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
+ ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);
+ typedef asio::basic_system_executor<
+ asio::execution::blocking_t::possibly_t,
+ Relationship, Allocator> result_type;
+};
+
+template <typename Blocking, typename Relationship, typename Allocator>
+struct require_member<
+ asio::basic_system_executor<Blocking, Relationship, Allocator>,
+ asio::execution::blocking_t::always_t
+ >
+{
+ ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
+ ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);
+ typedef asio::basic_system_executor<
+ asio::execution::blocking_t::always_t,
+ Relationship, Allocator> result_type;
+};
+
+template <typename Blocking, typename Relationship, typename Allocator>
+struct require_member<
+ asio::basic_system_executor<Blocking, Relationship, Allocator>,
+ asio::execution::blocking_t::never_t
+ >
+{
+ ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
+ ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);
+ typedef asio::basic_system_executor<
+ asio::execution::blocking_t::never_t,
+ Relationship, Allocator> result_type;
+};
+
+template <typename Blocking, typename Relationship, typename Allocator>
+struct require_member<
+ asio::basic_system_executor<Blocking, Relationship, Allocator>,
+ asio::execution::relationship_t::fork_t
+ >
+{
+ ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
+ ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);
+ typedef asio::basic_system_executor<Blocking,
+ asio::execution::relationship_t::fork_t,
+ Allocator> result_type;
+};
+
+template <typename Blocking, typename Relationship, typename Allocator>
+struct require_member<
+ asio::basic_system_executor<Blocking, Relationship, Allocator>,
+ asio::execution::relationship_t::continuation_t
+ >
+{
+ ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
+ ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);
+ typedef asio::basic_system_executor<Blocking,
+ asio::execution::relationship_t::continuation_t,
+ Allocator> result_type;
+};
+
+template <typename Blocking, typename Relationship, typename Allocator>
+struct require_member<
+ asio::basic_system_executor<Blocking, Relationship, Allocator>,
+ asio::execution::allocator_t<void>
+ >
+{
+ ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
+ ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);
+ typedef asio::basic_system_executor<Blocking,
+ Relationship, std::allocator<void> > result_type;
+};
+
+template <typename Blocking, typename Relationship,
+ typename Allocator, typename OtherAllocator>
+struct require_member<
+ asio::basic_system_executor<Blocking, Relationship, Allocator>,
+ asio::execution::allocator_t<OtherAllocator>
+ >
+{
+ ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
+ ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);
+ typedef asio::basic_system_executor<Blocking,
+ Relationship, OtherAllocator> result_type;
+};
+
+#endif // !defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)
+
+#if !defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)
+
+template <typename Blocking, typename Relationship,
+ typename Allocator, typename Property>
+struct query_static_constexpr_member<
+ asio::basic_system_executor<Blocking, Relationship, Allocator>,
+ Property,
+ typename asio::enable_if<
+ asio::is_convertible<
+ Property,
+ asio::execution::mapping_t
+ >::value
+ >::type
+ >
+{
+ ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
+ ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
+ typedef asio::execution::mapping_t::thread_t result_type;
+
+ static ASIO_CONSTEXPR result_type value() ASIO_NOEXCEPT
{
- return false;
+ return result_type();
}
+};
-private:
- struct thread_function;
+#endif // !defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)
- // Hidden implementation of the system execution context.
- struct context_impl
- : public execution_context
- {
- // Constructor creates all threads in the system thread pool.
- ASIO_DECL context_impl();
+#if !defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)
- // Destructor shuts down all threads in the system thread pool.
- ASIO_DECL ~context_impl();
+template <typename Blocking, typename Relationship,
+ typename Allocator, typename Property>
+struct query_member<
+ asio::basic_system_executor<Blocking, Relationship, Allocator>,
+ Property,
+ typename asio::enable_if<
+ asio::is_convertible<
+ Property,
+ asio::execution::blocking_t
+ >::value
+ >::type
+ >
+{
+ ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
+ ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
+ typedef asio::execution::blocking_t result_type;
+};
- // The underlying scheduler.
- detail::scheduler& scheduler_;
+template <typename Blocking, typename Relationship,
+ typename Allocator, typename Property>
+struct query_member<
+ asio::basic_system_executor<Blocking, Relationship, Allocator>,
+ Property,
+ typename asio::enable_if<
+ asio::is_convertible<
+ Property,
+ asio::execution::relationship_t
+ >::value
+ >::type
+ >
+{
+ ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
+ ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
+ typedef asio::execution::relationship_t result_type;
+};
+
+template <typename Blocking, typename Relationship, typename Allocator>
+struct query_member<
+ asio::basic_system_executor<Blocking, Relationship, Allocator>,
+ asio::execution::context_t
+ >
+{
+ ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
+ ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
+ typedef asio::system_context& result_type;
+};
- // The threads in the system thread pool.
- detail::thread_group threads_;
- };
+template <typename Blocking, typename Relationship, typename Allocator>
+struct query_member<
+ asio::basic_system_executor<Blocking, Relationship, Allocator>,
+ asio::execution::allocator_t<void>
+ >
+{
+ ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
+ ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
+ typedef Allocator result_type;
};
+template <typename Blocking, typename Relationship, typename Allocator>
+struct query_member<
+ asio::basic_system_executor<Blocking, Relationship, Allocator>,
+ asio::execution::allocator_t<Allocator>
+ >
+{
+ ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
+ ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
+ typedef Allocator result_type;
+};
+
+#endif // !defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)
+
+} // namespace traits
+
+#endif // !defined(GENERATING_DOCUMENTATION)
+
} // namespace asio
#include "asio/detail/pop_options.hpp"
#include "asio/impl/system_executor.hpp"
-#if defined(ASIO_HEADER_ONLY)
-# include "asio/impl/system_executor.ipp"
-#endif // defined(ASIO_HEADER_ONLY)
#endif // ASIO_SYSTEM_EXECUTOR_HPP