diff --git a/doc/overview/spawn.qbk b/doc/overview/spawn.qbk index 0566e558..b1615b97 100644 --- a/doc/overview/spawn.qbk +++ b/doc/overview/spawn.qbk @@ -39,8 +39,8 @@ synchronous manner, as shown in the following example: The first argument to `spawn()` may be a [link boost_asio.reference.io_context__strand `strand`], -[link boost_asio.reference.io_context `io_context`], or -[link boost_asio.reference.CompletionHandler completion handler]. +[link boost_asio.reference.io_context `io_context`], or a +[link boost_asio.reference.Handler completion handler]. This argument determines the context in which the coroutine is permitted to execute. For example, a server's per-client object may consist of multiple coroutines; they should all run on the same `strand` so that no explicit diff --git a/doc/quickref.xml b/doc/quickref.xml index 79830895..3e70d912 100644 --- a/doc/quickref.xml +++ b/doc/quickref.xml @@ -335,10 +335,10 @@ Asynchronous operations CancellationHandler CancellationSlot - CompletionHandler ExecutionContext Executor Handler + NullaryToken Service diff --git a/doc/reference.qbk b/doc/reference.qbk index ff07d1e8..7518fd5c 100644 --- a/doc/reference.qbk +++ b/doc/reference.qbk @@ -25,7 +25,6 @@ [include requirements/CancellationHandler.qbk] [include requirements/CancellationSlot.qbk] [include requirements/CompletionCondition.qbk] -[include requirements/CompletionHandler.qbk] [include requirements/ConnectCondition.qbk] [include requirements/ConnectHandler.qbk] [include requirements/ConnectToken.qbk] @@ -51,6 +50,7 @@ [include requirements/MoveAcceptHandler.qbk] [include requirements/MoveAcceptToken.qbk] [include requirements/MutableBufferSequence.qbk] +[include requirements/NullaryToken.qbk] [include requirements/OperationState.qbk] [include requirements/ProtoAllocator.qbk] [include requirements/Protocol.qbk] @@ -78527,26 +78527,26 @@ If `T` has a nested type `default_completion_token_type`, `T::default_completion Submits a completion token or function object for execution. template< - typename CompletionToken> + typename ``[link boost_asio.reference.NullaryToken NullaryToken]``> ``[link boost_asio.reference.asynchronous_operations.automatic_deduction_of_initiating_function_return_type ['DEDUCED]]`` ``[link boost_asio.reference.defer.overload1 defer]``( - CompletionToken && token); + NullaryToken && token); `` [''''»''' [link boost_asio.reference.defer.overload1 more...]]`` template< typename ``[link boost_asio.reference.Executor1 Executor]``, - typename CompletionToken = ``[link boost_asio.reference.asynchronous_operations.default_completion_tokens ['DEFAULT]]``> + typename ``[link boost_asio.reference.NullaryToken NullaryToken]`` = ``[link boost_asio.reference.asynchronous_operations.default_completion_tokens ['DEFAULT]]``> ``[link boost_asio.reference.asynchronous_operations.automatic_deduction_of_initiating_function_return_type ['DEDUCED]]`` ``[link boost_asio.reference.defer.overload2 defer]``( const Executor & ex, - CompletionToken && token = ``[link boost_asio.reference.asynchronous_operations.default_completion_tokens ['DEFAULT]]``, + NullaryToken && token = ``[link boost_asio.reference.asynchronous_operations.default_completion_tokens ['DEFAULT]]``, typename constraint< execution::is_executor< Executor >::value||is_executor< Executor >::value >::type = 0); `` [''''»''' [link boost_asio.reference.defer.overload2 more...]]`` template< typename ExecutionContext, - typename CompletionToken = ``[link boost_asio.reference.asynchronous_operations.default_completion_tokens ['DEFAULT]]``> + typename ``[link boost_asio.reference.NullaryToken NullaryToken]`` = ``[link boost_asio.reference.asynchronous_operations.default_completion_tokens ['DEFAULT]]``> ``[link boost_asio.reference.asynchronous_operations.automatic_deduction_of_initiating_function_return_type ['DEDUCED]]`` ``[link boost_asio.reference.defer.overload3 defer]``( ExecutionContext & ctx, - CompletionToken && token = ``[link boost_asio.reference.asynchronous_operations.default_completion_tokens ['DEFAULT]]``, + NullaryToken && token = ``[link boost_asio.reference.asynchronous_operations.default_completion_tokens ['DEFAULT]]``, typename constraint< is_convertible< ExecutionContext &, execution_context & >::value >::type = 0); `` [''''»''' [link boost_asio.reference.defer.overload3 more...]]`` @@ -78564,34 +78564,86 @@ Submits a completion token or function object for execution. template< - typename CompletionToken> + typename ``[link boost_asio.reference.NullaryToken NullaryToken]``> ``[link boost_asio.reference.asynchronous_operations.automatic_deduction_of_initiating_function_return_type ['DEDUCED]]`` defer( - CompletionToken && token); + NullaryToken && token); This function submits an object for execution using the object's associated executor. The function object is queued for execution, and is never called from the current thread prior to returning from `defer()`. The use of `defer()`, rather than [link boost_asio.reference.post `post`], indicates the caller's preference that the executor defer the queueing of the function object. This may allow the executor to optimise queueing for cases when the function object represents a continuation of the current call context. -This function has the following effects: + +[heading Parameters] + + +[variablelist + +[[token][The [link boost_asio.overview.model.completion_tokens completion token] that will be used to produce a completion handler. The function signature of the completion handler must be: +`` + void handler(); +`` +]] + +] -* Constructs a function object handler of type `Handler`, initialized with `handler(forward(token))`. +[heading Return Value] + +This function returns `async_initiate(Init{}, token)`, where `Init` is a function object type defined as: -* Constructs an object `result` of type `async_result`, initializing the object as `result(handler)`. + + class Init + { + public: + template + void operator()(CompletionHandler&& completion_handler) const; + }; -* Obtains the handler's associated executor object `ex` by performing `get_associated_executor(handler)`. -* Obtains the handler's associated allocator object `alloc` by performing `get_associated_allocator(handler)`. +The function call operator of `Init:` -* Performs `ex.defer(std::move(handler), alloc)`. +* Obtains the handler's associated executor object `ex` of type `Ex` by performing + + auto ex = get_associated_executor(handler); + + + + + +* Obtains the handler's associated allocator object `alloc` by performing + + auto alloc = get_associated_allocator(handler); + + + + + +* If `execution::is_executor::value` is true, performs + + execution::execute( + prefer( + require(ex, execution::blocking.never), + execution::relationship.continuation, + execution::allocator(alloc)), + std::forward(completion_handler)); + + + + + +* If `execution::is_executor::value` is false, performs + + ex.defer( + std::forward(completion_handler), + alloc); + -* Returns `result.get()`. [heading Completion Signature] @@ -78618,10 +78670,10 @@ Submits a completion token or function object for execution. template< typename ``[link boost_asio.reference.Executor1 Executor]``, - typename CompletionToken = ``[link boost_asio.reference.asynchronous_operations.default_completion_tokens ['DEFAULT]]``> + typename ``[link boost_asio.reference.NullaryToken NullaryToken]`` = ``[link boost_asio.reference.asynchronous_operations.default_completion_tokens ['DEFAULT]]``> ``[link boost_asio.reference.asynchronous_operations.automatic_deduction_of_initiating_function_return_type ['DEDUCED]]`` defer( const Executor & ex, - CompletionToken && token = ``[link boost_asio.reference.asynchronous_operations.default_completion_tokens ['DEFAULT]]``, + NullaryToken && token = ``[link boost_asio.reference.asynchronous_operations.default_completion_tokens ['DEFAULT]]``, typename constraint< execution::is_executor< Executor >::value||is_executor< Executor >::value >::type = 0); @@ -78629,31 +78681,105 @@ This function submits an object for execution using the specified executor. The The use of `defer()`, rather than [link boost_asio.reference.post `post`], indicates the caller's preference that the executor defer the queueing of the function object. This may allow the executor to optimise queueing for cases when the function object represents a continuation of the current call context. -This function has the following effects: + +[heading Parameters] + + +[variablelist + +[[ex][The target executor.]] + +[[token][The [link boost_asio.overview.model.completion_tokens completion token] that will be used to produce a completion handler. The function signature of the completion handler must be: +`` + void handler(); +`` +]] + +] -* Constructs a function object handler of type `Handler`, initialized with `handler(forward(token))`. +[heading Return Value] + +This function returns `async_initiate(Init{ex}, token)`, where `Init` is a function object type defined as: -* Constructs an object `result` of type `async_result`, initializing the object as `result(handler)`. + + class Init + { + public: + using executor_type = Executor; + explicit Init(const Executor& ex) : ex_(ex) {} + executor_type get_executor() const noexcept { return ex_; } + template + void operator()(CompletionHandler&& completion_handler) const; + private: + Executor ex_; // exposition only + }; -* Obtains the handler's associated executor object `ex1` by performing `get_associated_executor(handler)`. -* Creates a work object `w` by performing `make_work(ex1)`. +The function call operator of `Init:` -* Obtains the handler's associated allocator object `alloc` by performing `get_associated_allocator(handler)`. +* Obtains the handler's associated executor object `ex1` of type `Ex1` by performing + + auto ex1 = get_associated_executor(handler, ex); -* Constructs a function object `f` with a function call operator that performs `ex1.dispatch(std::move(handler), alloc)` followed by `w.reset()`. -* Performs `Executor(ex).defer(std::move(f), alloc)`. + +* Obtains the handler's associated allocator object `alloc` by performing + + auto alloc = get_associated_allocator(handler); + + + + + +* If `execution::is_executor::value` is true, constructs a function object `f` with a member `executor_` that is initialised with `prefer(ex1, execution::outstanding_work.tracked)`, a member `handler_` that is a decay-copy of `completion_handler`, and a function call operator that performs: + + auto a = get_associated_allocator(handler_); + execution::execute( + prefer(executor_, + execution::blocking.possibly, + execution::allocator(a)), + std::move(handler_)); + + + + + +* If `execution::is_executor::value` is false, constructs a function object `f` with a member `work_` that is initialised with `make_work_guard(ex1)`, a member `handler_` that is a decay-copy of `completion_handler`, and a function call operator that performs: + + auto a = get_associated_allocator(handler_); + work_.get_executor().dispatch(std::move(handler_), a); + work_.reset(); + + + + + +* If `execution::is_executor::value` is true, performs + + execution::execute( + prefer( + require(ex, execution::blocking.never), + execution::relationship.continuation, + execution::allocator(alloc)), + std::move(f)); + + + + + +* If `execution::is_executor::value` is false, performs + + ex.defer(std::move(f), alloc); + -* Returns `result.get()`. [heading Completion Signature] @@ -78680,17 +78806,33 @@ Submits a completion token or function object for execution. template< typename ExecutionContext, - typename CompletionToken = ``[link boost_asio.reference.asynchronous_operations.default_completion_tokens ['DEFAULT]]``> + typename ``[link boost_asio.reference.NullaryToken NullaryToken]`` = ``[link boost_asio.reference.asynchronous_operations.default_completion_tokens ['DEFAULT]]``> ``[link boost_asio.reference.asynchronous_operations.automatic_deduction_of_initiating_function_return_type ['DEDUCED]]`` defer( ExecutionContext & ctx, - CompletionToken && token = ``[link boost_asio.reference.asynchronous_operations.default_completion_tokens ['DEFAULT]]``, + NullaryToken && token = ``[link boost_asio.reference.asynchronous_operations.default_completion_tokens ['DEFAULT]]``, typename constraint< is_convertible< ExecutionContext &, execution_context & >::value >::type = 0); +[heading Parameters] + + +[variablelist + +[[ctx][An execution context, from which the target executor is obtained.]] + +[[token][The [link boost_asio.overview.model.completion_tokens completion token] that will be used to produce a completion handler. The function signature of the completion handler must be: +`` + void handler(); +`` +]] + +] + + [heading Return Value] -`defer(ctx.get_executor(), forward(token))`. +`defer(ctx.get_executor(), forward(token))`. [heading Completion Signature] @@ -79025,26 +79167,26 @@ A cancellation filter that disables cancellation. Submits a completion token or function object for execution. template< - typename CompletionToken> + typename ``[link boost_asio.reference.NullaryToken NullaryToken]``> ``[link boost_asio.reference.asynchronous_operations.automatic_deduction_of_initiating_function_return_type ['DEDUCED]]`` ``[link boost_asio.reference.dispatch.overload1 dispatch]``( - CompletionToken && token); + NullaryToken && token); `` [''''»''' [link boost_asio.reference.dispatch.overload1 more...]]`` template< typename ``[link boost_asio.reference.Executor1 Executor]``, - typename CompletionToken = ``[link boost_asio.reference.asynchronous_operations.default_completion_tokens ['DEFAULT]]``> + typename ``[link boost_asio.reference.NullaryToken NullaryToken]`` = ``[link boost_asio.reference.asynchronous_operations.default_completion_tokens ['DEFAULT]]``> ``[link boost_asio.reference.asynchronous_operations.automatic_deduction_of_initiating_function_return_type ['DEDUCED]]`` ``[link boost_asio.reference.dispatch.overload2 dispatch]``( const Executor & ex, - CompletionToken && token = ``[link boost_asio.reference.asynchronous_operations.default_completion_tokens ['DEFAULT]]``, + NullaryToken && token = ``[link boost_asio.reference.asynchronous_operations.default_completion_tokens ['DEFAULT]]``, typename constraint< execution::is_executor< Executor >::value||is_executor< Executor >::value >::type = 0); `` [''''»''' [link boost_asio.reference.dispatch.overload2 more...]]`` template< typename ExecutionContext, - typename CompletionToken = ``[link boost_asio.reference.asynchronous_operations.default_completion_tokens ['DEFAULT]]``> + typename ``[link boost_asio.reference.NullaryToken NullaryToken]`` = ``[link boost_asio.reference.asynchronous_operations.default_completion_tokens ['DEFAULT]]``> ``[link boost_asio.reference.asynchronous_operations.automatic_deduction_of_initiating_function_return_type ['DEDUCED]]`` ``[link boost_asio.reference.dispatch.overload3 dispatch]``( ExecutionContext & ctx, - CompletionToken && token = ``[link boost_asio.reference.asynchronous_operations.default_completion_tokens ['DEFAULT]]``, + NullaryToken && token = ``[link boost_asio.reference.asynchronous_operations.default_completion_tokens ['DEFAULT]]``, typename constraint< is_convertible< ExecutionContext &, execution_context & >::value >::type = 0); `` [''''»''' [link boost_asio.reference.dispatch.overload3 more...]]`` @@ -79062,32 +79204,83 @@ Submits a completion token or function object for execution. template< - typename CompletionToken> + typename ``[link boost_asio.reference.NullaryToken NullaryToken]``> ``[link boost_asio.reference.asynchronous_operations.automatic_deduction_of_initiating_function_return_type ['DEDUCED]]`` dispatch( - CompletionToken && token); + NullaryToken && token); This function submits an object for execution using the object's associated executor. The function object may be called from the current thread prior to returning from `dispatch()`. Otherwise, it is queued for execution. -This function has the following effects: + +[heading Parameters] + + +[variablelist + +[[token][The [link boost_asio.overview.model.completion_tokens completion token] that will be used to produce a completion handler. The function signature of the completion handler must be: +`` + void handler(); +`` +]] + +] -* Constructs a function object handler of type `Handler`, initialized with `handler(forward(token))`. +[heading Return Value] + +This function returns `async_initiate(Init{}, token)`, where `Init` is a function object type defined as: -* Constructs an object `result` of type `async_result`, initializing the object as `result(handler)`. + + class Init + { + public: + template + void operator()(CompletionHandler&& completion_handler) const; + }; -* Obtains the handler's associated executor object `ex` by performing `get_associated_executor(handler)`. -* Obtains the handler's associated allocator object `alloc` by performing `get_associated_allocator(handler)`. +The function call operator of `Init:` -* Performs `ex.dispatch(std::move(handler), alloc)`. +* Obtains the handler's associated executor object `ex` of type `Ex` by performing + + auto ex = get_associated_executor(handler); + + + + + +* Obtains the handler's associated allocator object `alloc` by performing + + auto alloc = get_associated_allocator(handler); + + + + + +* If `execution::is_executor::value` is true, performs + + execution::execute( + prefer(ex, + execution::blocking.possibly, + execution::allocator(alloc)), + std::forward(completion_handler)); + + + + + +* If `execution::is_executor::value` is false, performs + + ex.dispatch( + std::forward(completion_handler), + alloc); + -* Returns `result.get()`. [heading Completion Signature] @@ -79114,40 +79307,113 @@ Submits a completion token or function object for execution. template< typename ``[link boost_asio.reference.Executor1 Executor]``, - typename CompletionToken = ``[link boost_asio.reference.asynchronous_operations.default_completion_tokens ['DEFAULT]]``> + typename ``[link boost_asio.reference.NullaryToken NullaryToken]`` = ``[link boost_asio.reference.asynchronous_operations.default_completion_tokens ['DEFAULT]]``> ``[link boost_asio.reference.asynchronous_operations.automatic_deduction_of_initiating_function_return_type ['DEDUCED]]`` dispatch( const Executor & ex, - CompletionToken && token = ``[link boost_asio.reference.asynchronous_operations.default_completion_tokens ['DEFAULT]]``, + NullaryToken && token = ``[link boost_asio.reference.asynchronous_operations.default_completion_tokens ['DEFAULT]]``, typename constraint< execution::is_executor< Executor >::value||is_executor< Executor >::value >::type = 0); This function submits an object for execution using the specified executor. The function object may be called from the current thread prior to returning from `dispatch()`. Otherwise, it is queued for execution. -This function has the following effects: + +[heading Parameters] + + +[variablelist + +[[ex][The target executor.]] + +[[token][The [link boost_asio.overview.model.completion_tokens completion token] that will be used to produce a completion handler. The function signature of the completion handler must be: +`` + void handler(); +`` +]] + +] -* Constructs a function object handler of type `Handler`, initialized with `handler(forward(token))`. +[heading Return Value] + +This function returns `async_initiate(Init{ex}, token)`, where `Init` is a function object type defined as: -* Constructs an object `result` of type `async_result`, initializing the object as `result(handler)`. + + class Init + { + public: + using executor_type = Executor; + explicit Init(const Executor& ex) : ex_(ex) {} + executor_type get_executor() const noexcept { return ex_; } + template + void operator()(CompletionHandler&& completion_handler) const; + private: + Executor ex_; // exposition only + }; -* Obtains the handler's associated executor object `ex1` by performing `get_associated_executor(handler)`. -* Creates a work object `w` by performing `make_work(ex1)`. +The function call operator of `Init:` -* Obtains the handler's associated allocator object `alloc` by performing `get_associated_allocator(handler)`. +* Obtains the handler's associated executor object `ex1` of type `Ex1` by performing + + auto ex1 = get_associated_executor(handler, ex); -* Constructs a function object `f` with a function call operator that performs `ex1.dispatch(std::move(handler), alloc)` followed by `w.reset()`. -* Performs `Executor(ex).dispatch(std::move(f), alloc)`. + +* Obtains the handler's associated allocator object `alloc` by performing + + auto alloc = get_associated_allocator(handler); + + + + + +* If `execution::is_executor::value` is true, constructs a function object `f` with a member `executor_` that is initialised with `prefer(ex1, execution::outstanding_work.tracked)`, a member `handler_` that is a decay-copy of `completion_handler`, and a function call operator that performs: + + auto a = get_associated_allocator(handler_); + execution::execute( + prefer(executor_, + execution::blocking.possibly, + execution::allocator(a)), + std::move(handler_)); + + + + + +* If `execution::is_executor::value` is false, constructs a function object `f` with a member `work_` that is initialised with `make_work_guard(ex1)`, a member `handler_` that is a decay-copy of `completion_handler`, and a function call operator that performs: + + auto a = get_associated_allocator(handler_); + work_.get_executor().dispatch(std::move(handler_), a); + work_.reset(); + + + + + +* If `execution::is_executor::value` is true, performs + + execution::execute( + prefer(ex, + execution::blocking.possibly, + execution::allocator(alloc)), + std::move(f)); + + + + + +* If `execution::is_executor::value` is false, performs + + ex.dispatch(std::move(f), alloc); + -* Returns `result.get()`. [heading Completion Signature] @@ -79174,17 +79440,33 @@ Submits a completion token or function object for execution. template< typename ExecutionContext, - typename CompletionToken = ``[link boost_asio.reference.asynchronous_operations.default_completion_tokens ['DEFAULT]]``> + typename ``[link boost_asio.reference.NullaryToken NullaryToken]`` = ``[link boost_asio.reference.asynchronous_operations.default_completion_tokens ['DEFAULT]]``> ``[link boost_asio.reference.asynchronous_operations.automatic_deduction_of_initiating_function_return_type ['DEDUCED]]`` dispatch( ExecutionContext & ctx, - CompletionToken && token = ``[link boost_asio.reference.asynchronous_operations.default_completion_tokens ['DEFAULT]]``, + NullaryToken && token = ``[link boost_asio.reference.asynchronous_operations.default_completion_tokens ['DEFAULT]]``, typename constraint< is_convertible< ExecutionContext &, execution_context & >::value >::type = 0); +[heading Parameters] + + +[variablelist + +[[ctx][An execution context, from which the target executor is obtained.]] + +[[token][The [link boost_asio.overview.model.completion_tokens completion token] that will be used to produce a completion handler. The function signature of the completion handler must be: +`` + void handler(); +`` +]] + +] + + [heading Return Value] -`dispatch(ctx.get_executor(), forward(token))`. +`dispatch(ctx.get_executor(), forward(token))`. [heading Completion Signature] @@ -134079,26 +134361,26 @@ Synchronous `read_some` and `write_some` operations are thread safe with respect Submits a completion token or function object for execution. template< - typename CompletionToken> + typename ``[link boost_asio.reference.NullaryToken NullaryToken]``> ``[link boost_asio.reference.asynchronous_operations.automatic_deduction_of_initiating_function_return_type ['DEDUCED]]`` ``[link boost_asio.reference.post.overload1 post]``( - CompletionToken && token); + NullaryToken && token); `` [''''»''' [link boost_asio.reference.post.overload1 more...]]`` template< typename ``[link boost_asio.reference.Executor1 Executor]``, - typename CompletionToken = ``[link boost_asio.reference.asynchronous_operations.default_completion_tokens ['DEFAULT]]``> + typename ``[link boost_asio.reference.NullaryToken NullaryToken]`` = ``[link boost_asio.reference.asynchronous_operations.default_completion_tokens ['DEFAULT]]``> ``[link boost_asio.reference.asynchronous_operations.automatic_deduction_of_initiating_function_return_type ['DEDUCED]]`` ``[link boost_asio.reference.post.overload2 post]``( const Executor & ex, - CompletionToken && token = ``[link boost_asio.reference.asynchronous_operations.default_completion_tokens ['DEFAULT]]``, + NullaryToken && token = ``[link boost_asio.reference.asynchronous_operations.default_completion_tokens ['DEFAULT]]``, typename constraint< execution::is_executor< Executor >::value||is_executor< Executor >::value >::type = 0); `` [''''»''' [link boost_asio.reference.post.overload2 more...]]`` template< typename ExecutionContext, - typename CompletionToken = ``[link boost_asio.reference.asynchronous_operations.default_completion_tokens ['DEFAULT]]``> + typename ``[link boost_asio.reference.NullaryToken NullaryToken]`` = ``[link boost_asio.reference.asynchronous_operations.default_completion_tokens ['DEFAULT]]``> ``[link boost_asio.reference.asynchronous_operations.automatic_deduction_of_initiating_function_return_type ['DEDUCED]]`` ``[link boost_asio.reference.post.overload3 post]``( ExecutionContext & ctx, - CompletionToken && token = ``[link boost_asio.reference.asynchronous_operations.default_completion_tokens ['DEFAULT]]``, + NullaryToken && token = ``[link boost_asio.reference.asynchronous_operations.default_completion_tokens ['DEFAULT]]``, typename constraint< is_convertible< ExecutionContext &, execution_context & >::value >::type = 0); `` [''''»''' [link boost_asio.reference.post.overload3 more...]]`` @@ -134116,34 +134398,86 @@ Submits a completion token or function object for execution. template< - typename CompletionToken> + typename ``[link boost_asio.reference.NullaryToken NullaryToken]``> ``[link boost_asio.reference.asynchronous_operations.automatic_deduction_of_initiating_function_return_type ['DEDUCED]]`` post( - CompletionToken && token); + NullaryToken && token); This function submits an object for execution using the object's associated executor. The function object is queued for execution, and is never called from the current thread prior to returning from `post()`. The use of `post()`, rather than [link boost_asio.reference.defer `defer`], indicates the caller's preference that the function object be eagerly queued for execution. -This function has the following effects: + +[heading Parameters] + + +[variablelist + +[[token][The [link boost_asio.overview.model.completion_tokens completion token] that will be used to produce a completion handler. The function signature of the completion handler must be: +`` + void handler(); +`` +]] + +] -* Constructs a function object handler of type `Handler`, initialized with `handler(forward(token))`. +[heading Return Value] + +This function returns `async_initiate(Init{}, token)`, where `Init` is a function object type defined as: -* Constructs an object `result` of type `async_result`, initializing the object as `result(handler)`. + + class Init + { + public: + template + void operator()(CompletionHandler&& completion_handler) const; + }; -* Obtains the handler's associated executor object `ex` by performing `get_associated_executor(handler)`. -* Obtains the handler's associated allocator object `alloc` by performing `get_associated_allocator(handler)`. +The function call operator of `Init:` -* Performs `ex.post(std::move(handler), alloc)`. +* Obtains the handler's associated executor object `ex` of type `Ex` by performing + + auto ex = get_associated_executor(handler); + + + + + +* Obtains the handler's associated allocator object `alloc` by performing + + auto alloc = get_associated_allocator(handler); + + + + + +* If `execution::is_executor::value` is true, performs + + execution::execute( + prefer( + require(ex, execution::blocking.never), + execution::relationship.fork, + execution::allocator(alloc)), + std::forward(completion_handler)); + + + + + +* If `execution::is_executor::value` is false, performs + + ex.post( + std::forward(completion_handler), + alloc); + -* Returns `result.get()`. [heading Completion Signature] @@ -134170,10 +134504,10 @@ Submits a completion token or function object for execution. template< typename ``[link boost_asio.reference.Executor1 Executor]``, - typename CompletionToken = ``[link boost_asio.reference.asynchronous_operations.default_completion_tokens ['DEFAULT]]``> + typename ``[link boost_asio.reference.NullaryToken NullaryToken]`` = ``[link boost_asio.reference.asynchronous_operations.default_completion_tokens ['DEFAULT]]``> ``[link boost_asio.reference.asynchronous_operations.automatic_deduction_of_initiating_function_return_type ['DEDUCED]]`` post( const Executor & ex, - CompletionToken && token = ``[link boost_asio.reference.asynchronous_operations.default_completion_tokens ['DEFAULT]]``, + NullaryToken && token = ``[link boost_asio.reference.asynchronous_operations.default_completion_tokens ['DEFAULT]]``, typename constraint< execution::is_executor< Executor >::value||is_executor< Executor >::value >::type = 0); @@ -134181,31 +134515,105 @@ This function submits an object for execution using the specified executor. The The use of `post()`, rather than [link boost_asio.reference.defer `defer`], indicates the caller's preference that the function object be eagerly queued for execution. -This function has the following effects: + +[heading Parameters] + + +[variablelist + +[[ex][The target executor.]] + +[[token][The [link boost_asio.overview.model.completion_tokens completion token] that will be used to produce a completion handler. The function signature of the completion handler must be: +`` + void handler(); +`` +]] + +] -* Constructs a function object handler of type `Handler`, initialized with `handler(forward(token))`. +[heading Return Value] + +This function returns `async_initiate(Init{ex}, token)`, where `Init` is a function object type defined as: -* Constructs an object `result` of type `async_result`, initializing the object as `result(handler)`. + + class Init + { + public: + using executor_type = Executor; + explicit Init(const Executor& ex) : ex_(ex) {} + executor_type get_executor() const noexcept { return ex_; } + template + void operator()(CompletionHandler&& completion_handler) const; + private: + Executor ex_; // exposition only + }; -* Obtains the handler's associated executor object `ex1` by performing `get_associated_executor(handler)`. -* Creates a work object `w` by performing `make_work(ex1)`. +The function call operator of `Init:` -* Obtains the handler's associated allocator object `alloc` by performing `get_associated_allocator(handler)`. +* Obtains the handler's associated executor object `ex1` of type `Ex1` by performing + + auto ex1 = get_associated_executor(handler, ex); -* Constructs a function object `f` with a function call operator that performs `ex1.dispatch(std::move(handler), alloc)` followed by `w.reset()`. -* Performs `Executor(ex).post(std::move(f), alloc)`. + +* Obtains the handler's associated allocator object `alloc` by performing + + auto alloc = get_associated_allocator(handler); + + + + + +* If `execution::is_executor::value` is true, constructs a function object `f` with a member `executor_` that is initialised with `prefer(ex1, execution::outstanding_work.tracked)`, a member `handler_` that is a decay-copy of `completion_handler`, and a function call operator that performs: + + auto a = get_associated_allocator(handler_); + execution::execute( + prefer(executor_, + execution::blocking.possibly, + execution::allocator(a)), + std::move(handler_)); + + + + + +* If `execution::is_executor::value` is false, constructs a function object `f` with a member `work_` that is initialised with `make_work_guard(ex1)`, a member `handler_` that is a decay-copy of `completion_handler`, and a function call operator that performs: + + auto a = get_associated_allocator(handler_); + work_.get_executor().dispatch(std::move(handler_), a); + work_.reset(); + + + + + +* If `execution::is_executor::value` is true, performs + + execution::execute( + prefer( + require(ex, execution::blocking.never), + execution::relationship.fork, + execution::allocator(alloc)), + std::move(f)); + + + + + +* If `execution::is_executor::value` is false, performs + + ex.post(std::move(f), alloc); + -* Returns `result.get()`. [heading Completion Signature] @@ -134232,17 +134640,33 @@ Submits a completion token or function object for execution. template< typename ExecutionContext, - typename CompletionToken = ``[link boost_asio.reference.asynchronous_operations.default_completion_tokens ['DEFAULT]]``> + typename ``[link boost_asio.reference.NullaryToken NullaryToken]`` = ``[link boost_asio.reference.asynchronous_operations.default_completion_tokens ['DEFAULT]]``> ``[link boost_asio.reference.asynchronous_operations.automatic_deduction_of_initiating_function_return_type ['DEDUCED]]`` post( ExecutionContext & ctx, - CompletionToken && token = ``[link boost_asio.reference.asynchronous_operations.default_completion_tokens ['DEFAULT]]``, + NullaryToken && token = ``[link boost_asio.reference.asynchronous_operations.default_completion_tokens ['DEFAULT]]``, typename constraint< is_convertible< ExecutionContext &, execution_context & >::value >::type = 0); +[heading Parameters] + + +[variablelist + +[[ctx][An execution context, from which the target executor is obtained.]] + +[[token][The [link boost_asio.overview.model.completion_tokens completion token] that will be used to produce a completion handler. The function signature of the completion handler must be: +`` + void handler(); +`` +]] + +] + + [heading Return Value] -`post(ctx.get_executor(), forward(token))`. +`post(ctx.get_executor(), forward(token))`. [heading Completion Signature] diff --git a/doc/reference.xsl b/doc/reference.xsl index 7105f3b8..48f80e41 100644 --- a/doc/reference.xsl +++ b/doc/reference.xsl @@ -56,7 +56,6 @@ [include requirements/CancellationHandler.qbk] [include requirements/CancellationSlot.qbk] [include requirements/CompletionCondition.qbk] -[include requirements/CompletionHandler.qbk] [include requirements/ConnectCondition.qbk] [include requirements/ConnectHandler.qbk] [include requirements/ConnectToken.qbk] @@ -82,6 +81,7 @@ [include requirements/MoveAcceptHandler.qbk] [include requirements/MoveAcceptToken.qbk] [include requirements/MutableBufferSequence.qbk] +[include requirements/NullaryToken.qbk] [include requirements/OperationState.qbk] [include requirements/ProtoAllocator.qbk] [include requirements/Protocol.qbk] @@ -1646,6 +1646,9 @@ + + + diff --git a/doc/requirements/CompletionHandler.qbk b/doc/requirements/CompletionHandler.qbk deleted file mode 100644 index 5445bcb2..00000000 --- a/doc/requirements/CompletionHandler.qbk +++ /dev/null @@ -1,63 +0,0 @@ -[/ - / Copyright (c) 2003-2022 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) - /] - -[section:CompletionHandler Completion handler requirements] - -A completion handler must meet the requirements for a [link -boost_asio.reference.Handler handler]. A value `h` of a completion handler -class should work correctly in the expression `h()`. - -[heading Examples] - -A free function as a completion handler: - - void completion_handler() - { - ... - } - -A completion handler function object: - - struct completion_handler - { - ... - void operator()() - { - ... - } - ... - }; - -A lambda as a completion handler: - - my_io_service.post( - []() - { - ... - }); - -A non-static class member function adapted to a completion handler using -`std::bind()`: - - void my_class::completion_handler() - { - ... - } - ... - my_io_service.post(std::bind(&my_class::completion_handler, this)); - -A non-static class member function adapted to a completion handler using -`boost::bind()`: - - void my_class::completion_handler() - { - ... - } - ... - my_io_service.post(boost::bind(&my_class::completion_handler, this)); - -[endsect] diff --git a/doc/requirements/NullaryToken.qbk b/doc/requirements/NullaryToken.qbk new file mode 100644 index 00000000..1b17c74e --- /dev/null +++ b/doc/requirements/NullaryToken.qbk @@ -0,0 +1,79 @@ +[/ + / Copyright (c) 2003-2022 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) + /] + +[section:NullaryToken Nullary token requirements] + +A nullary token is a [link boost_asio.overview.model.completion_tokens completion +token] for completion signature `void()`. + +[heading Examples] + +A free function as a nullary token: + + void nullary_handler() + { + ... + } + +A nullary token function object: + + struct nullary_handler + { + ... + void operator()() + { + ... + } + ... + }; + +A lambda as a nullary token: + + boost::asio::post(..., + []() + { + ... + }); + +A non-static class member function adapted to a nullary token using +`std::bind()`: + + void my_class::nullary_handler() + { + ... + } + ... + boost::asio::post(..., + std::bind(&my_class::nullary_handler, this)); + +A non-static class member function adapted to a nullary token using +`boost::bind()`: + + void my_class::nullary_handler() + { + ... + } + ... + boost::asio::post(..., + boost::bind(&my_class::nullary_handler, this)); + +Using [link boost_asio.reference.use_future use_future] as a nullary token: + + std::future f = boost::asio::post(..., boost::asio::use_future); + ... + f.get(); + +Using [link boost_asio.reference.use_awaitable use_awaitable] as a nullary token: + + boost::asio::awaitable my_coroutine() + { + ... + co_await boost::asio::post(..., boost::asio::use_awaitable); + ... + } + +[endsect] diff --git a/include/boost/asio/defer.hpp b/include/boost/asio/defer.hpp index 4eb16e8c..2411f7f5 100644 --- a/include/boost/asio/defer.hpp +++ b/include/boost/asio/defer.hpp @@ -38,30 +38,48 @@ namespace asio { * may allow the executor to optimise queueing for cases when the function * object represents a continuation of the current call context. * - * This function has the following effects: + * @param token The @ref completion_token that will be used to produce a + * completion handler. The function signature of the completion handler must be: + * @code void handler(); @endcode * - * @li Constructs a function object handler of type @c Handler, initialized - * with handler(forward(token)). + * @returns This function returns async_initiate(Init{}, token), where @c Init is a function object type defined + * as: * - * @li Constructs an object @c result of type async_result, - * initializing the object as result(handler). + * @code class Init + * { + * public: + * template + * void operator()(CompletionHandler&& completion_handler) const; + * }; @endcode * - * @li Obtains the handler's associated executor object @c ex by performing - * get_associated_executor(handler). + * The function call operator of @c Init: + * + * @li Obtains the handler's associated executor object @c ex of type @c Ex by + * performing @code auto ex = get_associated_executor(handler); @endcode * * @li Obtains the handler's associated allocator object @c alloc by performing - * get_associated_allocator(handler). + * @code auto alloc = get_associated_allocator(handler); @endcode * - * @li Performs ex.defer(std::move(handler), alloc). + * @li If execution::is_executor::value is true, performs + * @code execution::execute( + * prefer( + * require(ex, execution::blocking.never), + * execution::relationship.continuation, + * execution::allocator(alloc)), + * std::forward(completion_handler)); @endcode * - * @li Returns result.get(). + * @li If execution::is_executor::value is false, performs + * @code ex.defer( + * std::forward(completion_handler), + * alloc); @endcode * * @par Completion Signature * @code void() @endcode */ -template -BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) defer( - BOOST_ASIO_MOVE_ARG(CompletionToken) token); +template +BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(NullaryToken, void()) defer( + BOOST_ASIO_MOVE_ARG(NullaryToken) token); /// Submits a completion token or function object for execution. /** @@ -74,39 +92,76 @@ BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) defer( * may allow the executor to optimise queueing for cases when the function * object represents a continuation of the current call context. * - * This function has the following effects: + * @param ex The target executor. * - * @li Constructs a function object handler of type @c Handler, initialized - * with handler(forward(token)). + * @param token The @ref completion_token that will be used to produce a + * completion handler. The function signature of the completion handler must be: + * @code void handler(); @endcode * - * @li Constructs an object @c result of type async_result, - * initializing the object as result(handler). + * @returns This function returns async_initiate(Init{ex}, token), where @c Init is a function object type + * defined as: * - * @li Obtains the handler's associated executor object @c ex1 by performing - * get_associated_executor(handler). + * @code class Init + * { + * public: + * using executor_type = Executor; + * explicit Init(const Executor& ex) : ex_(ex) {} + * executor_type get_executor() const noexcept { return ex_; } + * template + * void operator()(CompletionHandler&& completion_handler) const; + * private: + * Executor ex_; // exposition only + * }; @endcode * - * @li Creates a work object @c w by performing make_work(ex1). + * The function call operator of @c Init: + * + * @li Obtains the handler's associated executor object @c ex1 of type @c Ex1 by + * performing @code auto ex1 = get_associated_executor(handler, ex); @endcode * * @li Obtains the handler's associated allocator object @c alloc by performing - * get_associated_allocator(handler). + * @code auto alloc = get_associated_allocator(handler); @endcode * - * @li Constructs a function object @c f with a function call operator that - * performs ex1.dispatch(std::move(handler), alloc) followed by - * w.reset(). + * @li If execution::is_executor::value is true, constructs a + * function object @c f with a member @c executor_ that is initialised with + * prefer(ex1, execution::outstanding_work.tracked), a member @c + * handler_ that is a decay-copy of @c completion_handler, and a function call + * operator that performs: + * @code auto a = get_associated_allocator(handler_); + * execution::execute( + * prefer(executor_, + * execution::blocking.possibly, + * execution::allocator(a)), + * std::move(handler_)); @endcode * - * @li Performs Executor(ex).defer(std::move(f), alloc). + * @li If execution::is_executor::value is false, constructs a + * function object @c f with a member @c work_ that is initialised with + * make_work_guard(ex1), a member @c handler_ that is a decay-copy of + * @c completion_handler, and a function call operator that performs: + * @code auto a = get_associated_allocator(handler_); + * work_.get_executor().dispatch(std::move(handler_), a); + * work_.reset(); @endcode * - * @li Returns result.get(). + * @li If execution::is_executor::value is true, performs + * @code execution::execute( + * prefer( + * require(ex, execution::blocking.never), + * execution::relationship.continuation, + * execution::allocator(alloc)), + * std::move(f)); @endcode + * + * @li If execution::is_executor::value is false, performs + * @code ex.defer(std::move(f), alloc); @endcode * * @par Completion Signature * @code void() @endcode */ template -BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) defer( +BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(NullaryToken, void()) defer( const Executor& ex, - BOOST_ASIO_MOVE_ARG(CompletionToken) token + BOOST_ASIO_MOVE_ARG(NullaryToken) token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(Executor), typename constraint< execution::is_executor::value || is_executor::value @@ -114,18 +169,24 @@ BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) defer( /// Submits a completion token or function object for execution. /** - * @returns defer(ctx.get_executor(), forward(token)). + * @param ctx An execution context, from which the target executor is obtained. + * + * @param token The @ref completion_token that will be used to produce a + * completion handler. The function signature of the completion handler must be: + * @code void handler(); @endcode + * + * @returns defer(ctx.get_executor(), forward(token)). * * @par Completion Signature * @code void() @endcode */ template -BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) defer( +BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(NullaryToken, void()) defer( ExecutionContext& ctx, - BOOST_ASIO_MOVE_ARG(CompletionToken) token + BOOST_ASIO_MOVE_ARG(NullaryToken) token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN( typename ExecutionContext::executor_type), typename constraintdispatch(). Otherwise, it is queued for execution. * - * This function has the following effects: + * @param token The @ref completion_token that will be used to produce a + * completion handler. The function signature of the completion handler must be: + * @code void handler(); @endcode * - * @li Constructs a function object handler of type @c Handler, initialized - * with handler(forward(token)). + * @returns This function returns async_initiate(Init{}, token), where @c Init is a function object type defined + * as: * - * @li Constructs an object @c result of type async_result, - * initializing the object as result(handler). + * @code class Init + * { + * public: + * template + * void operator()(CompletionHandler&& completion_handler) const; + * }; @endcode * - * @li Obtains the handler's associated executor object @c ex by performing - * get_associated_executor(handler). + * The function call operator of @c Init: + * + * @li Obtains the handler's associated executor object @c ex of type @c Ex by + * performing @code auto ex = get_associated_executor(handler); @endcode * * @li Obtains the handler's associated allocator object @c alloc by performing - * get_associated_allocator(handler). + * @code auto alloc = get_associated_allocator(handler); @endcode * - * @li Performs ex.dispatch(std::move(handler), alloc). + * @li If execution::is_executor::value is true, performs + * @code execution::execute( + * prefer(ex, + * execution::blocking.possibly, + * execution::allocator(alloc)), + * std::forward(completion_handler)); @endcode * - * @li Returns result.get(). + * @li If execution::is_executor::value is false, performs + * @code ex.dispatch( + * std::forward(completion_handler), + * alloc); @endcode * * @par Completion Signature * @code void() @endcode */ -template -BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) dispatch( - BOOST_ASIO_MOVE_ARG(CompletionToken) token); +template +BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(NullaryToken, void()) dispatch( + BOOST_ASIO_MOVE_ARG(NullaryToken) token); /// Submits a completion token or function object for execution. /** @@ -64,39 +81,75 @@ BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) dispatch( * The function object may be called from the current thread prior to returning * from dispatch(). Otherwise, it is queued for execution. * - * This function has the following effects: + * @param ex The target executor. * - * @li Constructs a function object handler of type @c Handler, initialized - * with handler(forward(token)). + * @param token The @ref completion_token that will be used to produce a + * completion handler. The function signature of the completion handler must be: + * @code void handler(); @endcode * - * @li Constructs an object @c result of type async_result, - * initializing the object as result(handler). + * @returns This function returns async_initiate(Init{ex}, token), where @c Init is a function object type + * defined as: * - * @li Obtains the handler's associated executor object @c ex1 by performing - * get_associated_executor(handler). + * @code class Init + * { + * public: + * using executor_type = Executor; + * explicit Init(const Executor& ex) : ex_(ex) {} + * executor_type get_executor() const noexcept { return ex_; } + * template + * void operator()(CompletionHandler&& completion_handler) const; + * private: + * Executor ex_; // exposition only + * }; @endcode * - * @li Creates a work object @c w by performing make_work(ex1). + * The function call operator of @c Init: + * + * @li Obtains the handler's associated executor object @c ex1 of type @c Ex1 by + * performing @code auto ex1 = get_associated_executor(handler, ex); @endcode * * @li Obtains the handler's associated allocator object @c alloc by performing - * get_associated_allocator(handler). + * @code auto alloc = get_associated_allocator(handler); @endcode * - * @li Constructs a function object @c f with a function call operator that - * performs ex1.dispatch(std::move(handler), alloc) followed by - * w.reset(). + * @li If execution::is_executor::value is true, constructs a + * function object @c f with a member @c executor_ that is initialised with + * prefer(ex1, execution::outstanding_work.tracked), a member @c + * handler_ that is a decay-copy of @c completion_handler, and a function call + * operator that performs: + * @code auto a = get_associated_allocator(handler_); + * execution::execute( + * prefer(executor_, + * execution::blocking.possibly, + * execution::allocator(a)), + * std::move(handler_)); @endcode * - * @li Performs Executor(ex).dispatch(std::move(f), alloc). + * @li If execution::is_executor::value is false, constructs a + * function object @c f with a member @c work_ that is initialised with + * make_work_guard(ex1), a member @c handler_ that is a decay-copy of + * @c completion_handler, and a function call operator that performs: + * @code auto a = get_associated_allocator(handler_); + * work_.get_executor().dispatch(std::move(handler_), a); + * work_.reset(); @endcode * - * @li Returns result.get(). + * @li If execution::is_executor::value is true, performs + * @code execution::execute( + * prefer(ex, + * execution::blocking.possibly, + * execution::allocator(alloc)), + * std::move(f)); @endcode + * + * @li If execution::is_executor::value is false, performs + * @code ex.dispatch(std::move(f), alloc); @endcode * * @par Completion Signature * @code void() @endcode */ template -BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) dispatch( +BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(NullaryToken, void()) dispatch( const Executor& ex, - BOOST_ASIO_MOVE_ARG(CompletionToken) token + BOOST_ASIO_MOVE_ARG(NullaryToken) token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(Executor), typename constraint< execution::is_executor::value || is_executor::value @@ -104,19 +157,25 @@ BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) dispatch( /// Submits a completion token or function object for execution. /** + * @param ctx An execution context, from which the target executor is obtained. + * + * @param token The @ref completion_token that will be used to produce a + * completion handler. The function signature of the completion handler must be: + * @code void handler(); @endcode + * * @returns dispatch(ctx.get_executor(), - * forward(token)). + * forward(token)). * * @par Completion Signature * @code void() @endcode */ template -BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) dispatch( +BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(NullaryToken, void()) dispatch( ExecutionContext& ctx, - BOOST_ASIO_MOVE_ARG(CompletionToken) token + BOOST_ASIO_MOVE_ARG(NullaryToken) token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN( typename ExecutionContext::executor_type), typename constraint -BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) defer( - BOOST_ASIO_MOVE_ARG(CompletionToken) token) +template +BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(NullaryToken, void()) defer( + BOOST_ASIO_MOVE_ARG(NullaryToken) token) { - return async_initiate( + return async_initiate( detail::initiate_defer(), token); } template -BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) defer( - const Executor& ex, BOOST_ASIO_MOVE_ARG(CompletionToken) token, + BOOST_ASIO_COMPLETION_TOKEN_FOR(void()) NullaryToken> +BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(NullaryToken, void()) defer( + const Executor& ex, BOOST_ASIO_MOVE_ARG(NullaryToken) token, typename constraint< execution::is_executor::value || is_executor::value >::type) { - return async_initiate( + return async_initiate( detail::initiate_defer_with_executor(ex), token); } template -inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) defer( - ExecutionContext& ctx, BOOST_ASIO_MOVE_ARG(CompletionToken) token, + BOOST_ASIO_COMPLETION_TOKEN_FOR(void()) NullaryToken> +inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(NullaryToken, void()) defer( + ExecutionContext& ctx, BOOST_ASIO_MOVE_ARG(NullaryToken) token, typename constraint::value>::type) { - return async_initiate( + return async_initiate( detail::initiate_defer_with_executor< typename ExecutionContext::executor_type>( ctx.get_executor()), token); diff --git a/include/boost/asio/impl/dispatch.hpp b/include/boost/asio/impl/dispatch.hpp index 16d846e9..589d6f15 100644 --- a/include/boost/asio/impl/dispatch.hpp +++ b/include/boost/asio/impl/dispatch.hpp @@ -212,34 +212,34 @@ private: } // namespace detail -template -BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) dispatch( - BOOST_ASIO_MOVE_ARG(CompletionToken) token) +template +BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(NullaryToken, void()) dispatch( + BOOST_ASIO_MOVE_ARG(NullaryToken) token) { - return async_initiate( + return async_initiate( detail::initiate_dispatch(), token); } template -BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) dispatch( - const Executor& ex, BOOST_ASIO_MOVE_ARG(CompletionToken) token, + BOOST_ASIO_COMPLETION_TOKEN_FOR(void()) NullaryToken> +BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(NullaryToken, void()) dispatch( + const Executor& ex, BOOST_ASIO_MOVE_ARG(NullaryToken) token, typename constraint< execution::is_executor::value || is_executor::value >::type) { - return async_initiate( + return async_initiate( detail::initiate_dispatch_with_executor(ex), token); } template -inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) dispatch( - ExecutionContext& ctx, BOOST_ASIO_MOVE_ARG(CompletionToken) token, + BOOST_ASIO_COMPLETION_TOKEN_FOR(void()) NullaryToken> +inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(NullaryToken, void()) dispatch( + ExecutionContext& ctx, BOOST_ASIO_MOVE_ARG(NullaryToken) token, typename constraint::value>::type) { - return async_initiate( + return async_initiate( detail::initiate_dispatch_with_executor< typename ExecutionContext::executor_type>( ctx.get_executor()), token); diff --git a/include/boost/asio/impl/post.hpp b/include/boost/asio/impl/post.hpp index c712fb0a..8c4a0baa 100644 --- a/include/boost/asio/impl/post.hpp +++ b/include/boost/asio/impl/post.hpp @@ -217,34 +217,34 @@ private: } // namespace detail -template -BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) post( - BOOST_ASIO_MOVE_ARG(CompletionToken) token) +template +BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(NullaryToken, void()) post( + BOOST_ASIO_MOVE_ARG(NullaryToken) token) { - return async_initiate( + return async_initiate( detail::initiate_post(), token); } template -BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) post( - const Executor& ex, BOOST_ASIO_MOVE_ARG(CompletionToken) token, + BOOST_ASIO_COMPLETION_TOKEN_FOR(void()) NullaryToken> +BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(NullaryToken, void()) post( + const Executor& ex, BOOST_ASIO_MOVE_ARG(NullaryToken) token, typename constraint< execution::is_executor::value || is_executor::value >::type) { - return async_initiate( + return async_initiate( detail::initiate_post_with_executor(ex), token); } template -inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) post( - ExecutionContext& ctx, BOOST_ASIO_MOVE_ARG(CompletionToken) token, + BOOST_ASIO_COMPLETION_TOKEN_FOR(void()) NullaryToken> +inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(NullaryToken, void()) post( + ExecutionContext& ctx, BOOST_ASIO_MOVE_ARG(NullaryToken) token, typename constraint::value>::type) { - return async_initiate( + return async_initiate( detail::initiate_post_with_executor< typename ExecutionContext::executor_type>( ctx.get_executor()), token); diff --git a/include/boost/asio/post.hpp b/include/boost/asio/post.hpp index f65103eb..acf02ede 100644 --- a/include/boost/asio/post.hpp +++ b/include/boost/asio/post.hpp @@ -36,30 +36,48 @@ namespace asio { * The use of @c post(), rather than @ref defer(), indicates the caller's * preference that the function object be eagerly queued for execution. * - * This function has the following effects: + * @param token The @ref completion_token that will be used to produce a + * completion handler. The function signature of the completion handler must be: + * @code void handler(); @endcode * - * @li Constructs a function object handler of type @c Handler, initialized - * with handler(forward(token)). + * @returns This function returns async_initiate(Init{}, token), where @c Init is a function object type defined + * as: * - * @li Constructs an object @c result of type async_result, - * initializing the object as result(handler). + * @code class Init + * { + * public: + * template + * void operator()(CompletionHandler&& completion_handler) const; + * }; @endcode * - * @li Obtains the handler's associated executor object @c ex by performing - * get_associated_executor(handler). + * The function call operator of @c Init: + * + * @li Obtains the handler's associated executor object @c ex of type @c Ex by + * performing @code auto ex = get_associated_executor(handler); @endcode * * @li Obtains the handler's associated allocator object @c alloc by performing - * get_associated_allocator(handler). + * @code auto alloc = get_associated_allocator(handler); @endcode * - * @li Performs ex.post(std::move(handler), alloc). + * @li If execution::is_executor::value is true, performs + * @code execution::execute( + * prefer( + * require(ex, execution::blocking.never), + * execution::relationship.fork, + * execution::allocator(alloc)), + * std::forward(completion_handler)); @endcode * - * @li Returns result.get(). + * @li If execution::is_executor::value is false, performs + * @code ex.post( + * std::forward(completion_handler), + * alloc); @endcode * * @par Completion Signature * @code void() @endcode */ -template -BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) post( - BOOST_ASIO_MOVE_ARG(CompletionToken) token); +template +BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(NullaryToken, void()) post( + BOOST_ASIO_MOVE_ARG(NullaryToken) token); /// Submits a completion token or function object for execution. /** @@ -70,39 +88,76 @@ BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) post( * The use of @c post(), rather than @ref defer(), indicates the caller's * preference that the function object be eagerly queued for execution. * - * This function has the following effects: + * @param ex The target executor. * - * @li Constructs a function object handler of type @c Handler, initialized - * with handler(forward(token)). + * @param token The @ref completion_token that will be used to produce a + * completion handler. The function signature of the completion handler must be: + * @code void handler(); @endcode * - * @li Constructs an object @c result of type async_result, - * initializing the object as result(handler). + * @returns This function returns async_initiate(Init{ex}, token), where @c Init is a function object type + * defined as: * - * @li Obtains the handler's associated executor object @c ex1 by performing - * get_associated_executor(handler). + * @code class Init + * { + * public: + * using executor_type = Executor; + * explicit Init(const Executor& ex) : ex_(ex) {} + * executor_type get_executor() const noexcept { return ex_; } + * template + * void operator()(CompletionHandler&& completion_handler) const; + * private: + * Executor ex_; // exposition only + * }; @endcode * - * @li Creates a work object @c w by performing make_work(ex1). + * The function call operator of @c Init: + * + * @li Obtains the handler's associated executor object @c ex1 of type @c Ex1 by + * performing @code auto ex1 = get_associated_executor(handler, ex); @endcode * * @li Obtains the handler's associated allocator object @c alloc by performing - * get_associated_allocator(handler). + * @code auto alloc = get_associated_allocator(handler); @endcode * - * @li Constructs a function object @c f with a function call operator that - * performs ex1.dispatch(std::move(handler), alloc) followed by - * w.reset(). + * @li If execution::is_executor::value is true, constructs a + * function object @c f with a member @c executor_ that is initialised with + * prefer(ex1, execution::outstanding_work.tracked), a member @c + * handler_ that is a decay-copy of @c completion_handler, and a function call + * operator that performs: + * @code auto a = get_associated_allocator(handler_); + * execution::execute( + * prefer(executor_, + * execution::blocking.possibly, + * execution::allocator(a)), + * std::move(handler_)); @endcode * - * @li Performs Executor(ex).post(std::move(f), alloc). + * @li If execution::is_executor::value is false, constructs a + * function object @c f with a member @c work_ that is initialised with + * make_work_guard(ex1), a member @c handler_ that is a decay-copy of + * @c completion_handler, and a function call operator that performs: + * @code auto a = get_associated_allocator(handler_); + * work_.get_executor().dispatch(std::move(handler_), a); + * work_.reset(); @endcode * - * @li Returns result.get(). + * @li If execution::is_executor::value is true, performs + * @code execution::execute( + * prefer( + * require(ex, execution::blocking.never), + * execution::relationship.fork, + * execution::allocator(alloc)), + * std::move(f)); @endcode + * + * @li If execution::is_executor::value is false, performs + * @code ex.post(std::move(f), alloc); @endcode * * @par Completion Signature * @code void() @endcode */ template -BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) post( +BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(NullaryToken, void()) post( const Executor& ex, - BOOST_ASIO_MOVE_ARG(CompletionToken) token + BOOST_ASIO_MOVE_ARG(NullaryToken) token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(Executor), typename constraint< execution::is_executor::value || is_executor::value @@ -110,18 +165,24 @@ BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) post( /// Submits a completion token or function object for execution. /** - * @returns post(ctx.get_executor(), forward(token)). + * @param ctx An execution context, from which the target executor is obtained. + * + * @param token The @ref completion_token that will be used to produce a + * completion handler. The function signature of the completion handler must be: + * @code void handler(); @endcode + * + * @returns post(ctx.get_executor(), forward(token)). * * @par Completion Signature * @code void() @endcode */ template -BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) post( +BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(NullaryToken, void()) post( ExecutionContext& ctx, - BOOST_ASIO_MOVE_ARG(CompletionToken) token + BOOST_ASIO_MOVE_ARG(NullaryToken) token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN( typename ExecutionContext::executor_type), typename constraint