diff --git a/doc/examples.qbk b/doc/examples.qbk index aafc1721..c238f80c 100644 --- a/doc/examples.qbk +++ b/doc/examples.qbk @@ -398,10 +398,15 @@ Boost.Asio's asynchronous operations. [heading Handler Tracking] -This example shows how to implement custom handler tracking. +This example header file shows how to implement custom handler tracking. * [@boost_asio/example/cpp11/handler_tracking/custom_tracking.hpp] +This example program shows how to include source location information in +the handler tracking output. + +* [@boost_asio/example/cpp11/handler_tracking/async_tcp_echo_server.cpp] + [heading HTTP Server] diff --git a/doc/net_ts.qbk b/doc/net_ts.qbk index 32ab46d9..4ffee0ad 100644 --- a/doc/net_ts.qbk +++ b/doc/net_ts.qbk @@ -44,14 +44,14 @@ below shows the new Networking TS interfaces and the facilities they replace: ExecutionContext].] ] [ - [[link boost_asio.reference.dispatch `post`]] + [[link boost_asio.reference.post `post`]] [[link boost_asio.reference.io_context.post `io_service::post`]] - [The `dispatch` free function can be used to submit functions to any [link + [The `post` free function can be used to submit functions to any [link boost_asio.reference.Executor1 Executor] or [link boost_asio.reference.ExecutionContext ExecutionContext].] ] [ - [[link boost_asio.reference.dispatch `defer`]] + [[link boost_asio.reference.defer `defer`]] [[link boost_asio.reference.io_context.post `io_service::post`] when the [link boost_asio.reference.asio_handler_is_continuation `asio_handler_is_continuation`] hook returns true] diff --git a/doc/overview/coroutines_ts.qbk b/doc/overview/coroutines_ts.qbk index 7638e72d..04a07774 100644 --- a/doc/overview/coroutines_ts.qbk +++ b/doc/overview/coroutines_ts.qbk @@ -14,12 +14,7 @@ boost_asio.reference.co_spawn `co_spawn()`] function. These facilities allow pro to implement asynchronous logic in a synchronous manner, in conjunction with the `co_await` keyword, as shown in the following example: - boost::asio::co_spawn(executor, - [socket = std::move(socket)]() mutable - { - return echo(std::move(socket)); - }, - boost::asio::detached); + boost::asio::co_spawn(executor, echo(std::move(socket)), boost::asio::detached); // ... @@ -46,10 +41,12 @@ 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 synchronisation is required. -The second argument is a nullary function object that returns a [link -boost_asio.reference.awaitable `boost::asio::awaitable`], -where `R` is the type of return value produced by the coroutine. In the above -example, the coroutine returns `void`. +The second argument is an [link boost_asio.reference.awaitable `awaitable`], +that is the result of the coroutine's entry point function, and in the above +example is the result of the call to `echo`. (Alternatively, this argument can +be a function object that returns the [link boost_asio.reference.awaitable +`awaitable`].) The template parameter `R` is the type of return value +produced by the coroutine. In the above example, the coroutine returns `void`. The third argument is a completion token, and this is used by `co_spawn()` to produce a completion handler with signature `void(std::exception_ptr, R)`. This diff --git a/doc/overview/handler_tracking.qbk b/doc/overview/handler_tracking.qbk index fad1ef59..5cb34ce9 100644 --- a/doc/overview/handler_tracking.qbk +++ b/doc/overview/handler_tracking.qbk @@ -18,30 +18,31 @@ asynchronous operations are chained together, or what the pending asynchronous operations are. As an illustration, here is the output when you run the HTTP Server example, handle a single request, then shut down via Ctrl+C: - @asio|1512254357.979980|0*1|signal_set@0x7ffeaaaa20d8.async_wait - @asio|1512254357.980127|0*2|socket@0x7ffeaaaa20f8.async_accept - @asio|1512254357.980150|.2|non_blocking_accept,ec=asio.system:11 - @asio|1512254357.980162|0|resolver@0x7ffeaaaa1fd8.cancel - @asio|1512254368.457147|.2|non_blocking_accept,ec=system:0 - @asio|1512254368.457193|>2|ec=system:0 - @asio|1512254368.457219|2*3|socket@0x55cf39f0a238.async_receive - @asio|1512254368.457244|.3|non_blocking_recv,ec=system:0,bytes_transferred=141 - @asio|1512254368.457275|2*4|socket@0x7ffeaaaa20f8.async_accept - @asio|1512254368.457293|.4|non_blocking_accept,ec=asio.system:11 - @asio|1512254368.457301|<2| - @asio|1512254368.457310|>3|ec=system:0,bytes_transferred=141 - @asio|1512254368.457441|3*5|socket@0x55cf39f0a238.async_send - @asio|1512254368.457502|.5|non_blocking_send,ec=system:0,bytes_transferred=156 - @asio|1512254368.457511|<3| - @asio|1512254368.457519|>5|ec=system:0,bytes_transferred=156 - @asio|1512254368.457544|5|socket@0x55cf39f0a238.close - @asio|1512254368.457559|<5| - @asio|1512254371.385106|>1|ec=system:0,signal_number=2 - @asio|1512254371.385130|1|socket@0x7ffeaaaa20f8.close - @asio|1512254371.385163|<1| - @asio|1512254371.385175|>4|ec=asio.system:125 - @asio|1512254371.385182|<4| - @asio|1512254371.385202|0|signal_set@0x7ffeaaaa20d8.cancel + @asio|1589424178.741850|0*1|signal_set@0x7ffee977d878.async_wait + @asio|1589424178.742593|0*2|socket@0x7ffee977d8a8.async_accept + @asio|1589424178.742619|.2|non_blocking_accept,ec=asio.system:11 + @asio|1589424178.742625|0|resolver@0x7ffee977d760.cancel + @asio|1589424195.830382|.2|non_blocking_accept,ec=system:0 + @asio|1589424195.830413|>2|ec=system:0 + @asio|1589424195.830473|2*3|socket@0x7fa71d808230.async_receive + @asio|1589424195.830496|.3|non_blocking_recv,ec=system:0,bytes_transferred=151 + @asio|1589424195.830503|2*4|socket@0x7ffee977d8a8.async_accept + @asio|1589424195.830507|.4|non_blocking_accept,ec=asio.system:11 + @asio|1589424195.830510|<2| + @asio|1589424195.830529|>3|ec=system:0,bytes_transferred=151 + @asio|1589424195.831143|3^5|in 'async_write' (./../../../boost/asio/impl/write.hpp:330) + @asio|1589424195.831143|3*5|socket@0x7fa71d808230.async_send + @asio|1589424195.831186|.5|non_blocking_send,ec=system:0,bytes_transferred=1090 + @asio|1589424195.831194|<3| + @asio|1589424195.831218|>5|ec=system:0,bytes_transferred=1090 + @asio|1589424195.831263|5|socket@0x7fa71d808230.close + @asio|1589424195.831298|<5| + @asio|1589424199.793770|>1|ec=system:0,signal_number=2 + @asio|1589424199.793781|1|socket@0x7ffee977d8a8.close + @asio|1589424199.793809|<1| + @asio|1589424199.793840|>4|ec=asio.system:125 + @asio|1589424199.793854|<4| + @asio|1589424199.793883|0|signal_set@0x7ffee977d878.cancel Each line is of the form: @@ -74,6 +75,13 @@ The `` takes one of the following forms: usually the case for any unfinished asynchronous operations when the `io_context` is destroyed.] ] + [ + [n^m] + [The handler number `n` is about to create a new asynchronous operation with + completion handler number `m`. The `` contains source location + information to help identify where in the program the asynchronous operation + is being started.] + ] [ [n*m] [The handler number `n` created a new asynchronous operation with completion @@ -105,6 +113,53 @@ As shown above, Each handler is assigned a numeric identifier. Where the handler tracking output shows a handler number of 0, it means that the action was performed outside of any handler. +[heading Adding Location Information] + +[c++] +Programs may augment the handler tracking output's location information by +using the macro `BOOST_ASIO_HANDLER_LOCATION` in the source code. For example: + + #define HANDLER_LOCATION \ + BOOST_ASIO_HANDLER_LOCATION((__FILE__, __LINE__, __func__)) + + // ... + + void do_read() + { + HANDLER_LOCATION; + + auto self(shared_from_this()); + socket_.async_read_some(boost::asio::buffer(data_, max_length), + [this, self](boost::system::error_code ec, std::size_t length) + { + HANDLER_LOCATION; + + if (!ec) + { + do_write(length); + } + }); + } + +[teletype] +With the additional location information available, the handler tracking output +may include a call stack of source locations: + + @asio|1589423304.861944|>7|ec=system:0,bytes_transferred=5 + @asio|1589423304.861952|7^8|in 'async_write' (./../../../boost/asio/impl/write.hpp:330) + @asio|1589423304.861952|7^8|called from 'do_write' (handler_tracking/async_tcp_echo_server.cpp:62) + @asio|1589423304.861952|7^8|called from 'operator()' (handler_tracking/async_tcp_echo_server.cpp:51) + @asio|1589423304.861952|7*8|socket@0x7ff61c008230.async_send + @asio|1589423304.861975|.8|non_blocking_send,ec=system:0,bytes_transferred=5 + @asio|1589423304.861980|<7| + +Furthermore, if `std::source_location` or `std::experimental::source_location` +are available, the [link boost_asio.reference.use_awaitable_t `use_awaitable_t`] +token (when default-constructed or used as a default completion token) will +also cause handler tracking to output a source location for each newly created +asynchronous operation. A `use_awaitable_t` object may also be explicitly +constructed with location information. + [heading Visual Representations] The handler tracking output may be post-processed using the included @@ -137,6 +192,12 @@ preprocessor macros: [`BOOST_ASIO_HANDLER_TRACKING_INIT(args)`] [An expression that is used to initialise the tracking mechanism.] ] + [ + [`BOOST_ASIO_HANDLER_LOCATION(args)`] + [A variable declaration that is used to define a source code location. + `args` is a parenthesised function argument list containing the file + name, line number, and function name.] + ] [ [`BOOST_ASIO_HANDLER_CREATION(args)`] [An expression that is called on creation of an asynchronous operation. @@ -214,7 +275,7 @@ preprocessor macros: [heading See Also] -[link boost_asio.examples.cpp11_examples.handler_tracking Custom handler tracking -example]. +[link boost_asio.examples.cpp11_examples.handler_tracking Handler tracking +examples]. [endsect] diff --git a/doc/quickref.xml b/doc/quickref.xml index cf478be2..3228079a 100644 --- a/doc/quickref.xml +++ b/doc/quickref.xml @@ -9,6 +9,135 @@ --> + + + + + + + + + Properties + + + Execution + + + + + + + Customisation Points + + prefer + query + require + require_concept + + Traits + + can_prefer + can_query + can_require + can_require_concept + is_nothrow_prefer + is_nothrow_query + is_nothrow_require + is_nothrow_require_concept + prefer_result_type + query_result_type + require_result_type + require_concept_result_type + + + + Concepts + + Executor + + Customisation Points + + execution::execute + + Class Templates + + execution::any_executor + + Classes + + execution::bad_executor + execution::invocable_archetype + + Traits + + execution::is_executor + execution::can_execute + + + + Properties + + execution::allocator_t + execution::blocking_t + execution::blocking_t::possibly_t + execution::blocking_t::always_t + execution::blocking_t::never_t + execution::blocking_adaptation_t + execution::blocking_adaptation_t::disallowed_t + execution::blocking_adaptation_t::allowed_t + execution::bulk_guarantee_t + execution::bulk_guarantee_t::unsequenced_t + execution::bulk_guarantee_t::sequenced_t + execution::bulk_guarantee_t::parallel_t + execution::context_t + execution::context_as_t + execution::mapping_t + execution::mapping_t::thread_t + execution::mapping_t::new_thread_t + execution::mapping_t::other_t + execution::occupancy_t + execution::outstanding_work_t + execution::outstanding_work_t::untracked_t + execution::outstanding_work_t::tracked_t + execution::prefer_only + execution::relationship_t + execution::relationship_t::fork_t + execution::relationship_t::continuation_t + + + + Property Objects + + execution::allocator + execution::blocking + execution::blocking.possibly + execution::blocking.always + execution::blocking.never + execution::blocking_adaptation + execution::blocking_adaptation.disallowed + execution::blocking_adaptation.allowed + execution::bulk_guarantee + execution::bulk_guarantee.unsequenced + execution::bulk_guarantee.sequenced + execution::bulk_guarantee.parallel + execution::context + execution::context_as + execution::mapping + execution::mapping.thread + execution::mapping.new_thread + execution::mapping.other + execution::occupancy + execution::outstanding_work + execution::outstanding_work.untracked + execution::outstanding_work.tracked + execution::relationship + execution::relationship.fork + execution::relationship.continuation + + + + + @@ -26,6 +155,7 @@ Classes + any_io_executor bad_executor coroutine detached_t @@ -36,16 +166,18 @@ executor_arg_t invalid_service_owner io_context - io_context::executor_type + io_context::executor_type io_context::service io_context::strand io_context::work (deprecated) + multiple_exceptions service_already_exists + static_thread_pool system_context system_executor this_coro::executor_t thread_pool - thread_pool::executor_type + thread_pool::executor_type yield_context @@ -53,9 +185,9 @@ Free Functions add_service - asio_handler_allocate - asio_handler_deallocate - asio_handler_invoke + asio_handler_allocate (deprecated) + asio_handler_deallocate (deprecated) + asio_handler_invoke (deprecated) asio_handler_is_continuation async_compose async_initiate @@ -80,11 +212,14 @@ async_completion awaitable basic_io_object + basic_system_executor basic_yield_context executor_binder executor_work_guard + io_context::basic_executor_type redirect_error_t strand + thread_pool::basic_executor_type use_awaitable_t use_future_t diff --git a/doc/reference.dox b/doc/reference.dox index 6db85872..a77ccdf1 100644 --- a/doc/reference.dox +++ b/doc/reference.dox @@ -81,6 +81,7 @@ INPUT = ./../../../boost/asio.hpp \ ./../../../boost/asio/posix \ ./../../../boost/asio/ssl \ ./../../../boost/asio/windows \ + ./../../../boost/asio/execution \ ./noncopyable_dox.txt \ ./std_exception_dox.txt FILE_PATTERNS = @@ -221,7 +222,8 @@ PREDEFINED = GENERATING_DOCUMENTATION \ BOOST_ASIO_MUTABLE_BUFFER=mutable_buffer \ BOOST_ASIO_SYNC_OP_VOID=void \ BOOST_ASIO_STRING_VIEW_PARAM=string_view \ - BOOST_ASIO_UNUSED_VARIABLE= + BOOST_ASIO_UNUSED_VARIABLE= \ + BOOST_ASIO_UNSPECIFIED(e)=unspecified EXPAND_AS_DEFINED = SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- diff --git a/doc/reference.qbk b/doc/reference.qbk index 86c50785..12182f9f 100644 --- a/doc/reference.qbk +++ b/doc/reference.qbk @@ -64,13 +64,138 @@ +[section:any_io_executor any_io_executor] + +[indexterm1 boost_asio.indexterm.any_io_executor..any_io_executor] +Polymorphic executor type for use with I/O objects. + + + typedef execution::any_executor<...> any_io_executor; + + +[heading Member Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.execution__any_executor.any_executor [*any_executor]]] + [Default constructor. + [hr] + Copy constructor. + [hr] + Move constructor. + [hr] + Construct to point to the same target as another any_executor. + [hr] + Construct a polymorphic wrapper for the specified executor. ] + ] + + [ + [[link boost_asio.reference.execution__any_executor.context [*context]]] + [Obtain the underlying execution context. ] + ] + + [ + [[link boost_asio.reference.execution__any_executor.execute [*execute]]] + [Execute the function on the target executor. ] + ] + + [ + [[link boost_asio.reference.execution__any_executor.operator_bool [*operator bool]]] + [Determine whether the wrapper has a target executor. ] + ] + + [ + [[link boost_asio.reference.execution__any_executor.operator_eq_ [*operator=]]] + [Assignment operator. + [hr] + Move assignment operator. + [hr] + Assignment operator to create a polymorphic wrapper for the specified executor. ] + ] + + [ + [[link boost_asio.reference.execution__any_executor.prefer [*prefer]]] + [Obtain a polymorphic wrapper with the specified property. ] + ] + + [ + [[link boost_asio.reference.execution__any_executor.query [*query]]] + [Obtain the value associated with the specified property. ] + ] + + [ + [[link boost_asio.reference.execution__any_executor.require [*require]]] + [Obtain a polymorphic wrapper with the specified property. ] + ] + + [ + [[link boost_asio.reference.execution__any_executor.target [*target]]] + [Get a pointer to the target executor. ] + ] + + [ + [[link boost_asio.reference.execution__any_executor.target_type [*target_type]]] + [Get the type of the target executor. ] + ] + + [ + [[link boost_asio.reference.execution__any_executor._any_executor [*~any_executor]]] + [Destructor. ] + ] + +] + +[heading Related Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.execution__any_executor.operator_not__eq_ [*operator!=]]] + [Inequality operator. ] + ] + + [ + [[link boost_asio.reference.execution__any_executor.operator_eq__eq_ [*operator==]]] + [Equality operator. ] + ] + +] + + +The `any_io_executor` type is a polymorphic executor that supports the set of properties required by I/O objects. It is defined as the [link boost_asio.reference.execution__any_executor `execution::any_executor`] class template parameterised as follows: + + execution::any_executor< + execution::context_as_t, + execution::blocking_t::never_t, + execution::prefer_only, + execution::prefer_only, + execution::prefer_only, + execution::prefer_only, + execution::prefer_only + > + + + + +[heading Requirements] + +['Header: ][^boost/asio/any_io_executor.hpp] + +['Convenience header: ][^boost/asio.hpp] + + +[endsect] + + + [section:asio_handler_allocate asio_handler_allocate] [indexterm1 boost_asio.indexterm.asio_handler_allocate..asio_handler_allocate] -Default allocation function for handlers. +(Deprecated: Use the [link boost_asio.reference.associated_allocator `associated_allocator`] trait.) Default allocation function for handlers. - void * asio_handler_allocate( + asio_handler_allocate_is_deprecated asio_handler_allocate( std::size_t size, ... ); @@ -126,7 +251,7 @@ All temporary objects associated with a handler will be deallocated before the u Default deallocation function for handlers. - void asio_handler_deallocate( + asio_handler_deallocate_is_deprecated asio_handler_deallocate( void * pointer, std::size_t size, ... ); @@ -152,14 +277,14 @@ The default implementation of these allocation hooks uses `operator new` and `op [section:asio_handler_invoke asio_handler_invoke] [indexterm1 boost_asio.indexterm.asio_handler_invoke..asio_handler_invoke] -Default invoke function for handlers. +(Deprecated: Use the [link boost_asio.reference.associated_executor `associated_executor`] trait.) Default invoke function for handlers. Default handler invocation hook used for non-const function objects. template< typename Function> - void ``[link boost_asio.reference.asio_handler_invoke.overload1 asio_handler_invoke]``( + asio_handler_invoke_is_deprecated ``[link boost_asio.reference.asio_handler_invoke.overload1 asio_handler_invoke]``( Function & function, ... ); `` [''''»''' [link boost_asio.reference.asio_handler_invoke.overload1 more...]]`` @@ -168,7 +293,7 @@ Default handler invocation hook used for const function objects. template< typename Function> - void ``[link boost_asio.reference.asio_handler_invoke.overload2 asio_handler_invoke]``( + asio_handler_invoke_is_deprecated ``[link boost_asio.reference.asio_handler_invoke.overload2 asio_handler_invoke]``( const Function & function, ... ); `` [''''»''' [link boost_asio.reference.asio_handler_invoke.overload2 more...]]`` @@ -219,7 +344,7 @@ Default handler invocation hook used for non-const function objects. template< typename Function> - void asio_handler_invoke( + asio_handler_invoke_is_deprecated asio_handler_invoke( Function & function, ... ); @@ -237,7 +362,7 @@ Default handler invocation hook used for const function objects. template< typename Function> - void asio_handler_invoke( + asio_handler_invoke_is_deprecated asio_handler_invoke( const Function & function, ... ); @@ -5439,7 +5564,7 @@ The return type of a coroutine or asynchronous operation. template< typename T, - typename ``[link boost_asio.reference.Executor1 Executor]`` = executor> + typename ``[link boost_asio.reference.Executor1 Executor]`` = any_io_executor> class awaitable @@ -12431,7 +12556,7 @@ Provides waitable timer functionality. template< typename Time, typename ``[link boost_asio.reference.TimeTraits TimeTraits]`` = boost::asio::time_traits