diff options
Diffstat (limited to '3rdparty/asio/include/asio/system_executor.hpp')
-rw-r--r-- | 3rdparty/asio/include/asio/system_executor.hpp | 625 |
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 |