Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:29:09

0001 //
0002 // defer.hpp
0003 // ~~~~~~~~~
0004 //
0005 // Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
0006 //
0007 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0008 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0009 //
0010 
0011 #ifndef BOOST_ASIO_DEFER_HPP
0012 #define BOOST_ASIO_DEFER_HPP
0013 
0014 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
0015 # pragma once
0016 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
0017 
0018 #include <boost/asio/detail/config.hpp>
0019 #include <boost/asio/async_result.hpp>
0020 #include <boost/asio/detail/initiate_defer.hpp>
0021 #include <boost/asio/detail/type_traits.hpp>
0022 #include <boost/asio/execution_context.hpp>
0023 #include <boost/asio/execution/blocking.hpp>
0024 #include <boost/asio/execution/executor.hpp>
0025 #include <boost/asio/is_executor.hpp>
0026 #include <boost/asio/require.hpp>
0027 
0028 #include <boost/asio/detail/push_options.hpp>
0029 
0030 namespace boost {
0031 namespace asio {
0032 
0033 /// Submits a completion token or function object for execution.
0034 /**
0035  * This function submits an object for execution using the object's associated
0036  * executor. The function object is queued for execution, and is never called
0037  * from the current thread prior to returning from <tt>defer()</tt>.
0038  *
0039  * The use of @c defer(), rather than @ref post(), indicates the caller's
0040  * preference that the executor defer the queueing of the function object. This
0041  * may allow the executor to optimise queueing for cases when the function
0042  * object represents a continuation of the current call context.
0043  *
0044  * @param token The @ref completion_token that will be used to produce a
0045  * completion handler. The function signature of the completion handler must be:
0046  * @code void handler(); @endcode
0047  *
0048  * @returns This function returns <tt>async_initiate<NullaryToken,
0049  * void()>(Init{}, token)</tt>, where @c Init is a function object type defined
0050  * as:
0051  *
0052  * @code class Init
0053  * {
0054  * public:
0055  *   template <typename CompletionHandler>
0056  *     void operator()(CompletionHandler&& completion_handler) const;
0057  * }; @endcode
0058  *
0059  * The function call operator of @c Init:
0060  *
0061  * @li Obtains the handler's associated executor object @c ex of type @c Ex by
0062  * performing @code auto ex = get_associated_executor(handler); @endcode
0063  *
0064  * @li Obtains the handler's associated allocator object @c alloc by performing
0065  * @code auto alloc = get_associated_allocator(handler); @endcode
0066  *
0067  * @li If <tt>execution::is_executor<Ex>::value</tt> is true, performs
0068  * @code prefer(
0069  *     require(ex, execution::blocking.never),
0070  *     execution::relationship.continuation,
0071  *     execution::allocator(alloc)
0072  *   ).execute(std::forward<CompletionHandler>(completion_handler)); @endcode
0073  *
0074  * @li If <tt>execution::is_executor<Ex>::value</tt> is false, performs
0075  * @code ex.defer(
0076  *     std::forward<CompletionHandler>(completion_handler),
0077  *     alloc); @endcode
0078  *
0079  * @par Completion Signature
0080  * @code void() @endcode
0081  */
0082 template <BOOST_ASIO_COMPLETION_TOKEN_FOR(void()) NullaryToken>
0083 auto defer(NullaryToken&& token)
0084   -> decltype(
0085     async_initiate<NullaryToken, void()>(
0086       declval<detail::initiate_defer>(), token))
0087 {
0088   return async_initiate<NullaryToken, void()>(
0089       detail::initiate_defer(), token);
0090 }
0091 
0092 /// Submits a completion token or function object for execution.
0093 /**
0094  * This function submits an object for execution using the specified executor.
0095  * The function object is queued for execution, and is never called from the
0096  * current thread prior to returning from <tt>defer()</tt>.
0097  *
0098  * The use of @c defer(), rather than @ref post(), indicates the caller's
0099  * preference that the executor defer the queueing of the function object. This
0100  * may allow the executor to optimise queueing for cases when the function
0101  * object represents a continuation of the current call context.
0102  *
0103  * @param ex The target executor.
0104  *
0105  * @param token The @ref completion_token that will be used to produce a
0106  * completion handler. The function signature of the completion handler must be:
0107  * @code void handler(); @endcode
0108  *
0109  * @returns This function returns <tt>async_initiate<NullaryToken,
0110  * void()>(Init{ex}, token)</tt>, where @c Init is a function object type
0111  * defined as:
0112  *
0113  * @code class Init
0114  * {
0115  * public:
0116  *   using executor_type = Executor;
0117  *   explicit Init(const Executor& ex) : ex_(ex) {}
0118  *   executor_type get_executor() const noexcept { return ex_; }
0119  *   template <typename CompletionHandler>
0120  *     void operator()(CompletionHandler&& completion_handler) const;
0121  * private:
0122  *   Executor ex_; // exposition only
0123  * }; @endcode
0124  *
0125  * The function call operator of @c Init:
0126  *
0127  * @li Obtains the handler's associated executor object @c ex1 of type @c Ex1 by
0128  * performing @code auto ex1 = get_associated_executor(handler, ex); @endcode
0129  *
0130  * @li Obtains the handler's associated allocator object @c alloc by performing
0131  * @code auto alloc = get_associated_allocator(handler); @endcode
0132  *
0133  * @li If <tt>execution::is_executor<Ex1>::value</tt> is true, constructs a
0134  * function object @c f with a member @c executor_ that is initialised with
0135  * <tt>prefer(ex1, execution::outstanding_work.tracked)</tt>, a member @c
0136  * handler_ that is a decay-copy of @c completion_handler, and a function call
0137  * operator that performs:
0138  * @code auto a = get_associated_allocator(handler_);
0139  * prefer(executor_, execution::allocator(a)).execute(std::move(handler_));
0140  * @endcode
0141  *
0142  * @li If <tt>execution::is_executor<Ex1>::value</tt> is false, constructs a
0143  * function object @c f with a member @c work_ that is initialised with
0144  * <tt>make_work_guard(ex1)</tt>, a member @c handler_ that is a decay-copy of
0145  * @c completion_handler, and a function call operator that performs:
0146  * @code auto a = get_associated_allocator(handler_);
0147  * work_.get_executor().dispatch(std::move(handler_), a);
0148  * work_.reset(); @endcode
0149  *
0150  * @li If <tt>execution::is_executor<Ex>::value</tt> is true, performs
0151  * @code prefer(
0152  *     require(ex, execution::blocking.never),
0153  *     execution::relationship.continuation,
0154  *     execution::allocator(alloc)
0155  *   ).execute(std::move(f)); @endcode
0156  *
0157  * @li If <tt>execution::is_executor<Ex>::value</tt> is false, performs
0158  * @code ex.defer(std::move(f), alloc); @endcode
0159  *
0160  * @par Completion Signature
0161  * @code void() @endcode
0162  */
0163 template <typename Executor,
0164     BOOST_ASIO_COMPLETION_TOKEN_FOR(void()) NullaryToken
0165       = default_completion_token_t<Executor>>
0166 auto defer(const Executor& ex,
0167     NullaryToken&& token
0168       = default_completion_token_t<Executor>(),
0169     constraint_t<
0170       (execution::is_executor<Executor>::value
0171           && can_require<Executor, execution::blocking_t::never_t>::value)
0172         || is_executor<Executor>::value
0173     > = 0)
0174   -> decltype(
0175     async_initiate<NullaryToken, void()>(
0176       declval<detail::initiate_defer_with_executor<Executor>>(), token))
0177 {
0178   return async_initiate<NullaryToken, void()>(
0179       detail::initiate_defer_with_executor<Executor>(ex), token);
0180 }
0181 
0182 /// Submits a completion token or function object for execution.
0183 /**
0184  * @param ctx An execution context, from which the target executor is obtained.
0185  *
0186  * @param token The @ref completion_token that will be used to produce a
0187  * completion handler. The function signature of the completion handler must be:
0188  * @code void handler(); @endcode
0189  *
0190  * @returns <tt>defer(ctx.get_executor(), forward<NullaryToken>(token))</tt>.
0191  *
0192  * @par Completion Signature
0193  * @code void() @endcode
0194  */
0195 template <typename ExecutionContext,
0196     BOOST_ASIO_COMPLETION_TOKEN_FOR(void()) NullaryToken
0197       = default_completion_token_t<typename ExecutionContext::executor_type>>
0198 auto defer(ExecutionContext& ctx,
0199     NullaryToken&& token
0200       = default_completion_token_t<typename ExecutionContext::executor_type>(),
0201     constraint_t<
0202       is_convertible<ExecutionContext&, execution_context&>::value
0203     > = 0)
0204   -> decltype(
0205     async_initiate<NullaryToken, void()>(
0206       declval<detail::initiate_defer_with_executor<
0207         typename ExecutionContext::executor_type>>(), token))
0208 {
0209   return async_initiate<NullaryToken, void()>(
0210       detail::initiate_defer_with_executor<
0211         typename ExecutionContext::executor_type>(
0212           ctx.get_executor()), token);
0213 }
0214 
0215 } // namespace asio
0216 } // namespace boost
0217 
0218 #include <boost/asio/detail/pop_options.hpp>
0219 
0220 #endif // BOOST_ASIO_DEFER_HPP