This change fixes the scheduler and win_iocp_io_context destructors so
that they correctly stop the internal thread that was created in the
constructor. This fixes a deadlock that can occur when two threads
concurrently attempt to create the first I/O object associated with a
non-native I/O execution context.
This change enables move construction and assignment between different timer
types, provided the executor types are convertible. For example:
basic_waitable_timer<
clock_type,
traits_type,
io_context::executor_type
> timer1(my_io_context);
basic_waitable_timer<
clock_type,
traits_type,
executor // polymorphic wrapper
> timer2(std::move(timer1));
The handlertree.pl script filters handler tracking output to include
only those events in the tree that produced the nominated handlers. For
example, to filter the output to include only the events associated with
handlers 123, 456, and their predecessors:
cat output.txt | perl handlertree.pl 123 456
or:
perl handlertree.pl 123 456 < output.txt
This script may be combined with handerlive.pl and handlerviz.pl to
produce a graph of the "live" asynchronous operation chains. For
example:
cat output.txt | perl handlertree.pl `perl handlerlive.pl output.txt` | perl handlerviz.pl | dot -Tsvg > output.svg
The handlerlive.pl script processes handler tracking output to produce a
list of "live" handlers, namely those that are associated with pending
asynchronous operations, as well as handlers that are currently executing.
To use:
cat output.txt | perl handlerlive.pl
or:
perl handerlive.pl < output.txt
or:
perl handlerlive.pl output.txt
* Add nodes for pending handlers at bottom of graph, outlined in red.
* Display source location in a tooltip on the edge label (for SVG).
* Use invisible nodes to enforce order to keep related control flow vertical.
The ASIO_HANDLER_LOCATION((file_name, line, function_name)) macro may
be used to inform the handler tracking mechanism of a source location.
This macro declares an object that is placed on the stack.
When an asynchronous operation is launched with location information, it
outputs lines using the <action> 'n^m', prior to the 'n*m' line that
signifies the beginning of the asynchronous operation. For example:
@asio|1589423304.861944|>7|ec=system:0,bytes_transferred=5
@asio|1589423304.861952|7^8|in 'async_write' (./../../../include/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|
If std::source_location or std::experimental::source_location are
available, the 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.
On some versions of Windows, it seems that "self pipe trick" sockets may
be disconnected after a system sleep. To work around this, we recreate
the sockets following an error on read.