Adds asio library and Storage Module
This commit is contained in:
1 parent
79a6ee5779
commit
30439acd43
4869 files changed
+618801
-903
No files matched your search
@@ -0,0 +1,136 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title>Custom Memory Allocation</title>
|
||||
<link rel="stylesheet" href="../../../boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.75.2">
|
||||
<link rel="home" href="../../../index.html" title="Asio">
|
||||
<link rel="up" href="../core.html" title="Core Concepts and Functionality">
|
||||
<link rel="prev" href="line_based.html" title="Line-Based Operations">
|
||||
<link rel="next" href="handler_tracking.html" title="Handler Tracking">
|
||||
</head>
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
<table cellpadding="2" width="100%"><tr><td valign="top"><img alt="asio C++ library" width="250" height="60" src="../../../asio.png"></td></tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="line_based.html"><img src="../../../prev.png" alt="Prev"></a><a accesskey="u" href="../core.html"><img src="../../../up.png" alt="Up"></a><a accesskey="h" href="../../../index.html"><img src="../../../home.png" alt="Home"></a><a accesskey="n" href="handler_tracking.html"><img src="../../../next.png" alt="Next"></a>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="titlepage"><div><div><h4 class="title">
|
||||
<a name="asio.overview.core.allocation"></a><a class="link" href="allocation.html" title="Custom Memory Allocation">Custom Memory Allocation</a>
|
||||
</h4></div></div></div>
|
||||
<p>
|
||||
Many asynchronous operations need to allocate an object to store state
|
||||
associated with the operation. For example, a Win32 implementation needs
|
||||
<code class="computeroutput"><span class="identifier">OVERLAPPED</span></code>-derived objects
|
||||
to pass to Win32 API functions.
|
||||
</p>
|
||||
<p>
|
||||
Furthermore, programs typically contain easily identifiable chains of asynchronous
|
||||
operations. A half duplex protocol implementation (e.g. an HTTP server)
|
||||
would have a single chain of operations per client (receives followed by
|
||||
sends). A full duplex protocol implementation would have two chains executing
|
||||
in parallel. Programs should be able to leverage this knowledge to reuse
|
||||
memory for all asynchronous operations in a chain.
|
||||
</p>
|
||||
<p>
|
||||
Given a copy of a user-defined <code class="computeroutput"><span class="identifier">Handler</span></code>
|
||||
object <code class="computeroutput"><span class="identifier">h</span></code>, if the implementation
|
||||
needs to allocate memory associated with that handler it will obtain an
|
||||
allocator using the <code class="computeroutput"><span class="identifier">get_associated_allocator</span></code>
|
||||
function. For example:
|
||||
</p>
|
||||
<pre class="programlisting"><span class="identifier">asio</span><span class="special">::</span><span class="identifier">associated_allocator_t</span><span class="special"><</span><span class="identifier">Handler</span><span class="special">></span> <span class="identifier">a</span> <span class="special">=</span> <span class="identifier">asio</span><span class="special">::</span><span class="identifier">get_associated_allocator</span><span class="special">(</span><span class="identifier">h</span><span class="special">);</span>
|
||||
</pre>
|
||||
<p>
|
||||
The associated allocator must satisfy the standard Allocator requirements.
|
||||
</p>
|
||||
<p>
|
||||
By default, handlers use the standard allocator (which is implemented in
|
||||
terms of <code class="computeroutput"><span class="special">::</span><span class="keyword">operator</span>
|
||||
<span class="keyword">new</span><span class="special">()</span></code>
|
||||
and <code class="computeroutput"><span class="special">::</span><span class="keyword">operator</span>
|
||||
<span class="keyword">delete</span><span class="special">()</span></code>).
|
||||
The allocator may be customised for a particular handler type by specifying
|
||||
a nested type <code class="computeroutput"><span class="identifier">allocator_type</span></code>
|
||||
and member function <code class="computeroutput"><span class="identifier">get_allocator</span><span class="special">()</span></code>:
|
||||
</p>
|
||||
<pre class="programlisting"><span class="keyword">class</span> <span class="identifier">my_handler</span>
|
||||
<span class="special">{</span>
|
||||
<span class="keyword">public</span><span class="special">:</span>
|
||||
<span class="comment">// Custom implementation of Allocator type requirements.</span>
|
||||
<span class="keyword">typedef</span> <span class="identifier">my_allocator</span> <span class="identifier">allocator_type</span><span class="special">;</span>
|
||||
|
||||
<span class="comment">// Return a custom allocator implementation.</span>
|
||||
<span class="identifier">allocator_type</span> <span class="identifier">get_allocator</span><span class="special">()</span> <span class="keyword">const</span> <span class="keyword">noexcept</span>
|
||||
<span class="special">{</span>
|
||||
<span class="keyword">return</span> <span class="identifier">my_allocator</span><span class="special">();</span>
|
||||
<span class="special">}</span>
|
||||
|
||||
<span class="keyword">void</span> <span class="keyword">operator</span><span class="special">()()</span> <span class="special">{</span> <span class="special">...</span> <span class="special">}</span>
|
||||
<span class="special">};</span>
|
||||
</pre>
|
||||
<p>
|
||||
In more complex cases, the <code class="computeroutput"><span class="identifier">associated_allocator</span></code>
|
||||
template may be partially specialised directly:
|
||||
</p>
|
||||
<pre class="programlisting"><span class="keyword">namespace</span> <span class="identifier">asio</span> <span class="special">{</span>
|
||||
|
||||
<span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">Allocator</span><span class="special">></span>
|
||||
<span class="keyword">struct</span> <span class="identifier">associated_allocator</span><span class="special"><</span><span class="identifier">my_handler</span><span class="special">,</span> <span class="identifier">Allocator</span><span class="special">></span>
|
||||
<span class="special">{</span>
|
||||
<span class="comment">// Custom implementation of Allocator type requirements.</span>
|
||||
<span class="keyword">typedef</span> <span class="identifier">my_allocator</span> <span class="identifier">type</span><span class="special">;</span>
|
||||
|
||||
<span class="comment">// Return a custom allocator implementation.</span>
|
||||
<span class="keyword">static</span> <span class="identifier">type</span> <span class="identifier">get</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">my_handler</span><span class="special">&,</span>
|
||||
<span class="keyword">const</span> <span class="identifier">Allocator</span><span class="special">&</span> <span class="identifier">a</span> <span class="special">=</span> <span class="identifier">Allocator</span><span class="special">())</span> <span class="keyword">noexcept</span>
|
||||
<span class="special">{</span>
|
||||
<span class="keyword">return</span> <span class="identifier">my_allocator</span><span class="special">();</span>
|
||||
<span class="special">}</span>
|
||||
<span class="special">};</span>
|
||||
|
||||
<span class="special">}</span> <span class="comment">// namespace asio</span>
|
||||
</pre>
|
||||
<p>
|
||||
The implementation guarantees that the deallocation will occur before the
|
||||
associated handler is invoked, which means the memory is ready to be reused
|
||||
for any new asynchronous operations started by the handler.
|
||||
</p>
|
||||
<p>
|
||||
The custom memory allocation functions may be called from any user-created
|
||||
thread that is calling a library function. The implementation guarantees
|
||||
that, for the asynchronous operations included the library, the implementation
|
||||
will not make concurrent calls to the memory allocation functions for that
|
||||
handler. The implementation will insert appropriate memory barriers to
|
||||
ensure correct memory visibility should allocation functions need to be
|
||||
called from different threads.
|
||||
</p>
|
||||
<h6>
|
||||
<a name="asio.overview.core.allocation.h0"></a>
|
||||
<span><a name="asio.overview.core.allocation.see_also"></a></span><a class="link" href="allocation.html#asio.overview.core.allocation.see_also">See
|
||||
Also</a>
|
||||
</h6>
|
||||
<p>
|
||||
<a class="link" href="../../reference/associated_allocator.html" title="associated_allocator">associated_allocator</a>,
|
||||
<a class="link" href="../../reference/get_associated_allocator.html" title="get_associated_allocator">get_associated_allocator</a>,
|
||||
<a class="link" href="../../examples/cpp03_examples.html#asio.examples.cpp03_examples.allocation">custom memory allocation
|
||||
example (C++03)</a>, <a class="link" href="../../examples/cpp11_examples.html#asio.examples.cpp11_examples.allocation">custom
|
||||
memory allocation example (C++11)</a>.
|
||||
</p>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"></td>
|
||||
<td align="right"><div class="copyright-footer">Copyright © 2003-2020 Christopher M.
|
||||
Kohlhoff<p>
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
|
||||
</p>
|
||||
</div></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="line_based.html"><img src="../../../prev.png" alt="Prev"></a><a accesskey="u" href="../core.html"><img src="../../../up.png" alt="Up"></a><a accesskey="h" href="../../../index.html"><img src="../../../home.png" alt="Home"></a><a accesskey="n" href="handler_tracking.html"><img src="../../../next.png" alt="Next"></a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,280 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title>The Proactor Design Pattern: Concurrency Without Threads</title>
|
||||
<link rel="stylesheet" href="../../../boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.75.2">
|
||||
<link rel="home" href="../../../index.html" title="Asio">
|
||||
<link rel="up" href="../core.html" title="Core Concepts and Functionality">
|
||||
<link rel="prev" href="basics.html" title="Basic Asio Anatomy">
|
||||
<link rel="next" href="threads.html" title="Threads and Asio">
|
||||
</head>
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
<table cellpadding="2" width="100%"><tr><td valign="top"><img alt="asio C++ library" width="250" height="60" src="../../../asio.png"></td></tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="basics.html"><img src="../../../prev.png" alt="Prev"></a><a accesskey="u" href="../core.html"><img src="../../../up.png" alt="Up"></a><a accesskey="h" href="../../../index.html"><img src="../../../home.png" alt="Home"></a><a accesskey="n" href="threads.html"><img src="../../../next.png" alt="Next"></a>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="titlepage"><div><div><h4 class="title">
|
||||
<a name="asio.overview.core.async"></a><a class="link" href="async.html" title="The Proactor Design Pattern: Concurrency Without Threads">The Proactor Design Pattern:
|
||||
Concurrency Without Threads</a>
|
||||
</h4></div></div></div>
|
||||
<p>
|
||||
The Asio library offers side-by-side support for synchronous and asynchronous
|
||||
operations. The asynchronous support is based on the Proactor design pattern
|
||||
<a class="link" href="async.html#asio.overview.core.async.references">[POSA2]</a>. The
|
||||
advantages and disadvantages of this approach, when compared to a synchronous-only
|
||||
or Reactor approach, are outlined below.
|
||||
</p>
|
||||
<h6>
|
||||
<a name="asio.overview.core.async.h0"></a>
|
||||
<span><a name="asio.overview.core.async.proactor_and_asio"></a></span><a class="link" href="async.html#asio.overview.core.async.proactor_and_asio">Proactor
|
||||
and Asio</a>
|
||||
</h6>
|
||||
<p>
|
||||
Let us examine how the Proactor design pattern is implemented in Asio,
|
||||
without reference to platform-specific details.
|
||||
</p>
|
||||
<p>
|
||||
<span class="inlinemediaobject"><img src="../../../proactor.png" alt="proactor"></span>
|
||||
</p>
|
||||
<p>
|
||||
<span class="bold"><strong>Proactor design pattern (adapted from [POSA2])</strong></span>
|
||||
</p>
|
||||
<p>
|
||||
— Asynchronous Operation
|
||||
</p>
|
||||
<div class="blockquote"><blockquote class="blockquote"><p>
|
||||
Defines an operation that is executed asynchronously, such as an asynchronous
|
||||
read or write on a socket.
|
||||
</p></blockquote></div>
|
||||
<p>
|
||||
— Asynchronous Operation Processor
|
||||
</p>
|
||||
<div class="blockquote"><blockquote class="blockquote"><p>
|
||||
Executes asynchronous operations and queues events on a completion event
|
||||
queue when operations complete. From a high-level point of view, internal
|
||||
services like <code class="computeroutput"><span class="identifier">reactive_socket_service</span></code>
|
||||
are asynchronous operation processors.
|
||||
</p></blockquote></div>
|
||||
<p>
|
||||
— Completion Event Queue
|
||||
</p>
|
||||
<div class="blockquote"><blockquote class="blockquote"><p>
|
||||
Buffers completion events until they are dequeued by an asynchronous
|
||||
event demultiplexer.
|
||||
</p></blockquote></div>
|
||||
<p>
|
||||
— Completion Handler
|
||||
</p>
|
||||
<div class="blockquote"><blockquote class="blockquote"><p>
|
||||
Processes the result of an asynchronous operation. These are function
|
||||
objects, often created using <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">bind</span></code>.
|
||||
</p></blockquote></div>
|
||||
<p>
|
||||
— Asynchronous Event Demultiplexer
|
||||
</p>
|
||||
<div class="blockquote"><blockquote class="blockquote"><p>
|
||||
Blocks waiting for events to occur on the completion event queue, and
|
||||
returns a completed event to its caller.
|
||||
</p></blockquote></div>
|
||||
<p>
|
||||
— Proactor
|
||||
</p>
|
||||
<div class="blockquote"><blockquote class="blockquote"><p>
|
||||
Calls the asynchronous event demultiplexer to dequeue events, and dispatches
|
||||
the completion handler (i.e. invokes the function object) associated
|
||||
with the event. This abstraction is represented by the <code class="computeroutput"><span class="identifier">io_context</span></code> class.
|
||||
</p></blockquote></div>
|
||||
<p>
|
||||
— Initiator
|
||||
</p>
|
||||
<div class="blockquote"><blockquote class="blockquote"><p>
|
||||
Application-specific code that starts asynchronous operations. The initiator
|
||||
interacts with an asynchronous operation processor via a high-level interface
|
||||
such as <code class="computeroutput"><span class="identifier">basic_stream_socket</span></code>,
|
||||
which in turn delegates to a service like <code class="computeroutput"><span class="identifier">reactive_socket_service</span></code>.
|
||||
</p></blockquote></div>
|
||||
<h6>
|
||||
<a name="asio.overview.core.async.h1"></a>
|
||||
<span><a name="asio.overview.core.async.implementation_using_reactor"></a></span><a class="link" href="async.html#asio.overview.core.async.implementation_using_reactor">Implementation
|
||||
Using Reactor</a>
|
||||
</h6>
|
||||
<p>
|
||||
On many platforms, Asio implements the Proactor design pattern in terms
|
||||
of a Reactor, such as <code class="computeroutput"><span class="identifier">select</span></code>,
|
||||
<code class="computeroutput"><span class="identifier">epoll</span></code> or <code class="computeroutput"><span class="identifier">kqueue</span></code>. This implementation approach
|
||||
corresponds to the Proactor design pattern as follows:
|
||||
</p>
|
||||
<p>
|
||||
— Asynchronous Operation Processor
|
||||
</p>
|
||||
<div class="blockquote"><blockquote class="blockquote"><p>
|
||||
A reactor implemented using <code class="computeroutput"><span class="identifier">select</span></code>,
|
||||
<code class="computeroutput"><span class="identifier">epoll</span></code> or <code class="computeroutput"><span class="identifier">kqueue</span></code>. When the reactor indicates
|
||||
that the resource is ready to perform the operation, the processor executes
|
||||
the asynchronous operation and enqueues the associated completion handler
|
||||
on the completion event queue.
|
||||
</p></blockquote></div>
|
||||
<p>
|
||||
— Completion Event Queue
|
||||
</p>
|
||||
<div class="blockquote"><blockquote class="blockquote"><p>
|
||||
A linked list of completion handlers (i.e. function objects).
|
||||
</p></blockquote></div>
|
||||
<p>
|
||||
— Asynchronous Event Demultiplexer
|
||||
</p>
|
||||
<div class="blockquote"><blockquote class="blockquote"><p>
|
||||
This is implemented by waiting on an event or condition variable until
|
||||
a completion handler is available in the completion event queue.
|
||||
</p></blockquote></div>
|
||||
<h6>
|
||||
<a name="asio.overview.core.async.h2"></a>
|
||||
<span><a name="asio.overview.core.async.implementation_using_windows_overlapped_i_o"></a></span><a class="link" href="async.html#asio.overview.core.async.implementation_using_windows_overlapped_i_o">Implementation
|
||||
Using Windows Overlapped I/O</a>
|
||||
</h6>
|
||||
<p>
|
||||
On Windows NT, 2000 and XP, Asio takes advantage of overlapped I/O to provide
|
||||
an efficient implementation of the Proactor design pattern. This implementation
|
||||
approach corresponds to the Proactor design pattern as follows:
|
||||
</p>
|
||||
<p>
|
||||
— Asynchronous Operation Processor
|
||||
</p>
|
||||
<div class="blockquote"><blockquote class="blockquote"><p>
|
||||
This is implemented by the operating system. Operations are initiated
|
||||
by calling an overlapped function such as <code class="computeroutput"><span class="identifier">AcceptEx</span></code>.
|
||||
</p></blockquote></div>
|
||||
<p>
|
||||
— Completion Event Queue
|
||||
</p>
|
||||
<div class="blockquote"><blockquote class="blockquote"><p>
|
||||
This is implemented by the operating system, and is associated with an
|
||||
I/O completion port. There is one I/O completion port for each <code class="computeroutput"><span class="identifier">io_context</span></code> instance.
|
||||
</p></blockquote></div>
|
||||
<p>
|
||||
— Asynchronous Event Demultiplexer
|
||||
</p>
|
||||
<div class="blockquote"><blockquote class="blockquote"><p>
|
||||
Called by Asio to dequeue events and their associated completion handlers.
|
||||
</p></blockquote></div>
|
||||
<h6>
|
||||
<a name="asio.overview.core.async.h3"></a>
|
||||
<span><a name="asio.overview.core.async.advantages"></a></span><a class="link" href="async.html#asio.overview.core.async.advantages">Advantages</a>
|
||||
</h6>
|
||||
<p>
|
||||
— Portability.
|
||||
</p>
|
||||
<div class="blockquote"><blockquote class="blockquote"><p>
|
||||
Many operating systems offer a native asynchronous I/O API (such as overlapped
|
||||
I/O on <span class="emphasis"><em>Windows</em></span>) as the preferred option for developing
|
||||
high performance network applications. The library may be implemented
|
||||
in terms of native asynchronous I/O. However, if native support is not
|
||||
available, the library may also be implemented using synchronous event
|
||||
demultiplexors that typify the Reactor pattern, such as <span class="emphasis"><em>POSIX</em></span>
|
||||
<code class="computeroutput"><span class="identifier">select</span><span class="special">()</span></code>.
|
||||
</p></blockquote></div>
|
||||
<p>
|
||||
— Decoupling threading from concurrency.
|
||||
</p>
|
||||
<div class="blockquote"><blockquote class="blockquote"><p>
|
||||
Long-duration operations are performed asynchronously by the implementation
|
||||
on behalf of the application. Consequently applications do not need to
|
||||
spawn many threads in order to increase concurrency.
|
||||
</p></blockquote></div>
|
||||
<p>
|
||||
— Performance and scalability.
|
||||
</p>
|
||||
<div class="blockquote"><blockquote class="blockquote"><p>
|
||||
Implementation strategies such as thread-per-connection (which a synchronous-only
|
||||
approach would require) can degrade system performance, due to increased
|
||||
context switching, synchronisation and data movement among CPUs. With
|
||||
asynchronous operations it is possible to avoid the cost of context switching
|
||||
by minimising the number of operating system threads — typically a limited
|
||||
resource — and only activating the logical threads of control that have
|
||||
events to process.
|
||||
</p></blockquote></div>
|
||||
<p>
|
||||
— Simplified application synchronisation.
|
||||
</p>
|
||||
<div class="blockquote"><blockquote class="blockquote"><p>
|
||||
Asynchronous operation completion handlers can be written as though they
|
||||
exist in a single-threaded environment, and so application logic can
|
||||
be developed with little or no concern for synchronisation issues.
|
||||
</p></blockquote></div>
|
||||
<p>
|
||||
— Function composition.
|
||||
</p>
|
||||
<div class="blockquote"><blockquote class="blockquote"><p>
|
||||
Function composition refers to the implementation of functions to provide
|
||||
a higher-level operation, such as sending a message in a particular format.
|
||||
Each function is implemented in terms of multiple calls to lower-level
|
||||
read or write operations.
|
||||
</p></blockquote></div>
|
||||
<div class="blockquote"><blockquote class="blockquote"><p>
|
||||
For example, consider a protocol where each message consists of a fixed-length
|
||||
header followed by a variable length body, where the length of the body
|
||||
is specified in the header. A hypothetical read_message operation could
|
||||
be implemented using two lower-level reads, the first to receive the
|
||||
header and, once the length is known, the second to receive the body.
|
||||
</p></blockquote></div>
|
||||
<div class="blockquote"><blockquote class="blockquote"><p>
|
||||
To compose functions in an asynchronous model, asynchronous operations
|
||||
can be chained together. That is, a completion handler for one operation
|
||||
can initiate the next. Starting the first call in the chain can be encapsulated
|
||||
so that the caller need not be aware that the higher-level operation
|
||||
is implemented as a chain of asynchronous operations.
|
||||
</p></blockquote></div>
|
||||
<div class="blockquote"><blockquote class="blockquote"><p>
|
||||
The ability to compose new operations in this way simplifies the development
|
||||
of higher levels of abstraction above a networking library, such as functions
|
||||
to support a specific protocol.
|
||||
</p></blockquote></div>
|
||||
<h6>
|
||||
<a name="asio.overview.core.async.h4"></a>
|
||||
<span><a name="asio.overview.core.async.disadvantages"></a></span><a class="link" href="async.html#asio.overview.core.async.disadvantages">Disadvantages</a>
|
||||
</h6>
|
||||
<p>
|
||||
— Program complexity.
|
||||
</p>
|
||||
<div class="blockquote"><blockquote class="blockquote"><p>
|
||||
It is more difficult to develop applications using asynchronous mechanisms
|
||||
due to the separation in time and space between operation initiation
|
||||
and completion. Applications may also be harder to debug due to the inverted
|
||||
flow of control.
|
||||
</p></blockquote></div>
|
||||
<p>
|
||||
— Memory usage.
|
||||
</p>
|
||||
<div class="blockquote"><blockquote class="blockquote"><p>
|
||||
Buffer space must be committed for the duration of a read or write operation,
|
||||
which may continue indefinitely, and a separate buffer is required for
|
||||
each concurrent operation. The Reactor pattern, on the other hand, does
|
||||
not require buffer space until a socket is ready for reading or writing.
|
||||
</p></blockquote></div>
|
||||
<h6>
|
||||
<a name="asio.overview.core.async.h5"></a>
|
||||
<span><a name="asio.overview.core.async.references"></a></span><a class="link" href="async.html#asio.overview.core.async.references">References</a>
|
||||
</h6>
|
||||
<p>
|
||||
[POSA2] D. Schmidt et al, <span class="emphasis"><em>Pattern Oriented Software Architecture,
|
||||
Volume 2</em></span>. Wiley, 2000.
|
||||
</p>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"></td>
|
||||
<td align="right"><div class="copyright-footer">Copyright © 2003-2020 Christopher M.
|
||||
Kohlhoff<p>
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
|
||||
</p>
|
||||
</div></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="basics.html"><img src="../../../prev.png" alt="Prev"></a><a accesskey="u" href="../core.html"><img src="../../../up.png" alt="Up"></a><a accesskey="h" href="../../../index.html"><img src="../../../home.png" alt="Home"></a><a accesskey="n" href="threads.html"><img src="../../../next.png" alt="Next"></a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,172 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title>Basic Asio Anatomy</title>
|
||||
<link rel="stylesheet" href="../../../boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.75.2">
|
||||
<link rel="home" href="../../../index.html" title="Asio">
|
||||
<link rel="up" href="../core.html" title="Core Concepts and Functionality">
|
||||
<link rel="prev" href="../core.html" title="Core Concepts and Functionality">
|
||||
<link rel="next" href="async.html" title="The Proactor Design Pattern: Concurrency Without Threads">
|
||||
</head>
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
<table cellpadding="2" width="100%"><tr><td valign="top"><img alt="asio C++ library" width="250" height="60" src="../../../asio.png"></td></tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="../core.html"><img src="../../../prev.png" alt="Prev"></a><a accesskey="u" href="../core.html"><img src="../../../up.png" alt="Up"></a><a accesskey="h" href="../../../index.html"><img src="../../../home.png" alt="Home"></a><a accesskey="n" href="async.html"><img src="../../../next.png" alt="Next"></a>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="titlepage"><div><div><h4 class="title">
|
||||
<a name="asio.overview.core.basics"></a><a class="link" href="basics.html" title="Basic Asio Anatomy">Basic Asio Anatomy</a>
|
||||
</h4></div></div></div>
|
||||
<p>
|
||||
Asio may be used to perform both synchronous and asynchronous operations
|
||||
on I/O objects such as sockets. Before using Asio it may be useful to get
|
||||
a conceptual picture of the various parts of Asio, your program, and how
|
||||
they work together.
|
||||
</p>
|
||||
<p>
|
||||
As an introductory example, let's consider what happens when you perform
|
||||
a connect operation on a socket. We shall start by examining synchronous
|
||||
operations.
|
||||
</p>
|
||||
<p>
|
||||
<span class="inlinemediaobject"><img src="../../../sync_op.png" alt="sync_op"></span>
|
||||
</p>
|
||||
<p>
|
||||
<span class="bold"><strong>Your program</strong></span> will have at least one <span class="bold"><strong>I/O execution context</strong></span>, such as an <code class="computeroutput"><span class="identifier">asio</span><span class="special">::</span><span class="identifier">io_context</span></code> object, <code class="computeroutput"><span class="identifier">asio</span><span class="special">::</span><span class="identifier">thread_pool</span></code>
|
||||
object, or <code class="computeroutput"><span class="identifier">asio</span><span class="special">::</span><span class="identifier">system_context</span></code>. This <span class="bold"><strong>I/O
|
||||
execution context</strong></span> represents <span class="bold"><strong>your program</strong></span>'s
|
||||
link to the <span class="bold"><strong>operating system</strong></span>'s I/O services.
|
||||
</p>
|
||||
<pre class="programlisting"><span class="identifier">asio</span><span class="special">::</span><span class="identifier">io_context</span> <span class="identifier">io_context</span><span class="special">;</span>
|
||||
</pre>
|
||||
<p>
|
||||
To perform I/O operations <span class="bold"><strong>your program</strong></span>
|
||||
will need an <span class="bold"><strong>I/O object</strong></span> such as a TCP
|
||||
socket:
|
||||
</p>
|
||||
<pre class="programlisting"><span class="identifier">asio</span><span class="special">::</span><span class="identifier">ip</span><span class="special">::</span><span class="identifier">tcp</span><span class="special">::</span><span class="identifier">socket</span> <span class="identifier">socket</span><span class="special">(</span><span class="identifier">io_context</span><span class="special">);</span>
|
||||
</pre>
|
||||
<p>
|
||||
When a synchronous connect operation is performed, the following sequence
|
||||
of events occurs:
|
||||
</p>
|
||||
<p>
|
||||
1. <span class="bold"><strong>Your program</strong></span> initiates the connect
|
||||
operation by calling the <span class="bold"><strong>I/O object</strong></span>:
|
||||
</p>
|
||||
<pre class="programlisting"><span class="identifier">socket</span><span class="special">.</span><span class="identifier">connect</span><span class="special">(</span><span class="identifier">server_endpoint</span><span class="special">);</span>
|
||||
</pre>
|
||||
<p>
|
||||
2. The <span class="bold"><strong>I/O object</strong></span> forwards the request
|
||||
to the <span class="bold"><strong>I/O execution context</strong></span>.
|
||||
</p>
|
||||
<p>
|
||||
3. The <span class="bold"><strong>I/O execution context</strong></span> calls on
|
||||
the <span class="bold"><strong>operating system</strong></span> to perform the connect
|
||||
operation.
|
||||
</p>
|
||||
<p>
|
||||
4. The <span class="bold"><strong>operating system</strong></span> returns the result
|
||||
of the operation to the <span class="bold"><strong>I/O execution context</strong></span>.
|
||||
</p>
|
||||
<p>
|
||||
5. The <span class="bold"><strong>I/O execution context</strong></span> translates
|
||||
any error resulting from the operation into an object of type <code class="computeroutput"><span class="identifier">asio</span><span class="special">::</span><span class="identifier">error_code</span></code>. An <code class="computeroutput"><span class="identifier">error_code</span></code>
|
||||
may be compared with specific values, or tested as a boolean (where a
|
||||
<code class="computeroutput"><span class="keyword">false</span></code> result means that no
|
||||
error occurred). The result is then forwarded back up to the <span class="bold"><strong>I/O object</strong></span>.
|
||||
</p>
|
||||
<p>
|
||||
6. The <span class="bold"><strong>I/O object</strong></span> throws an exception
|
||||
of type <code class="computeroutput"><span class="identifier">asio</span><span class="special">::</span><span class="identifier">system_error</span></code> if the operation failed.
|
||||
If the code to initiate the operation had instead been written as:
|
||||
</p>
|
||||
<pre class="programlisting"><span class="identifier">asio</span><span class="special">::</span><span class="identifier">error_code</span> <span class="identifier">ec</span><span class="special">;</span>
|
||||
<span class="identifier">socket</span><span class="special">.</span><span class="identifier">connect</span><span class="special">(</span><span class="identifier">server_endpoint</span><span class="special">,</span> <span class="identifier">ec</span><span class="special">);</span>
|
||||
</pre>
|
||||
<p>
|
||||
then the <code class="computeroutput"><span class="identifier">error_code</span></code> variable
|
||||
<code class="computeroutput"><span class="identifier">ec</span></code> would be set to the
|
||||
result of the operation, and no exception would be thrown.
|
||||
</p>
|
||||
<p>
|
||||
When an asynchronous operation is used, a different sequence of events
|
||||
occurs.
|
||||
</p>
|
||||
<p>
|
||||
<span class="inlinemediaobject"><img src="../../../async_op1.png" alt="async_op1"></span>
|
||||
</p>
|
||||
<p>
|
||||
1. <span class="bold"><strong>Your program</strong></span> initiates the connect
|
||||
operation by calling the <span class="bold"><strong>I/O object</strong></span>:
|
||||
</p>
|
||||
<pre class="programlisting"><span class="identifier">socket</span><span class="special">.</span><span class="identifier">async_connect</span><span class="special">(</span><span class="identifier">server_endpoint</span><span class="special">,</span> <span class="identifier">your_completion_handler</span><span class="special">);</span>
|
||||
</pre>
|
||||
<p>
|
||||
where <code class="computeroutput"><span class="identifier">your_completion_handler</span></code>
|
||||
is a function or function object with the signature:
|
||||
</p>
|
||||
<pre class="programlisting"><span class="keyword">void</span> <span class="identifier">your_completion_handler</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">asio</span><span class="special">::</span><span class="identifier">error_code</span><span class="special">&</span> <span class="identifier">ec</span><span class="special">);</span>
|
||||
</pre>
|
||||
<p>
|
||||
The exact signature required depends on the asynchronous operation being
|
||||
performed. The reference documentation indicates the appropriate form for
|
||||
each operation.
|
||||
</p>
|
||||
<p>
|
||||
2. The <span class="bold"><strong>I/O object</strong></span> forwards the request
|
||||
to the <span class="bold"><strong>I/O execution context</strong></span>.
|
||||
</p>
|
||||
<p>
|
||||
3. The <span class="bold"><strong>I/O execution context</strong></span> signals to
|
||||
the <span class="bold"><strong>operating system</strong></span> that it should start
|
||||
an asynchronous connect.
|
||||
</p>
|
||||
<p>
|
||||
Time passes. (In the synchronous case this wait would have been contained
|
||||
entirely within the duration of the connect operation.)
|
||||
</p>
|
||||
<p>
|
||||
<span class="inlinemediaobject"><img src="../../../async_op2.png" alt="async_op2"></span>
|
||||
</p>
|
||||
<p>
|
||||
4. The <span class="bold"><strong>operating system</strong></span> indicates that
|
||||
the connect operation has completed by placing the result on a queue, ready
|
||||
to be picked up by the <span class="bold"><strong>I/O execution context</strong></span>.
|
||||
</p>
|
||||
<p>
|
||||
5. When using an <code class="computeroutput"><span class="identifier">io_context</span></code>
|
||||
as the <span class="bold"><strong>I/O execution context</strong></span>, <span class="bold"><strong>your program</strong></span> must make a call to <code class="computeroutput"><span class="identifier">io_context</span><span class="special">::</span><span class="identifier">run</span><span class="special">()</span></code> (or to one of the similar <code class="computeroutput"><span class="identifier">io_context</span></code> member functions) in order
|
||||
for the result to be retrieved. A call to <code class="computeroutput"><span class="identifier">io_context</span><span class="special">::</span><span class="identifier">run</span><span class="special">()</span></code> blocks while there are unfinished asynchronous
|
||||
operations, so you would typically call it as soon as you have started
|
||||
your first asynchronous operation.
|
||||
</p>
|
||||
<p>
|
||||
6. While inside the call to <code class="computeroutput"><span class="identifier">io_context</span><span class="special">::</span><span class="identifier">run</span><span class="special">()</span></code>, the <span class="bold"><strong>I/O execution
|
||||
context</strong></span> dequeues the result of the operation, translates it
|
||||
into an <code class="computeroutput"><span class="identifier">error_code</span></code>, and
|
||||
then passes it to <span class="bold"><strong>your completion handler</strong></span>.
|
||||
</p>
|
||||
<p>
|
||||
This is a simplified picture of how Asio operates. You will want to delve
|
||||
further into the documentation if your needs are more advanced, such as
|
||||
extending Asio to perform other types of asynchronous operations.
|
||||
</p>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"></td>
|
||||
<td align="right"><div class="copyright-footer">Copyright © 2003-2020 Christopher M.
|
||||
Kohlhoff<p>
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
|
||||
</p>
|
||||
</div></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="../core.html"><img src="../../../prev.png" alt="Prev"></a><a accesskey="u" href="../core.html"><img src="../../../up.png" alt="Up"></a><a accesskey="h" href="../../../index.html"><img src="../../../home.png" alt="Home"></a><a accesskey="n" href="async.html"><img src="../../../next.png" alt="Next"></a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,235 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title>Buffers</title>
|
||||
<link rel="stylesheet" href="../../../boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.75.2">
|
||||
<link rel="home" href="../../../index.html" title="Asio">
|
||||
<link rel="up" href="../core.html" title="Core Concepts and Functionality">
|
||||
<link rel="prev" href="strands.html" title="Strands: Use Threads Without Explicit Locking">
|
||||
<link rel="next" href="streams.html" title="Streams, Short Reads and Short Writes">
|
||||
</head>
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
<table cellpadding="2" width="100%"><tr><td valign="top"><img alt="asio C++ library" width="250" height="60" src="../../../asio.png"></td></tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="strands.html"><img src="../../../prev.png" alt="Prev"></a><a accesskey="u" href="../core.html"><img src="../../../up.png" alt="Up"></a><a accesskey="h" href="../../../index.html"><img src="../../../home.png" alt="Home"></a><a accesskey="n" href="streams.html"><img src="../../../next.png" alt="Next"></a>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="titlepage"><div><div><h4 class="title">
|
||||
<a name="asio.overview.core.buffers"></a><a class="link" href="buffers.html" title="Buffers">Buffers</a>
|
||||
</h4></div></div></div>
|
||||
<p>
|
||||
Fundamentally, I/O involves the transfer of data to and from contiguous
|
||||
regions of memory, called buffers. These buffers can be simply expressed
|
||||
as a tuple consisting of a pointer and a size in bytes. However, to allow
|
||||
the development of efficient network applications, Asio includes support
|
||||
for scatter-gather operations. These operations involve one or more buffers:
|
||||
</p>
|
||||
<div class="itemizedlist"><ul class="itemizedlist" type="disc">
|
||||
<li class="listitem">
|
||||
A scatter-read receives data into multiple buffers.
|
||||
</li>
|
||||
<li class="listitem">
|
||||
A gather-write transmits multiple buffers.
|
||||
</li>
|
||||
</ul></div>
|
||||
<p>
|
||||
Therefore we require an abstraction to represent a collection of buffers.
|
||||
The approach used in Asio is to define a type (actually two types) to represent
|
||||
a single buffer. These can be stored in a container, which may be passed
|
||||
to the scatter-gather operations.
|
||||
</p>
|
||||
<p>
|
||||
In addition to specifying buffers as a pointer and size in bytes, Asio
|
||||
makes a distinction between modifiable memory (called mutable) and non-modifiable
|
||||
memory (where the latter is created from the storage for a const-qualified
|
||||
variable). These two types could therefore be defined as follows:
|
||||
</p>
|
||||
<pre class="programlisting"><span class="keyword">typedef</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">pair</span><span class="special"><</span><span class="keyword">void</span><span class="special">*,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span><span class="special">></span> <span class="identifier">mutable_buffer</span><span class="special">;</span>
|
||||
<span class="keyword">typedef</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">pair</span><span class="special"><</span><span class="keyword">const</span> <span class="keyword">void</span><span class="special">*,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span><span class="special">></span> <span class="identifier">const_buffer</span><span class="special">;</span>
|
||||
</pre>
|
||||
<p>
|
||||
Here, a mutable_buffer would be convertible to a const_buffer, but conversion
|
||||
in the opposite direction is not valid.
|
||||
</p>
|
||||
<p>
|
||||
However, Asio does not use the above definitions as-is, but instead defines
|
||||
two classes: <code class="computeroutput"><span class="identifier">mutable_buffer</span></code>
|
||||
and <code class="computeroutput"><span class="identifier">const_buffer</span></code>. The goal
|
||||
of these is to provide an opaque representation of contiguous memory, where:
|
||||
</p>
|
||||
<div class="itemizedlist"><ul class="itemizedlist" type="disc">
|
||||
<li class="listitem">
|
||||
Types behave as std::pair would in conversions. That is, a <code class="computeroutput"><span class="identifier">mutable_buffer</span></code> is convertible to
|
||||
a <code class="computeroutput"><span class="identifier">const_buffer</span></code>, but
|
||||
the opposite conversion is disallowed.
|
||||
</li>
|
||||
<li class="listitem">
|
||||
There is protection against buffer overruns. Given a buffer instance,
|
||||
a user can only create another buffer representing the same range of
|
||||
memory or a sub-range of it. To provide further safety, the library
|
||||
also includes mechanisms for automatically determining the size of
|
||||
a buffer from an array, <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">array</span></code>
|
||||
or <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span></code> of POD elements, or from a
|
||||
<code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code>.
|
||||
</li>
|
||||
<li class="listitem">
|
||||
The underlying memory is explicitly accessed using the <code class="computeroutput"><span class="identifier">data</span><span class="special">()</span></code>
|
||||
member function. In general an application should never need to do
|
||||
this, but it is required by the library implementation to pass the
|
||||
raw memory to the underlying operating system functions.
|
||||
</li>
|
||||
</ul></div>
|
||||
<p>
|
||||
Finally, multiple buffers can be passed to scatter-gather operations (such
|
||||
as <a class="link" href="../../reference/read.html" title="read">read()</a> or <a class="link" href="../../reference/write.html" title="write">write()</a>)
|
||||
by putting the buffer objects into a container. The <code class="computeroutput"><span class="identifier">MutableBufferSequence</span></code>
|
||||
and <code class="computeroutput"><span class="identifier">ConstBufferSequence</span></code>
|
||||
concepts have been defined so that containers such as <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span></code>,
|
||||
<code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">list</span></code>, <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">array</span></code>
|
||||
or <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">array</span></code> can be used.
|
||||
</p>
|
||||
<h6>
|
||||
<a name="asio.overview.core.buffers.h0"></a>
|
||||
<span><a name="asio.overview.core.buffers.streambuf_for_integration_with_iostreams"></a></span><a class="link" href="buffers.html#asio.overview.core.buffers.streambuf_for_integration_with_iostreams">Streambuf
|
||||
for Integration with Iostreams</a>
|
||||
</h6>
|
||||
<p>
|
||||
The class <code class="computeroutput"><span class="identifier">asio</span><span class="special">::</span><span class="identifier">basic_streambuf</span></code> is derived from <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_streambuf</span></code> to associate the input
|
||||
sequence and output sequence with one or more objects of some character
|
||||
array type, whose elements store arbitrary values. These character array
|
||||
objects are internal to the streambuf object, but direct access to the
|
||||
array elements is provided to permit them to be used with I/O operations,
|
||||
such as the send or receive operations of a socket:
|
||||
</p>
|
||||
<div class="itemizedlist"><ul class="itemizedlist" type="disc">
|
||||
<li class="listitem">
|
||||
The input sequence of the streambuf is accessible via the <a class="link" href="../../reference/basic_streambuf/data.html" title="basic_streambuf::data">data()</a>
|
||||
member function. The return type of this function meets the <code class="computeroutput"><span class="identifier">ConstBufferSequence</span></code> requirements.
|
||||
</li>
|
||||
<li class="listitem">
|
||||
The output sequence of the streambuf is accessible via the <a class="link" href="../../reference/basic_streambuf/prepare.html" title="basic_streambuf::prepare">prepare()</a>
|
||||
member function. The return type of this function meets the <code class="computeroutput"><span class="identifier">MutableBufferSequence</span></code> requirements.
|
||||
</li>
|
||||
<li class="listitem">
|
||||
Data is transferred from the front of the output sequence to the back
|
||||
of the input sequence by calling the <a class="link" href="../../reference/basic_streambuf/commit.html" title="basic_streambuf::commit">commit()</a>
|
||||
member function.
|
||||
</li>
|
||||
<li class="listitem">
|
||||
Data is removed from the front of the input sequence by calling the
|
||||
<a class="link" href="../../reference/basic_streambuf/consume.html" title="basic_streambuf::consume">consume()</a>
|
||||
member function.
|
||||
</li>
|
||||
</ul></div>
|
||||
<p>
|
||||
The streambuf constructor accepts a <code class="computeroutput"><span class="identifier">size_t</span></code>
|
||||
argument specifying the maximum of the sum of the sizes of the input sequence
|
||||
and output sequence. Any operation that would, if successful, grow the
|
||||
internal data beyond this limit will throw a <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">length_error</span></code>
|
||||
exception.
|
||||
</p>
|
||||
<h6>
|
||||
<a name="asio.overview.core.buffers.h1"></a>
|
||||
<span><a name="asio.overview.core.buffers.bytewise_traversal_of_buffer_sequences"></a></span><a class="link" href="buffers.html#asio.overview.core.buffers.bytewise_traversal_of_buffer_sequences">Bytewise
|
||||
Traversal of Buffer Sequences</a>
|
||||
</h6>
|
||||
<p>
|
||||
The <code class="computeroutput"><span class="identifier">buffers_iterator</span><span class="special"><></span></code>
|
||||
class template allows buffer sequences (i.e. types meeting <code class="computeroutput"><span class="identifier">MutableBufferSequence</span></code> or <code class="computeroutput"><span class="identifier">ConstBufferSequence</span></code> requirements) to
|
||||
be traversed as though they were a contiguous sequence of bytes. Helper
|
||||
functions called buffers_begin() and buffers_end() are also provided, where
|
||||
the buffers_iterator<> template parameter is automatically deduced.
|
||||
</p>
|
||||
<p>
|
||||
As an example, to read a single line from a socket and into a <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code>, you may write:
|
||||
</p>
|
||||
<pre class="programlisting"><span class="identifier">asio</span><span class="special">::</span><span class="identifier">streambuf</span> <span class="identifier">sb</span><span class="special">;</span>
|
||||
<span class="special">...</span>
|
||||
<span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">n</span> <span class="special">=</span> <span class="identifier">asio</span><span class="special">::</span><span class="identifier">read_until</span><span class="special">(</span><span class="identifier">sock</span><span class="special">,</span> <span class="identifier">sb</span><span class="special">,</span> <span class="char">'\n'</span><span class="special">);</span>
|
||||
<span class="identifier">asio</span><span class="special">::</span><span class="identifier">streambuf</span><span class="special">::</span><span class="identifier">const_buffers_type</span> <span class="identifier">bufs</span> <span class="special">=</span> <span class="identifier">sb</span><span class="special">.</span><span class="identifier">data</span><span class="special">();</span>
|
||||
<span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">line</span><span class="special">(</span>
|
||||
<span class="identifier">asio</span><span class="special">::</span><span class="identifier">buffers_begin</span><span class="special">(</span><span class="identifier">bufs</span><span class="special">),</span>
|
||||
<span class="identifier">asio</span><span class="special">::</span><span class="identifier">buffers_begin</span><span class="special">(</span><span class="identifier">bufs</span><span class="special">)</span> <span class="special">+</span> <span class="identifier">n</span><span class="special">);</span>
|
||||
</pre>
|
||||
<h6>
|
||||
<a name="asio.overview.core.buffers.h2"></a>
|
||||
<span><a name="asio.overview.core.buffers.buffer_debugging"></a></span><a class="link" href="buffers.html#asio.overview.core.buffers.buffer_debugging">Buffer
|
||||
Debugging</a>
|
||||
</h6>
|
||||
<p>
|
||||
Some standard library implementations, such as the one that ships with
|
||||
Microsoft Visual C++ 8.0 and later, provide a feature called iterator debugging.
|
||||
What this means is that the validity of iterators is checked at runtime.
|
||||
If a program tries to use an iterator that has been invalidated, an assertion
|
||||
will be triggered. For example:
|
||||
</p>
|
||||
<pre class="programlisting"><span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special"><</span><span class="keyword">int</span><span class="special">></span> <span class="identifier">v</span><span class="special">(</span><span class="number">1</span><span class="special">)</span>
|
||||
<span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special"><</span><span class="keyword">int</span><span class="special">>::</span><span class="identifier">iterator</span> <span class="identifier">i</span> <span class="special">=</span> <span class="identifier">v</span><span class="special">.</span><span class="identifier">begin</span><span class="special">();</span>
|
||||
<span class="identifier">v</span><span class="special">.</span><span class="identifier">clear</span><span class="special">();</span> <span class="comment">// invalidates iterators</span>
|
||||
<span class="special">*</span><span class="identifier">i</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span> <span class="comment">// assertion!</span>
|
||||
</pre>
|
||||
<p>
|
||||
Asio takes advantage of this feature to add buffer debugging. Consider
|
||||
the following code:
|
||||
</p>
|
||||
<pre class="programlisting"><span class="keyword">void</span> <span class="identifier">dont_do_this</span><span class="special">()</span>
|
||||
<span class="special">{</span>
|
||||
<span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">msg</span> <span class="special">=</span> <span class="string">"Hello, world!"</span><span class="special">;</span>
|
||||
<span class="identifier">asio</span><span class="special">::</span><span class="identifier">async_write</span><span class="special">(</span><span class="identifier">sock</span><span class="special">,</span> <span class="identifier">asio</span><span class="special">::</span><span class="identifier">buffer</span><span class="special">(</span><span class="identifier">msg</span><span class="special">),</span> <span class="identifier">my_handler</span><span class="special">);</span>
|
||||
<span class="special">}</span>
|
||||
</pre>
|
||||
<p>
|
||||
When you call an asynchronous read or write you need to ensure that the
|
||||
buffers for the operation are valid until the completion handler is called.
|
||||
In the above example, the buffer is the <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code>
|
||||
variable <code class="computeroutput"><span class="identifier">msg</span></code>. This variable
|
||||
is on the stack, and so it goes out of scope before the asynchronous operation
|
||||
completes. If you're lucky then the application will crash, but random
|
||||
failures are more likely.
|
||||
</p>
|
||||
<p>
|
||||
When buffer debugging is enabled, Asio stores an iterator into the string
|
||||
until the asynchronous operation completes, and then dereferences it to
|
||||
check its validity. In the above example you would observe an assertion
|
||||
failure just before Asio tries to call the completion handler.
|
||||
</p>
|
||||
<p>
|
||||
This feature is automatically made available for Microsoft Visual Studio
|
||||
8.0 or later and for GCC when <code class="computeroutput"><span class="identifier">_GLIBCXX_DEBUG</span></code>
|
||||
is defined. There is a performance cost to this checking, so buffer debugging
|
||||
is only enabled in debug builds. For other compilers it may be enabled
|
||||
by defining <code class="computeroutput"><span class="identifier">ASIO_ENABLE_BUFFER_DEBUGGING</span></code>.
|
||||
It can also be explicitly disabled by defining <code class="computeroutput"><span class="identifier">ASIO_DISABLE_BUFFER_DEBUGGING</span></code>.
|
||||
</p>
|
||||
<h6>
|
||||
<a name="asio.overview.core.buffers.h3"></a>
|
||||
<span><a name="asio.overview.core.buffers.see_also"></a></span><a class="link" href="buffers.html#asio.overview.core.buffers.see_also">See
|
||||
Also</a>
|
||||
</h6>
|
||||
<p>
|
||||
<a class="link" href="../../reference/buffer.html" title="buffer">buffer</a>, <a class="link" href="../../reference/buffers_begin.html" title="buffers_begin">buffers_begin</a>,
|
||||
<a class="link" href="../../reference/buffers_end.html" title="buffers_end">buffers_end</a>, <a class="link" href="../../reference/buffers_iterator.html" title="buffers_iterator">buffers_iterator</a>,
|
||||
<a class="link" href="../../reference/const_buffer.html" title="const_buffer">const_buffer</a>, <a class="link" href="../../reference/const_buffers_1.html" title="const_buffers_1">const_buffers_1</a>, <a class="link" href="../../reference/mutable_buffer.html" title="mutable_buffer">mutable_buffer</a>, <a class="link" href="../../reference/mutable_buffers_1.html" title="mutable_buffers_1">mutable_buffers_1</a>,
|
||||
<a class="link" href="../../reference/streambuf.html" title="streambuf">streambuf</a>, <a class="link" href="../../reference/ConstBufferSequence.html" title="Constant buffer sequence requirements">ConstBufferSequence</a>,
|
||||
<a class="link" href="../../reference/MutableBufferSequence.html" title="Mutable buffer sequence requirements">MutableBufferSequence</a>,
|
||||
<a class="link" href="../../examples/cpp03_examples.html#asio.examples.cpp03_examples.buffers">buffers example (C++03)</a>,
|
||||
<a class="link" href="../../examples/cpp11_examples.html#asio.examples.cpp11_examples.buffers">buffers example (c++11)</a>.
|
||||
</p>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"></td>
|
||||
<td align="right"><div class="copyright-footer">Copyright © 2003-2020 Christopher M.
|
||||
Kohlhoff<p>
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
|
||||
</p>
|
||||
</div></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="strands.html"><img src="../../../prev.png" alt="Prev"></a><a accesskey="u" href="../core.html"><img src="../../../up.png" alt="Up"></a><a accesskey="h" href="../../../index.html"><img src="../../../home.png" alt="Home"></a><a accesskey="n" href="streams.html"><img src="../../../next.png" alt="Next"></a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,168 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title>Concurrency Hints</title>
|
||||
<link rel="stylesheet" href="../../../boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.75.2">
|
||||
<link rel="home" href="../../../index.html" title="Asio">
|
||||
<link rel="up" href="../core.html" title="Core Concepts and Functionality">
|
||||
<link rel="prev" href="handler_tracking.html" title="Handler Tracking">
|
||||
<link rel="next" href="coroutine.html" title="Stackless Coroutines">
|
||||
</head>
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
<table cellpadding="2" width="100%"><tr><td valign="top"><img alt="asio C++ library" width="250" height="60" src="../../../asio.png"></td></tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="handler_tracking.html"><img src="../../../prev.png" alt="Prev"></a><a accesskey="u" href="../core.html"><img src="../../../up.png" alt="Up"></a><a accesskey="h" href="../../../index.html"><img src="../../../home.png" alt="Home"></a><a accesskey="n" href="coroutine.html"><img src="../../../next.png" alt="Next"></a>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="titlepage"><div><div><h4 class="title">
|
||||
<a name="asio.overview.core.concurrency_hint"></a><a class="link" href="concurrency_hint.html" title="Concurrency Hints">Concurrency Hints</a>
|
||||
</h4></div></div></div>
|
||||
<p>
|
||||
The <a class="link" href="../../reference/io_context/io_context.html" title="io_context::io_context"><code class="computeroutput"><span class="identifier">io_context</span></code> constructor</a> allows
|
||||
programs to specify a concurrency hint. This is a suggestion to the <code class="computeroutput"><span class="identifier">io_context</span></code> implementation as to the number
|
||||
of active threads that should be used for running completion handlers.
|
||||
</p>
|
||||
<p>
|
||||
When the Windows I/O completion port backend is in use, this value is passed
|
||||
to <code class="literal">CreateIoCompletionPort</code>.
|
||||
</p>
|
||||
<p>
|
||||
When a reactor-based backend is used, the implementation recognises the
|
||||
following special concurrency hint values:
|
||||
</p>
|
||||
<div class="informaltable"><table class="table">
|
||||
<colgroup>
|
||||
<col>
|
||||
<col>
|
||||
</colgroup>
|
||||
<thead><tr>
|
||||
<th>
|
||||
<p>
|
||||
Value
|
||||
</p>
|
||||
</th>
|
||||
<th>
|
||||
<p>
|
||||
Description
|
||||
</p>
|
||||
</th>
|
||||
</tr></thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<p>
|
||||
<code class="computeroutput"><span class="number">1</span></code>
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
The implementation assumes that the <code class="computeroutput"><span class="identifier">io_context</span></code>
|
||||
will be run from a single thread, and applies several optimisations
|
||||
based on this assumption.
|
||||
</p>
|
||||
<p>
|
||||
For example, when a handler is posted from within another handler,
|
||||
the new handler is added to a fast thread-local queue (with the
|
||||
consequence that the new handler is held back until the currently
|
||||
executing handler finishes).
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<p>
|
||||
<code class="computeroutput"><span class="identifier">ASIO_CONCURRENCY_HINT_UNSAFE</span></code>
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
This special concurrency hint disables locking in both the scheduler
|
||||
and reactor I/O. This hint has the following restrictions:
|
||||
</p>
|
||||
<p>
|
||||
— Care must be taken to ensure that all operations on the <code class="computeroutput"><span class="identifier">io_context</span></code> and any of its associated
|
||||
I/O objects (such as sockets and timers) occur in only one thread
|
||||
at a time.
|
||||
</p>
|
||||
<p>
|
||||
— Asynchronous resolve operations fail with <code class="computeroutput"><span class="identifier">operation_not_supported</span></code>.
|
||||
</p>
|
||||
<p>
|
||||
— If a <code class="computeroutput"><span class="identifier">signal_set</span></code>
|
||||
is used with the <code class="computeroutput"><span class="identifier">io_context</span></code>,
|
||||
<code class="computeroutput"><span class="identifier">signal_set</span></code> objects
|
||||
cannot be used with any other io_context in the program.
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<p>
|
||||
<code class="computeroutput"><span class="identifier">ASIO_CONCURRENCY_HINT_UNSAFE_IO</span></code>
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
This special concurrency hint disables locking in the reactor
|
||||
I/O. This hint has the following restrictions:
|
||||
</p>
|
||||
<p>
|
||||
— Care must be taken to ensure that run functions on the <code class="computeroutput"><span class="identifier">io_context</span></code>, and all operations
|
||||
on the context's associated I/O objects (such as sockets and
|
||||
timers), occur in only one thread at a time.
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<p>
|
||||
<code class="computeroutput"><span class="identifier">ASIO_CONCURRENCY_HINT_SAFE</span></code>
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
The default. The <code class="computeroutput"><span class="identifier">io_context</span></code>
|
||||
provides full thread safety, and distinct I/O objects may be
|
||||
used from any thread.
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table></div>
|
||||
<p>
|
||||
The concurrency hint used by default-constructed <code class="computeroutput">io_context</code>
|
||||
objects can be overridden at compile time by defining the <code class="computeroutput">ASIO_CONCURRENCY_HINT_DEFAULT</code>
|
||||
macro. For example, specifying
|
||||
</p>
|
||||
<pre class="programlisting">-DASIO_CONCURRENCY_HINT_DEFAULT=1
|
||||
</pre>
|
||||
<p>
|
||||
on the compiler command line means that a concurrency hint of <code class="computeroutput">1</code>
|
||||
is used for all default-constructed <code class="computeroutput">io_context</code> objects in
|
||||
the program. Similarly, the concurrency hint used by <code class="computeroutput">io_context</code>
|
||||
objects constructed with <code class="computeroutput">1</code> can be overridden by defining
|
||||
<code class="computeroutput">ASIO_CONCURRENCY_HINT_1</code>. For example, passing
|
||||
</p>
|
||||
<pre class="programlisting">-DASIO_CONCURRENCY_HINT_1=ASIO_CONCURRENCY_HINT_UNSAFE
|
||||
</pre>
|
||||
<p>
|
||||
to the compiler will disable thread safety for all of these objects.
|
||||
</p>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"></td>
|
||||
<td align="right"><div class="copyright-footer">Copyright © 2003-2020 Christopher M.
|
||||
Kohlhoff<p>
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
|
||||
</p>
|
||||
</div></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="handler_tracking.html"><img src="../../../prev.png" alt="Prev"></a><a accesskey="u" href="../core.html"><img src="../../../up.png" alt="Up"></a><a accesskey="h" href="../../../index.html"><img src="../../../home.png" alt="Home"></a><a accesskey="n" href="coroutine.html"><img src="../../../next.png" alt="Next"></a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,84 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title>Stackless Coroutines</title>
|
||||
<link rel="stylesheet" href="../../../boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.75.2">
|
||||
<link rel="home" href="../../../index.html" title="Asio">
|
||||
<link rel="up" href="../core.html" title="Core Concepts and Functionality">
|
||||
<link rel="prev" href="concurrency_hint.html" title="Concurrency Hints">
|
||||
<link rel="next" href="spawn.html" title="Stackful Coroutines">
|
||||
</head>
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
<table cellpadding="2" width="100%"><tr><td valign="top"><img alt="asio C++ library" width="250" height="60" src="../../../asio.png"></td></tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="concurrency_hint.html"><img src="../../../prev.png" alt="Prev"></a><a accesskey="u" href="../core.html"><img src="../../../up.png" alt="Up"></a><a accesskey="h" href="../../../index.html"><img src="../../../home.png" alt="Home"></a><a accesskey="n" href="spawn.html"><img src="../../../next.png" alt="Next"></a>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="titlepage"><div><div><h4 class="title">
|
||||
<a name="asio.overview.core.coroutine"></a><a class="link" href="coroutine.html" title="Stackless Coroutines">Stackless Coroutines</a>
|
||||
</h4></div></div></div>
|
||||
<p>
|
||||
The <a class="link" href="../../reference/coroutine.html" title="coroutine"><code class="computeroutput">coroutine</code></a>
|
||||
class provides support for stackless coroutines. Stackless coroutines enable
|
||||
programs to implement asynchronous logic in a synchronous manner, with
|
||||
minimal overhead, as shown in the following example:
|
||||
</p>
|
||||
<pre class="programlisting">struct session : asio::coroutine
|
||||
{
|
||||
boost::shared_ptr<tcp::socket> socket_;
|
||||
boost::shared_ptr<std::vector<char> > buffer_;
|
||||
|
||||
session(boost::shared_ptr<tcp::socket> socket)
|
||||
: socket_(socket),
|
||||
buffer_(new std::vector<char>(1024))
|
||||
{
|
||||
}
|
||||
|
||||
void operator()(asio::error_code ec = asio::error_code(), std::size_t n = 0)
|
||||
{
|
||||
if (!ec) reenter (this)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
yield socket_->async_read_some(asio::buffer(*buffer_), *this);
|
||||
yield asio::async_write(*socket_, asio::buffer(*buffer_, n), *this);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</pre>
|
||||
<p>
|
||||
The <code class="computeroutput">coroutine</code> class is used in conjunction with the pseudo-keywords
|
||||
<code class="computeroutput">reenter</code>, <code class="computeroutput">yield</code> and <code class="computeroutput">fork</code>. These are
|
||||
preprocessor macros, and are implemented in terms of a <code class="computeroutput">switch</code>
|
||||
statement using a technique similar to Duff's Device. The <a class="link" href="../../reference/coroutine.html" title="coroutine"><code class="computeroutput">coroutine</code></a>
|
||||
class's documentation provides a complete description of these pseudo-keywords.
|
||||
</p>
|
||||
<h6>
|
||||
<a name="asio.overview.core.coroutine.h0"></a>
|
||||
<span><a name="asio.overview.core.coroutine.see_also"></a></span><a class="link" href="coroutine.html#asio.overview.core.coroutine.see_also">See
|
||||
Also</a>
|
||||
</h6>
|
||||
<p>
|
||||
<a class="link" href="../../reference/coroutine.html" title="coroutine">coroutine</a>, <a class="link" href="../../examples/cpp03_examples.html#asio.examples.cpp03_examples.http_server_4">HTTP
|
||||
Server 4 example</a>, <a class="link" href="spawn.html" title="Stackful Coroutines">Stackful
|
||||
Coroutines</a>.
|
||||
</p>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"></td>
|
||||
<td align="right"><div class="copyright-footer">Copyright © 2003-2020 Christopher M.
|
||||
Kohlhoff<p>
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
|
||||
</p>
|
||||
</div></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="concurrency_hint.html"><img src="../../../prev.png" alt="Prev"></a><a accesskey="u" href="../core.html"><img src="../../../up.png" alt="Up"></a><a accesskey="h" href="../../../index.html"><img src="../../../home.png" alt="Home"></a><a accesskey="n" href="spawn.html"><img src="../../../next.png" alt="Next"></a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,132 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title>Coroutines TS Support</title>
|
||||
<link rel="stylesheet" href="../../../boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.75.2">
|
||||
<link rel="home" href="../../../index.html" title="Asio">
|
||||
<link rel="up" href="../core.html" title="Core Concepts and Functionality">
|
||||
<link rel="prev" href="spawn.html" title="Stackful Coroutines">
|
||||
<link rel="next" href="../networking.html" title="Networking">
|
||||
</head>
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
<table cellpadding="2" width="100%"><tr><td valign="top"><img alt="asio C++ library" width="250" height="60" src="../../../asio.png"></td></tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="spawn.html"><img src="../../../prev.png" alt="Prev"></a><a accesskey="u" href="../core.html"><img src="../../../up.png" alt="Up"></a><a accesskey="h" href="../../../index.html"><img src="../../../home.png" alt="Home"></a><a accesskey="n" href="../networking.html"><img src="../../../next.png" alt="Next"></a>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="titlepage"><div><div><h4 class="title">
|
||||
<a name="asio.overview.core.coroutines_ts"></a><a class="link" href="coroutines_ts.html" title="Coroutines TS Support">Coroutines TS Support</a>
|
||||
</h4></div></div></div>
|
||||
<p>
|
||||
Support for the Coroutines TS is provided via the <a class="link" href="../../reference/awaitable.html" title="awaitable"><code class="computeroutput">awaitable</code></a>
|
||||
class template, the <a class="link" href="../../reference/use_awaitable_t.html" title="use_awaitable_t"><code class="computeroutput">use_awaitable</code></a>
|
||||
completion token, and the <a class="link" href="../../reference/co_spawn.html" title="co_spawn"><code class="computeroutput">co_spawn()</code></a>
|
||||
function. These facilities allow programs to implement asynchronous logic
|
||||
in a synchronous manner, in conjunction with the <code class="computeroutput">co_await</code>
|
||||
keyword, as shown in the following example:
|
||||
</p>
|
||||
<pre class="programlisting">asio::co_spawn(executor, echo(std::move(socket)), asio::detached);
|
||||
|
||||
// ...
|
||||
|
||||
asio::awaitable<void> echo(tcp::socket socket)
|
||||
{
|
||||
try
|
||||
{
|
||||
char data[1024];
|
||||
for (;;)
|
||||
{
|
||||
std::size_t n = co_await socket.async_read_some(asio::buffer(data), asio::use_awaitable);
|
||||
co_await async_write(socket, asio::buffer(data, n), asio::use_awaitable);
|
||||
}
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
std::printf("echo Exception: %s\n", e.what());
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
<p>
|
||||
The first argument to <code class="computeroutput">co_spawn()</code> is an <a class="link" href="../../reference/Executor1.html" title="Executor requirements">executor</a>
|
||||
that 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 <code class="computeroutput">strand</code> so that no explicit
|
||||
synchronisation is required.
|
||||
</p>
|
||||
<p>
|
||||
The second argument is an <a class="link" href="../../reference/awaitable.html" title="awaitable"><code class="computeroutput">awaitable<R></code></a>,
|
||||
that is the result of the coroutine's entry point function, and in the
|
||||
above example is the result of the call to <code class="computeroutput">echo</code>. (Alternatively,
|
||||
this argument can be a function object that returns the <a class="link" href="../../reference/awaitable.html" title="awaitable"><code class="computeroutput">awaitable<R></code></a>.)
|
||||
The template parameter <code class="computeroutput">R</code> is the type of return value produced
|
||||
by the coroutine. In the above example, the coroutine returns <code class="computeroutput">void</code>.
|
||||
</p>
|
||||
<p>
|
||||
The third argument is a completion token, and this is used by <code class="computeroutput">co_spawn()</code>
|
||||
to produce a completion handler with signature <code class="computeroutput">void(std::exception_ptr,
|
||||
R)</code>. This completion handler is invoked with the result of the coroutine
|
||||
once it has finished. In the above example we pass a completion token type,
|
||||
<a class="link" href="../../reference/detached.html" title="detached"><code class="computeroutput">asio::detached</code></a>,
|
||||
which is used to explicitly ignore the result of an asynchronous operation.
|
||||
</p>
|
||||
<p>
|
||||
In this example the body of the coroutine is implemented in the <code class="computeroutput">echo</code>
|
||||
function. When the <code class="computeroutput">use_awaitable</code> completion token is passed
|
||||
to an asynchronous operation, the operation's initiating function returns
|
||||
an <code class="computeroutput">awaitable</code> that may be used with the <code class="computeroutput">co_await</code>
|
||||
keyword:
|
||||
</p>
|
||||
<pre class="programlisting">std::size_t n = co_await socket.async_read_some(asio::buffer(data), asio::use_awaitable);
|
||||
</pre>
|
||||
<p>
|
||||
Where an asynchronous operation's handler signature has the form:
|
||||
</p>
|
||||
<pre class="programlisting">void handler(asio::error_code ec, result_type result);
|
||||
</pre>
|
||||
<p>
|
||||
the resulting type of the <code class="computeroutput">co_await</code> expression is <code class="computeroutput">result_type</code>.
|
||||
In the <code class="computeroutput">async_read_some</code> example above, this is <code class="computeroutput">size_t</code>.
|
||||
If the asynchronous operation fails, the <code class="computeroutput">error_code</code> is converted
|
||||
into a <code class="computeroutput">system_error</code> exception and thrown.
|
||||
</p>
|
||||
<p>
|
||||
Where a handler signature has the form:
|
||||
</p>
|
||||
<pre class="programlisting">void handler(asio::error_code ec);
|
||||
</pre>
|
||||
<p>
|
||||
the <code class="computeroutput">co_await</code> expression produces a <code class="computeroutput">void</code> result.
|
||||
As above, an error is passed back to the coroutine as a <code class="computeroutput">system_error</code>
|
||||
exception.
|
||||
</p>
|
||||
<h6>
|
||||
<a name="asio.overview.core.coroutines_ts.h0"></a>
|
||||
<span><a name="asio.overview.core.coroutines_ts.see_also"></a></span><a class="link" href="coroutines_ts.html#asio.overview.core.coroutines_ts.see_also">See
|
||||
Also</a>
|
||||
</h6>
|
||||
<p>
|
||||
<a class="link" href="../../reference/co_spawn.html" title="co_spawn">co_spawn</a>, <a class="link" href="../../reference/detached.html" title="detached">detached</a>,
|
||||
<a class="link" href="../../reference/redirect_error.html" title="redirect_error">redirect_error</a>, <a class="link" href="../../reference/awaitable.html" title="awaitable">awaitable</a>, <a class="link" href="../../reference/use_awaitable_t.html" title="use_awaitable_t">use_awaitable_t</a>,
|
||||
<a class="link" href="../../reference/use_awaitable.html" title="use_awaitable">use_awaitable</a>, <a class="link" href="../../reference/this_coro__executor.html" title="this_coro::executor">this_coro::executor</a>,
|
||||
<a class="link" href="../../examples/cpp17_examples.html#asio.examples.cpp17_examples.coroutines_ts_support">Coroutines
|
||||
TS examples</a>, <a class="link" href="spawn.html" title="Stackful Coroutines">Stackful Coroutines</a>,
|
||||
<a class="link" href="coroutine.html" title="Stackless Coroutines">Stackless Coroutines</a>.
|
||||
</p>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"></td>
|
||||
<td align="right"><div class="copyright-footer">Copyright © 2003-2020 Christopher M.
|
||||
Kohlhoff<p>
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
|
||||
</p>
|
||||
</div></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="spawn.html"><img src="../../../prev.png" alt="Prev"></a><a accesskey="u" href="../core.html"><img src="../../../up.png" alt="Up"></a><a accesskey="h" href="../../../index.html"><img src="../../../home.png" alt="Home"></a><a accesskey="n" href="../networking.html"><img src="../../../next.png" alt="Next"></a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,490 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title>Handler Tracking</title>
|
||||
<link rel="stylesheet" href="../../../boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.75.2">
|
||||
<link rel="home" href="../../../index.html" title="Asio">
|
||||
<link rel="up" href="../core.html" title="Core Concepts and Functionality">
|
||||
<link rel="prev" href="allocation.html" title="Custom Memory Allocation">
|
||||
<link rel="next" href="concurrency_hint.html" title="Concurrency Hints">
|
||||
</head>
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
<table cellpadding="2" width="100%"><tr><td valign="top"><img alt="asio C++ library" width="250" height="60" src="../../../asio.png"></td></tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="allocation.html"><img src="../../../prev.png" alt="Prev"></a><a accesskey="u" href="../core.html"><img src="../../../up.png" alt="Up"></a><a accesskey="h" href="../../../index.html"><img src="../../../home.png" alt="Home"></a><a accesskey="n" href="concurrency_hint.html"><img src="../../../next.png" alt="Next"></a>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="titlepage"><div><div><h4 class="title">
|
||||
<a name="asio.overview.core.handler_tracking"></a><a class="link" href="handler_tracking.html" title="Handler Tracking">Handler Tracking</a>
|
||||
</h4></div></div></div>
|
||||
<p>
|
||||
To aid in debugging asynchronous programs, Asio provides support for handler
|
||||
tracking. When enabled by defining <code class="computeroutput"><span class="identifier">ASIO_ENABLE_HANDLER_TRACKING</span></code>,
|
||||
Asio writes debugging output to the standard error stream. The output records
|
||||
asynchronous operations and the relationships between their handlers.
|
||||
</p>
|
||||
<p>
|
||||
This feature is useful when debugging and you need to know how your 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:
|
||||
</p>
|
||||
<pre class="programlisting">@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' (./../../../include/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
|
||||
</pre>
|
||||
<p>
|
||||
Each line is of the form:
|
||||
</p>
|
||||
<pre class="programlisting"><tag>|<timestamp>|<action>|<description>
|
||||
</pre>
|
||||
<p>
|
||||
The <code class="computeroutput"><tag></code> is always <code class="computeroutput">@asio</code>, and is used
|
||||
to identify and extract the handler tracking messages from the program
|
||||
output.
|
||||
</p>
|
||||
<p>
|
||||
The <code class="computeroutput"><timestamp></code> is seconds and microseconds from 1 Jan
|
||||
1970 UTC.
|
||||
</p>
|
||||
<p>
|
||||
The <code class="computeroutput"><action></code> takes one of the following forms:
|
||||
</p>
|
||||
<div class="variablelist">
|
||||
<p class="title"><b></b></p>
|
||||
<dl>
|
||||
<dt><span class="term">>n</span></dt>
|
||||
<dd><p>
|
||||
The program entered the handler number <code class="computeroutput">n</code>. The <code class="computeroutput"><description></code>
|
||||
shows the arguments to the handler.
|
||||
</p></dd>
|
||||
<dt><span class="term"><n</span></dt>
|
||||
<dd><p>
|
||||
The program left handler number <code class="computeroutput">n</code>.
|
||||
</p></dd>
|
||||
<dt><span class="term">!n</span></dt>
|
||||
<dd><p>
|
||||
The program left handler number n due to an exception.
|
||||
</p></dd>
|
||||
<dt><span class="term">~n</span></dt>
|
||||
<dd><p>
|
||||
The handler number <code class="computeroutput">n</code> was destroyed without having been
|
||||
invoked. This is usually the case for any unfinished asynchronous
|
||||
operations when the <code class="computeroutput">io_context</code> is destroyed.
|
||||
</p></dd>
|
||||
<dt><span class="term">n^m</span></dt>
|
||||
<dd><p>
|
||||
The handler number <code class="computeroutput">n</code> is about to create a new asynchronous
|
||||
operation with completion handler number <code class="computeroutput">m</code>. The <code class="computeroutput"><description></code>
|
||||
contains source location information to help identify where in the
|
||||
program the asynchronous operation is being started.
|
||||
</p></dd>
|
||||
<dt><span class="term">n*m</span></dt>
|
||||
<dd><p>
|
||||
The handler number <code class="computeroutput">n</code> created a new asynchronous operation
|
||||
with completion handler number <code class="computeroutput">m</code>. The <code class="computeroutput"><description></code>
|
||||
shows what asynchronous operation was started.
|
||||
</p></dd>
|
||||
<dt><span class="term">n</span></dt>
|
||||
<dd><p>
|
||||
The handler number <code class="computeroutput">n</code> performed some other operation.
|
||||
The <code class="computeroutput"><description></code> shows what function was called.
|
||||
Currently only <code class="computeroutput">close()</code> and <code class="computeroutput">cancel()</code> operations
|
||||
are logged, as these may affect the state of pending asynchronous
|
||||
operations.
|
||||
</p></dd>
|
||||
<dt><span class="term">.n</span></dt>
|
||||
<dd><p>
|
||||
The implementation performed a system call as part of the asynchronous
|
||||
operation for which handler number <code class="computeroutput">n</code> is the completion
|
||||
handler. The <code class="computeroutput"><description></code> shows what function
|
||||
was called and its results. These tracking events are only emitted
|
||||
when using a reactor-based implementation.
|
||||
</p></dd>
|
||||
</dl>
|
||||
</div>
|
||||
<p>
|
||||
Where the <code class="computeroutput"><description></code> shows a synchronous or asynchronous
|
||||
operation, the format is <code class="computeroutput"><object-type>@<pointer>.<operation></code>.
|
||||
For handler entry, it shows a comma-separated list of arguments and their
|
||||
values.
|
||||
</p>
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
<h6>
|
||||
<a name="asio.overview.core.handler_tracking.h0"></a>
|
||||
<span><a name="asio.overview.core.handler_tracking.adding_location_information"></a></span><a class="link" href="handler_tracking.html#asio.overview.core.handler_tracking.adding_location_information">Adding
|
||||
Location Information</a>
|
||||
</h6>
|
||||
<p>
|
||||
Programs may augment the handler tracking output's location information
|
||||
by using the macro <code class="computeroutput"><span class="identifier">ASIO_HANDLER_LOCATION</span></code>
|
||||
in the source code. For example:
|
||||
</p>
|
||||
<pre class="programlisting"><span class="preprocessor">#define</span> <span class="identifier">HANDLER_LOCATION</span> <span class="special">\</span>
|
||||
<span class="identifier">ASIO_HANDLER_LOCATION</span><span class="special">((</span><span class="identifier">__FILE__</span><span class="special">,</span> <span class="identifier">__LINE__</span><span class="special">,</span> <span class="identifier">__func__</span><span class="special">))</span>
|
||||
|
||||
<span class="comment">// ...</span>
|
||||
|
||||
<span class="keyword">void</span> <span class="identifier">do_read</span><span class="special">()</span>
|
||||
<span class="special">{</span>
|
||||
<span class="identifier">HANDLER_LOCATION</span><span class="special">;</span>
|
||||
|
||||
<span class="keyword">auto</span> <span class="identifier">self</span><span class="special">(</span><span class="identifier">shared_from_this</span><span class="special">());</span>
|
||||
<span class="identifier">socket_</span><span class="special">.</span><span class="identifier">async_read_some</span><span class="special">(</span><span class="identifier">asio</span><span class="special">::</span><span class="identifier">buffer</span><span class="special">(</span><span class="identifier">data_</span><span class="special">,</span> <span class="identifier">max_length</span><span class="special">),</span>
|
||||
<span class="special">[</span><span class="keyword">this</span><span class="special">,</span> <span class="identifier">self</span><span class="special">](</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">error_code</span> <span class="identifier">ec</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">length</span><span class="special">)</span>
|
||||
<span class="special">{</span>
|
||||
<span class="identifier">HANDLER_LOCATION</span><span class="special">;</span>
|
||||
|
||||
<span class="keyword">if</span> <span class="special">(!</span><span class="identifier">ec</span><span class="special">)</span>
|
||||
<span class="special">{</span>
|
||||
<span class="identifier">do_write</span><span class="special">(</span><span class="identifier">length</span><span class="special">);</span>
|
||||
<span class="special">}</span>
|
||||
<span class="special">});</span>
|
||||
<span class="special">}</span>
|
||||
</pre>
|
||||
<p>
|
||||
With the additional location information available, the handler tracking
|
||||
output may include a call stack of source locations:
|
||||
</p>
|
||||
<pre class="programlisting">@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|
|
||||
</pre>
|
||||
<p>
|
||||
Furthermore, if <code class="computeroutput">std::source_location</code> or <code class="computeroutput">std::experimental::source_location</code>
|
||||
are available, the <a class="link" href="../../reference/use_awaitable_t.html" title="use_awaitable_t"><code class="computeroutput">use_awaitable_t</code></a>
|
||||
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 <code class="computeroutput">use_awaitable_t</code> object may
|
||||
also be explicitly constructed with location information.
|
||||
</p>
|
||||
<h6>
|
||||
<a name="asio.overview.core.handler_tracking.h1"></a>
|
||||
<span><a name="asio.overview.core.handler_tracking.visual_representations"></a></span><a class="link" href="handler_tracking.html#asio.overview.core.handler_tracking.visual_representations">Visual
|
||||
Representations</a>
|
||||
</h6>
|
||||
<p>
|
||||
The handler tracking output may be post-processed using the included <code class="literal">handlerviz.pl</code>
|
||||
tool to create a visual representation of the handlers (requires the GraphViz
|
||||
tool <code class="literal">dot</code>).
|
||||
</p>
|
||||
<h6>
|
||||
<a name="asio.overview.core.handler_tracking.h2"></a>
|
||||
<span><a name="asio.overview.core.handler_tracking.custom_tracking"></a></span><a class="link" href="handler_tracking.html#asio.overview.core.handler_tracking.custom_tracking">Custom Tracking</a>
|
||||
</h6>
|
||||
<p>
|
||||
Handling tracking may be customised by defining the <code class="computeroutput"><span class="identifier">ASIO_CUSTOM_HANDLER_TRACKING</span></code>
|
||||
macro to the name of a header file (enclosed in <code class="computeroutput"><span class="string">""</span></code>
|
||||
or <code class="computeroutput"><span class="special"><></span></code>). This header
|
||||
file must implement the following preprocessor macros:
|
||||
</p>
|
||||
<div class="informaltable"><table class="table">
|
||||
<colgroup>
|
||||
<col>
|
||||
<col>
|
||||
</colgroup>
|
||||
<thead><tr>
|
||||
<th>
|
||||
<p>
|
||||
Macro
|
||||
</p>
|
||||
</th>
|
||||
<th>
|
||||
<p>
|
||||
Description
|
||||
</p>
|
||||
</th>
|
||||
</tr></thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<p>
|
||||
<code class="computeroutput"><span class="identifier">ASIO_INHERIT_TRACKED_HANDLER</span></code>
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
Specifies a base class for classes that implement asynchronous
|
||||
operations. When used, the macro immediately follows the class
|
||||
name, so it must have the form <code class="computeroutput"><span class="special">:</span>
|
||||
<span class="keyword">public</span> <span class="identifier">my_class</span></code>.
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<p>
|
||||
<code class="computeroutput"><span class="identifier">ASIO_ALSO_INHERIT_TRACKED_HANDLER</span></code>
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
Specifies a base class for classes that implement asynchronous
|
||||
operations. When used, the macro follows other base classes,
|
||||
so it must have the form <code class="computeroutput"><span class="special">,</span>
|
||||
<span class="keyword">public</span> <span class="identifier">my_class</span></code>.
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<p>
|
||||
<code class="computeroutput"><span class="identifier">ASIO_HANDLER_TRACKING_INIT</span><span class="special">(</span><span class="identifier">args</span><span class="special">)</span></code>
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
An expression that is used to initialise the tracking mechanism.
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<p>
|
||||
<code class="computeroutput"><span class="identifier">ASIO_HANDLER_LOCATION</span><span class="special">(</span><span class="identifier">args</span><span class="special">)</span></code>
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
A variable declaration that is used to define a source code location.
|
||||
<code class="computeroutput"><span class="identifier">args</span></code> is a parenthesised
|
||||
function argument list containing the file name, line number,
|
||||
and function name.
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<p>
|
||||
<code class="computeroutput"><span class="identifier">ASIO_HANDLER_CREATION</span><span class="special">(</span><span class="identifier">args</span><span class="special">)</span></code>
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
An expression that is called on creation of an asynchronous operation.
|
||||
<code class="computeroutput"><span class="identifier">args</span></code> is a parenthesised
|
||||
function argument list containing the owning execution context,
|
||||
the tracked handler, the name of the object type, a pointer to
|
||||
the object, the object's native handle, and the operation name.
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<p>
|
||||
<code class="computeroutput"><span class="identifier">ASIO_HANDLER_COMPLETION</span><span class="special">(</span><span class="identifier">args</span><span class="special">)</span></code>
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
An expression that is called on completion of an asynchronous
|
||||
operation. <code class="computeroutput"><span class="identifier">args</span></code>
|
||||
is a parenthesised function argument list containing the tracked
|
||||
handler.
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<p>
|
||||
<code class="computeroutput"><span class="identifier">ASIO_HANDLER_INVOCATION_BEGIN</span><span class="special">(</span><span class="identifier">args</span><span class="special">)</span></code>
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
An expression that is called immediately before a completion
|
||||
handler is invoked. <code class="computeroutput"><span class="identifier">args</span></code>
|
||||
is a parenthesised function argument list containing the arguments
|
||||
to the completion handler.
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<p>
|
||||
<code class="computeroutput"><span class="identifier">ASIO_HANDLER_INVOCATION_END</span></code>
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
An expression that is called immediately after a completion handler
|
||||
is invoked.
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<p>
|
||||
<code class="computeroutput"><span class="identifier">ASIO_HANDLER_OPERATION</span><span class="special">(</span><span class="identifier">args</span><span class="special">)</span></code>
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
An expression that is called when some synchronous object operation
|
||||
is called (such as <code class="computeroutput"><span class="identifier">close</span><span class="special">()</span></code> or <code class="computeroutput"><span class="identifier">cancel</span><span class="special">()</span></code>). <code class="computeroutput"><span class="identifier">args</span></code>
|
||||
is a parenthesised function argument list containing the owning
|
||||
execution context, the name of the object type, a pointer to
|
||||
the object, the object's native handle, and the operation name.
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<p>
|
||||
<code class="computeroutput"><span class="identifier">ASIO_HANDLER_REACTOR_REGISTRATION</span><span class="special">(</span><span class="identifier">args</span><span class="special">)</span></code>
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
An expression that is called when an object is registered with
|
||||
the reactor. <code class="computeroutput"><span class="identifier">args</span></code>
|
||||
is a parenthesised function argument list containing the owning
|
||||
execution context, the object's native handle, and a unique registration
|
||||
key.
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<p>
|
||||
<code class="computeroutput"><span class="identifier">ASIO_HANDLER_REACTOR_DEREGISTRATION</span><span class="special">(</span><span class="identifier">args</span><span class="special">)</span></code>
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
An expression that is called when an object is deregistered from
|
||||
the reactor. <code class="computeroutput"><span class="identifier">args</span></code>
|
||||
is a parenthesised function argument list containing the owning
|
||||
execution context, the object's native handle, and a unique registration
|
||||
key.
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<p>
|
||||
<code class="computeroutput"><span class="identifier">ASIO_HANDLER_REACTOR_READ_EVENT</span></code>
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
A bitmask constant used to identify reactor read readiness events.
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<p>
|
||||
<code class="computeroutput"><span class="identifier">ASIO_HANDLER_REACTOR_WRITE_EVENT</span></code>
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
A bitmask constant used to identify reactor write readiness events.
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<p>
|
||||
<code class="computeroutput"><span class="identifier">ASIO_HANDLER_REACTOR_ERROR_EVENT</span></code>
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
A bitmask constant used to identify reactor error readiness events.
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<p>
|
||||
<code class="computeroutput"><span class="identifier">ASIO_HANDLER_REACTOR_EVENTS</span><span class="special">(</span><span class="identifier">args</span><span class="special">)</span></code>
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
An expression that is called when an object registered with the
|
||||
reactor becomes ready. <code class="computeroutput"><span class="identifier">args</span></code>
|
||||
is a parenthesised function argument list containing the owning
|
||||
execution context, the unique registration key, and a bitmask
|
||||
of the ready events.
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<p>
|
||||
<code class="computeroutput"><span class="identifier">ASIO_HANDLER_REACTOR_OPERATION</span><span class="special">(</span><span class="identifier">args</span><span class="special">)</span></code>
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
An expression that is called when the implementation performs
|
||||
a system call as part of a reactor-based asynchronous operation.
|
||||
<code class="computeroutput"><span class="identifier">args</span></code> is a parenthesised
|
||||
function argument list containing the tracked handler, the operation
|
||||
name, the error code produced by the operation, and (optionally)
|
||||
the number of bytes transferred.
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table></div>
|
||||
<h6>
|
||||
<a name="asio.overview.core.handler_tracking.h3"></a>
|
||||
<span><a name="asio.overview.core.handler_tracking.see_also"></a></span><a class="link" href="handler_tracking.html#asio.overview.core.handler_tracking.see_also">See
|
||||
Also</a>
|
||||
</h6>
|
||||
<p>
|
||||
<a class="link" href="../../examples/cpp11_examples.html#asio.examples.cpp11_examples.handler_tracking">Handler tracking
|
||||
examples</a>.
|
||||
</p>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"></td>
|
||||
<td align="right"><div class="copyright-footer">Copyright © 2003-2020 Christopher M.
|
||||
Kohlhoff<p>
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
|
||||
</p>
|
||||
</div></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="allocation.html"><img src="../../../prev.png" alt="Prev"></a><a accesskey="u" href="../core.html"><img src="../../../up.png" alt="Up"></a><a accesskey="h" href="../../../index.html"><img src="../../../home.png" alt="Home"></a><a accesskey="n" href="concurrency_hint.html"><img src="../../../next.png" alt="Next"></a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,158 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title>Line-Based Operations</title>
|
||||
<link rel="stylesheet" href="../../../boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.75.2">
|
||||
<link rel="home" href="../../../index.html" title="Asio">
|
||||
<link rel="up" href="../core.html" title="Core Concepts and Functionality">
|
||||
<link rel="prev" href="reactor.html" title="Reactor-Style Operations">
|
||||
<link rel="next" href="allocation.html" title="Custom Memory Allocation">
|
||||
</head>
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
<table cellpadding="2" width="100%"><tr><td valign="top"><img alt="asio C++ library" width="250" height="60" src="../../../asio.png"></td></tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="reactor.html"><img src="../../../prev.png" alt="Prev"></a><a accesskey="u" href="../core.html"><img src="../../../up.png" alt="Up"></a><a accesskey="h" href="../../../index.html"><img src="../../../home.png" alt="Home"></a><a accesskey="n" href="allocation.html"><img src="../../../next.png" alt="Next"></a>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="titlepage"><div><div><h4 class="title">
|
||||
<a name="asio.overview.core.line_based"></a><a class="link" href="line_based.html" title="Line-Based Operations">Line-Based Operations</a>
|
||||
</h4></div></div></div>
|
||||
<p>
|
||||
Many commonly-used internet protocols are line-based, which means that
|
||||
they have protocol elements that are delimited by the character sequence
|
||||
<code class="computeroutput"><span class="string">"\r\n"</span></code>. Examples
|
||||
include HTTP, SMTP and FTP. To more easily permit the implementation of
|
||||
line-based protocols, as well as other protocols that use delimiters, Asio
|
||||
includes the functions <code class="computeroutput"><span class="identifier">read_until</span><span class="special">()</span></code> and <code class="computeroutput"><span class="identifier">async_read_until</span><span class="special">()</span></code>.
|
||||
</p>
|
||||
<p>
|
||||
The following example illustrates the use of <code class="computeroutput"><span class="identifier">async_read_until</span><span class="special">()</span></code> in an HTTP server, to receive the first
|
||||
line of an HTTP request from a client:
|
||||
</p>
|
||||
<pre class="programlisting"><span class="keyword">class</span> <span class="identifier">http_connection</span>
|
||||
<span class="special">{</span>
|
||||
<span class="special">...</span>
|
||||
|
||||
<span class="keyword">void</span> <span class="identifier">start</span><span class="special">()</span>
|
||||
<span class="special">{</span>
|
||||
<span class="identifier">asio</span><span class="special">::</span><span class="identifier">async_read_until</span><span class="special">(</span><span class="identifier">socket_</span><span class="special">,</span> <span class="identifier">data_</span><span class="special">,</span> <span class="string">"\r\n"</span><span class="special">,</span>
|
||||
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">bind</span><span class="special">(&</span><span class="identifier">http_connection</span><span class="special">::</span><span class="identifier">handle_request_line</span><span class="special">,</span> <span class="keyword">this</span><span class="special">,</span> <span class="identifier">_1</span><span class="special">));</span>
|
||||
<span class="special">}</span>
|
||||
|
||||
<span class="keyword">void</span> <span class="identifier">handle_request_line</span><span class="special">(</span><span class="identifier">asio</span><span class="special">::</span><span class="identifier">error_code</span> <span class="identifier">ec</span><span class="special">)</span>
|
||||
<span class="special">{</span>
|
||||
<span class="keyword">if</span> <span class="special">(!</span><span class="identifier">ec</span><span class="special">)</span>
|
||||
<span class="special">{</span>
|
||||
<span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">method</span><span class="special">,</span> <span class="identifier">uri</span><span class="special">,</span> <span class="identifier">version</span><span class="special">;</span>
|
||||
<span class="keyword">char</span> <span class="identifier">sp1</span><span class="special">,</span> <span class="identifier">sp2</span><span class="special">,</span> <span class="identifier">cr</span><span class="special">,</span> <span class="identifier">lf</span><span class="special">;</span>
|
||||
<span class="identifier">std</span><span class="special">::</span><span class="identifier">istream</span> <span class="identifier">is</span><span class="special">(&</span><span class="identifier">data_</span><span class="special">);</span>
|
||||
<span class="identifier">is</span><span class="special">.</span><span class="identifier">unsetf</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">ios_base</span><span class="special">::</span><span class="identifier">skipws</span><span class="special">);</span>
|
||||
<span class="identifier">is</span> <span class="special">>></span> <span class="identifier">method</span> <span class="special">>></span> <span class="identifier">sp1</span> <span class="special">>></span> <span class="identifier">uri</span> <span class="special">>></span> <span class="identifier">sp2</span> <span class="special">>></span> <span class="identifier">version</span> <span class="special">>></span> <span class="identifier">cr</span> <span class="special">>></span> <span class="identifier">lf</span><span class="special">;</span>
|
||||
<span class="special">...</span>
|
||||
<span class="special">}</span>
|
||||
<span class="special">}</span>
|
||||
|
||||
<span class="special">...</span>
|
||||
|
||||
<span class="identifier">asio</span><span class="special">::</span><span class="identifier">ip</span><span class="special">::</span><span class="identifier">tcp</span><span class="special">::</span><span class="identifier">socket</span> <span class="identifier">socket_</span><span class="special">;</span>
|
||||
<span class="identifier">asio</span><span class="special">::</span><span class="identifier">streambuf</span> <span class="identifier">data_</span><span class="special">;</span>
|
||||
<span class="special">};</span>
|
||||
</pre>
|
||||
<p>
|
||||
The <code class="computeroutput"><span class="identifier">streambuf</span></code> data member
|
||||
serves as a place to store the data that has been read from the socket
|
||||
before it is searched for the delimiter. It is important to remember that
|
||||
there may be additional data <span class="emphasis"><em>after</em></span> the delimiter.
|
||||
This surplus data should be left in the <code class="computeroutput"><span class="identifier">streambuf</span></code>
|
||||
so that it may be inspected by a subsequent call to <code class="computeroutput"><span class="identifier">read_until</span><span class="special">()</span></code> or <code class="computeroutput"><span class="identifier">async_read_until</span><span class="special">()</span></code>.
|
||||
</p>
|
||||
<p>
|
||||
The delimiters may be specified as a single <code class="computeroutput"><span class="keyword">char</span></code>,
|
||||
a <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code> or a <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">regex</span></code>.
|
||||
The <code class="computeroutput"><span class="identifier">read_until</span><span class="special">()</span></code>
|
||||
and <code class="computeroutput"><span class="identifier">async_read_until</span><span class="special">()</span></code>
|
||||
functions also include overloads that accept a user-defined function object
|
||||
called a match condition. For example, to read data into a streambuf until
|
||||
whitespace is encountered:
|
||||
</p>
|
||||
<pre class="programlisting"><span class="keyword">typedef</span> <span class="identifier">asio</span><span class="special">::</span><span class="identifier">buffers_iterator</span><span class="special"><</span>
|
||||
<span class="identifier">asio</span><span class="special">::</span><span class="identifier">streambuf</span><span class="special">::</span><span class="identifier">const_buffers_type</span><span class="special">></span> <span class="identifier">iterator</span><span class="special">;</span>
|
||||
|
||||
<span class="identifier">std</span><span class="special">::</span><span class="identifier">pair</span><span class="special"><</span><span class="identifier">iterator</span><span class="special">,</span> <span class="keyword">bool</span><span class="special">></span>
|
||||
<span class="identifier">match_whitespace</span><span class="special">(</span><span class="identifier">iterator</span> <span class="identifier">begin</span><span class="special">,</span> <span class="identifier">iterator</span> <span class="identifier">end</span><span class="special">)</span>
|
||||
<span class="special">{</span>
|
||||
<span class="identifier">iterator</span> <span class="identifier">i</span> <span class="special">=</span> <span class="identifier">begin</span><span class="special">;</span>
|
||||
<span class="keyword">while</span> <span class="special">(</span><span class="identifier">i</span> <span class="special">!=</span> <span class="identifier">end</span><span class="special">)</span>
|
||||
<span class="keyword">if</span> <span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">isspace</span><span class="special">(*</span><span class="identifier">i</span><span class="special">++))</span>
|
||||
<span class="keyword">return</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">make_pair</span><span class="special">(</span><span class="identifier">i</span><span class="special">,</span> <span class="keyword">true</span><span class="special">);</span>
|
||||
<span class="keyword">return</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">make_pair</span><span class="special">(</span><span class="identifier">i</span><span class="special">,</span> <span class="keyword">false</span><span class="special">);</span>
|
||||
<span class="special">}</span>
|
||||
<span class="special">...</span>
|
||||
<span class="identifier">asio</span><span class="special">::</span><span class="identifier">streambuf</span> <span class="identifier">b</span><span class="special">;</span>
|
||||
<span class="identifier">asio</span><span class="special">::</span><span class="identifier">read_until</span><span class="special">(</span><span class="identifier">s</span><span class="special">,</span> <span class="identifier">b</span><span class="special">,</span> <span class="identifier">match_whitespace</span><span class="special">);</span>
|
||||
</pre>
|
||||
<p>
|
||||
To read data into a streambuf until a matching character is found:
|
||||
</p>
|
||||
<pre class="programlisting"><span class="keyword">class</span> <span class="identifier">match_char</span>
|
||||
<span class="special">{</span>
|
||||
<span class="keyword">public</span><span class="special">:</span>
|
||||
<span class="keyword">explicit</span> <span class="identifier">match_char</span><span class="special">(</span><span class="keyword">char</span> <span class="identifier">c</span><span class="special">)</span> <span class="special">:</span> <span class="identifier">c_</span><span class="special">(</span><span class="identifier">c</span><span class="special">)</span> <span class="special">{}</span>
|
||||
|
||||
<span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">Iterator</span><span class="special">></span>
|
||||
<span class="identifier">std</span><span class="special">::</span><span class="identifier">pair</span><span class="special"><</span><span class="identifier">Iterator</span><span class="special">,</span> <span class="keyword">bool</span><span class="special">></span> <span class="keyword">operator</span><span class="special">()(</span>
|
||||
<span class="identifier">Iterator</span> <span class="identifier">begin</span><span class="special">,</span> <span class="identifier">Iterator</span> <span class="identifier">end</span><span class="special">)</span> <span class="keyword">const</span>
|
||||
<span class="special">{</span>
|
||||
<span class="identifier">Iterator</span> <span class="identifier">i</span> <span class="special">=</span> <span class="identifier">begin</span><span class="special">;</span>
|
||||
<span class="keyword">while</span> <span class="special">(</span><span class="identifier">i</span> <span class="special">!=</span> <span class="identifier">end</span><span class="special">)</span>
|
||||
<span class="keyword">if</span> <span class="special">(</span><span class="identifier">c_</span> <span class="special">==</span> <span class="special">*</span><span class="identifier">i</span><span class="special">++)</span>
|
||||
<span class="keyword">return</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">make_pair</span><span class="special">(</span><span class="identifier">i</span><span class="special">,</span> <span class="keyword">true</span><span class="special">);</span>
|
||||
<span class="keyword">return</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">make_pair</span><span class="special">(</span><span class="identifier">i</span><span class="special">,</span> <span class="keyword">false</span><span class="special">);</span>
|
||||
<span class="special">}</span>
|
||||
|
||||
<span class="keyword">private</span><span class="special">:</span>
|
||||
<span class="keyword">char</span> <span class="identifier">c_</span><span class="special">;</span>
|
||||
<span class="special">};</span>
|
||||
|
||||
<span class="keyword">namespace</span> <span class="identifier">asio</span> <span class="special">{</span>
|
||||
<span class="keyword">template</span> <span class="special"><></span> <span class="keyword">struct</span> <span class="identifier">is_match_condition</span><span class="special"><</span><span class="identifier">match_char</span><span class="special">></span>
|
||||
<span class="special">:</span> <span class="keyword">public</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">true_type</span> <span class="special">{};</span>
|
||||
<span class="special">}</span> <span class="comment">// namespace asio</span>
|
||||
<span class="special">...</span>
|
||||
<span class="identifier">asio</span><span class="special">::</span><span class="identifier">streambuf</span> <span class="identifier">b</span><span class="special">;</span>
|
||||
<span class="identifier">asio</span><span class="special">::</span><span class="identifier">read_until</span><span class="special">(</span><span class="identifier">s</span><span class="special">,</span> <span class="identifier">b</span><span class="special">,</span> <span class="identifier">match_char</span><span class="special">(</span><span class="char">'a'</span><span class="special">));</span>
|
||||
</pre>
|
||||
<p>
|
||||
The <code class="computeroutput"><span class="identifier">is_match_condition</span><span class="special"><></span></code> type trait automatically evaluates
|
||||
to true for functions, and for function objects with a nested <code class="computeroutput"><span class="identifier">result_type</span></code> typedef. For other types
|
||||
the trait must be explicitly specialised, as shown above.
|
||||
</p>
|
||||
<h6>
|
||||
<a name="asio.overview.core.line_based.h0"></a>
|
||||
<span><a name="asio.overview.core.line_based.see_also"></a></span><a class="link" href="line_based.html#asio.overview.core.line_based.see_also">See
|
||||
Also</a>
|
||||
</h6>
|
||||
<p>
|
||||
<a class="link" href="../../reference/async_read_until.html" title="async_read_until">async_read_until()</a>,
|
||||
<a class="link" href="../../reference/is_match_condition.html" title="is_match_condition">is_match_condition</a>,
|
||||
<a class="link" href="../../reference/read_until.html" title="read_until">read_until()</a>, <a class="link" href="../../reference/streambuf.html" title="streambuf">streambuf</a>,
|
||||
<a class="link" href="../../examples/cpp03_examples.html#asio.examples.cpp03_examples.http_client">HTTP client example</a>.
|
||||
</p>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"></td>
|
||||
<td align="right"><div class="copyright-footer">Copyright © 2003-2020 Christopher M.
|
||||
Kohlhoff<p>
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
|
||||
</p>
|
||||
</div></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="reactor.html"><img src="../../../prev.png" alt="Prev"></a><a accesskey="u" href="../core.html"><img src="../../../up.png" alt="Up"></a><a accesskey="h" href="../../../index.html"><img src="../../../home.png" alt="Home"></a><a accesskey="n" href="allocation.html"><img src="../../../next.png" alt="Next"></a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,79 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title>Reactor-Style Operations</title>
|
||||
<link rel="stylesheet" href="../../../boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.75.2">
|
||||
<link rel="home" href="../../../index.html" title="Asio">
|
||||
<link rel="up" href="../core.html" title="Core Concepts and Functionality">
|
||||
<link rel="prev" href="streams.html" title="Streams, Short Reads and Short Writes">
|
||||
<link rel="next" href="line_based.html" title="Line-Based Operations">
|
||||
</head>
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
<table cellpadding="2" width="100%"><tr><td valign="top"><img alt="asio C++ library" width="250" height="60" src="../../../asio.png"></td></tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="streams.html"><img src="../../../prev.png" alt="Prev"></a><a accesskey="u" href="../core.html"><img src="../../../up.png" alt="Up"></a><a accesskey="h" href="../../../index.html"><img src="../../../home.png" alt="Home"></a><a accesskey="n" href="line_based.html"><img src="../../../next.png" alt="Next"></a>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="titlepage"><div><div><h4 class="title">
|
||||
<a name="asio.overview.core.reactor"></a><a class="link" href="reactor.html" title="Reactor-Style Operations">Reactor-Style Operations</a>
|
||||
</h4></div></div></div>
|
||||
<p>
|
||||
Sometimes a program must be integrated with a third-party library that
|
||||
wants to perform the I/O operations itself. To facilitate this, Asio includes
|
||||
synchronous and asynchronous operations that may be used to wait for a
|
||||
socket to become ready to read, ready to write, or to have a pending error
|
||||
condition.
|
||||
</p>
|
||||
<p>
|
||||
As an example, to perform a non-blocking read something like the following
|
||||
may be used:
|
||||
</p>
|
||||
<pre class="programlisting"><span class="identifier">ip</span><span class="special">::</span><span class="identifier">tcp</span><span class="special">::</span><span class="identifier">socket</span> <span class="identifier">socket</span><span class="special">(</span><span class="identifier">my_io_context</span><span class="special">);</span>
|
||||
<span class="special">...</span>
|
||||
<span class="identifier">socket</span><span class="special">.</span><span class="identifier">non_blocking</span><span class="special">(</span><span class="keyword">true</span><span class="special">);</span>
|
||||
<span class="special">...</span>
|
||||
<span class="identifier">socket</span><span class="special">.</span><span class="identifier">async_wait</span><span class="special">(</span><span class="identifier">ip</span><span class="special">::</span><span class="identifier">tcp</span><span class="special">::</span><span class="identifier">socket</span><span class="special">::</span><span class="identifier">wait_read</span><span class="special">,</span> <span class="identifier">read_handler</span><span class="special">);</span>
|
||||
<span class="special">...</span>
|
||||
<span class="keyword">void</span> <span class="identifier">read_handler</span><span class="special">(</span><span class="identifier">asio</span><span class="special">::</span><span class="identifier">error_code</span> <span class="identifier">ec</span><span class="special">)</span>
|
||||
<span class="special">{</span>
|
||||
<span class="keyword">if</span> <span class="special">(!</span><span class="identifier">ec</span><span class="special">)</span>
|
||||
<span class="special">{</span>
|
||||
<span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special"><</span><span class="keyword">char</span><span class="special">></span> <span class="identifier">buf</span><span class="special">(</span><span class="identifier">socket</span><span class="special">.</span><span class="identifier">available</span><span class="special">());</span>
|
||||
<span class="identifier">socket</span><span class="special">.</span><span class="identifier">read_some</span><span class="special">(</span><span class="identifier">buffer</span><span class="special">(</span><span class="identifier">buf</span><span class="special">));</span>
|
||||
<span class="special">}</span>
|
||||
<span class="special">}</span>
|
||||
</pre>
|
||||
<p>
|
||||
These operations are supported for sockets on all platforms, and for the
|
||||
POSIX stream-oriented descriptor classes.
|
||||
</p>
|
||||
<h6>
|
||||
<a name="asio.overview.core.reactor.h0"></a>
|
||||
<span><a name="asio.overview.core.reactor.see_also"></a></span><a class="link" href="reactor.html#asio.overview.core.reactor.see_also">See
|
||||
Also</a>
|
||||
</h6>
|
||||
<p>
|
||||
<a class="link" href="../../reference/basic_socket/wait.html" title="basic_socket::wait">basic_socket::wait()</a>,
|
||||
<a class="link" href="../../reference/basic_socket/async_wait.html" title="basic_socket::async_wait">basic_socket::async_wait()</a>,
|
||||
<a class="link" href="../../reference/basic_socket/non_blocking.html" title="basic_socket::non_blocking">basic_socket::non_blocking()</a>,
|
||||
<a class="link" href="../../reference/basic_socket/native_non_blocking.html" title="basic_socket::native_non_blocking">basic_socket::native_non_blocking()</a>,
|
||||
<a class="link" href="../../examples/cpp03_examples.html#asio.examples.cpp03_examples.nonblocking">nonblocking example</a>.
|
||||
</p>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"></td>
|
||||
<td align="right"><div class="copyright-footer">Copyright © 2003-2020 Christopher M.
|
||||
Kohlhoff<p>
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
|
||||
</p>
|
||||
</div></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="streams.html"><img src="../../../prev.png" alt="Prev"></a><a accesskey="u" href="../core.html"><img src="../../../up.png" alt="Up"></a><a accesskey="h" href="../../../index.html"><img src="../../../home.png" alt="Home"></a><a accesskey="n" href="line_based.html"><img src="../../../next.png" alt="Next"></a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,146 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title>Stackful Coroutines</title>
|
||||
<link rel="stylesheet" href="../../../boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.75.2">
|
||||
<link rel="home" href="../../../index.html" title="Asio">
|
||||
<link rel="up" href="../core.html" title="Core Concepts and Functionality">
|
||||
<link rel="prev" href="coroutine.html" title="Stackless Coroutines">
|
||||
<link rel="next" href="coroutines_ts.html" title="Coroutines TS Support">
|
||||
</head>
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
<table cellpadding="2" width="100%"><tr><td valign="top"><img alt="asio C++ library" width="250" height="60" src="../../../asio.png"></td></tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="coroutine.html"><img src="../../../prev.png" alt="Prev"></a><a accesskey="u" href="../core.html"><img src="../../../up.png" alt="Up"></a><a accesskey="h" href="../../../index.html"><img src="../../../home.png" alt="Home"></a><a accesskey="n" href="coroutines_ts.html"><img src="../../../next.png" alt="Next"></a>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="titlepage"><div><div><h4 class="title">
|
||||
<a name="asio.overview.core.spawn"></a><a class="link" href="spawn.html" title="Stackful Coroutines">Stackful Coroutines</a>
|
||||
</h4></div></div></div>
|
||||
<p>
|
||||
The <a class="link" href="../../reference/spawn.html" title="spawn"><code class="computeroutput">spawn()</code></a> function
|
||||
is a high-level wrapper for running stackful coroutines. It is based on
|
||||
the Boost.Coroutine library. The <code class="computeroutput">spawn()</code> function enables
|
||||
programs to implement asynchronous logic in a synchronous manner, as shown
|
||||
in the following example:
|
||||
</p>
|
||||
<pre class="programlisting">asio::spawn(my_strand, do_echo);
|
||||
|
||||
// ...
|
||||
|
||||
void do_echo(asio::yield_context yield)
|
||||
{
|
||||
try
|
||||
{
|
||||
char data[128];
|
||||
for (;;)
|
||||
{
|
||||
std::size_t length =
|
||||
my_socket.async_read_some(
|
||||
asio::buffer(data), yield);
|
||||
|
||||
asio::async_write(my_socket,
|
||||
asio::buffer(data, length), yield);
|
||||
}
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
// ...
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
<p>
|
||||
The first argument to <code class="computeroutput">spawn()</code> may be a <a class="link" href="../../reference/io_context__strand.html" title="io_context::strand"><code class="computeroutput">strand</code></a>,
|
||||
<a class="link" href="../../reference/io_context.html" title="io_context"><code class="computeroutput">io_context</code></a>,
|
||||
or <a class="link" href="../../reference/CompletionHandler.html" title="Completion handler requirements">completion handler</a>.
|
||||
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 <code class="computeroutput">strand</code> so that
|
||||
no explicit synchronisation is required.
|
||||
</p>
|
||||
<p>
|
||||
The second argument is a function object with signature:
|
||||
</p>
|
||||
<pre class="programlisting">void coroutine(asio::yield_context yield);
|
||||
</pre>
|
||||
<p>
|
||||
that specifies the code to be run as part of the coroutine. The parameter
|
||||
<code class="computeroutput">yield</code> may be passed to an asynchronous operation in place
|
||||
of the completion handler, as in:
|
||||
</p>
|
||||
<pre class="programlisting">std::size_t length =
|
||||
my_socket.async_read_some(
|
||||
asio::buffer(data), yield);
|
||||
</pre>
|
||||
<p>
|
||||
This starts the asynchronous operation and suspends the coroutine. The
|
||||
coroutine will be resumed automatically when the asynchronous operation
|
||||
completes.
|
||||
</p>
|
||||
<p>
|
||||
Where an asynchronous operation's handler signature has the form:
|
||||
</p>
|
||||
<pre class="programlisting">void handler(asio::error_code ec, result_type result);
|
||||
</pre>
|
||||
<p>
|
||||
the initiating function returns the result_type. In the <code class="computeroutput">async_read_some</code>
|
||||
example above, this is <code class="computeroutput">size_t</code>. If the asynchronous operation
|
||||
fails, the <code class="computeroutput">error_code</code> is converted into a <code class="computeroutput">system_error</code>
|
||||
exception and thrown.
|
||||
</p>
|
||||
<p>
|
||||
Where a handler signature has the form:
|
||||
</p>
|
||||
<pre class="programlisting">void handler(asio::error_code ec);
|
||||
</pre>
|
||||
<p>
|
||||
the initiating function returns <code class="computeroutput">void</code>. As above, an error is
|
||||
passed back to the coroutine as a <code class="computeroutput">system_error</code> exception.
|
||||
</p>
|
||||
<p>
|
||||
To collect the <code class="computeroutput">error_code</code> from an operation, rather than have
|
||||
it throw an exception, associate the output variable with the <code class="computeroutput">yield_context</code>
|
||||
as follows:
|
||||
</p>
|
||||
<pre class="programlisting">asio::error_code ec;
|
||||
std::size_t length =
|
||||
my_socket.async_read_some(
|
||||
asio::buffer(data), yield[ec]);
|
||||
</pre>
|
||||
<p>
|
||||
<span class="bold"><strong>Note:</strong></span> if <code class="computeroutput">spawn()</code> is used
|
||||
with a custom completion handler of type <code class="computeroutput">Handler</code>, the function
|
||||
object signature is actually:
|
||||
</p>
|
||||
<pre class="programlisting">void coroutine(asio::basic_yield_context<Handler> yield);
|
||||
</pre>
|
||||
<h6>
|
||||
<a name="asio.overview.core.spawn.h0"></a>
|
||||
<span><a name="asio.overview.core.spawn.see_also"></a></span><a class="link" href="spawn.html#asio.overview.core.spawn.see_also">See
|
||||
Also</a>
|
||||
</h6>
|
||||
<p>
|
||||
<a class="link" href="../../reference/spawn.html" title="spawn">spawn</a>, <a class="link" href="../../reference/yield_context.html" title="yield_context">yield_context</a>,
|
||||
<a class="link" href="../../reference/basic_yield_context.html" title="basic_yield_context">basic_yield_context</a>,
|
||||
<a class="link" href="../../examples/cpp03_examples.html#asio.examples.cpp03_examples.spawn">Spawn example (C++03)</a>,
|
||||
<a class="link" href="../../examples/cpp11_examples.html#asio.examples.cpp11_examples.spawn">Spawn example (C++11)</a>,
|
||||
<a class="link" href="coroutine.html" title="Stackless Coroutines">Stackless Coroutines</a>.
|
||||
</p>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"></td>
|
||||
<td align="right"><div class="copyright-footer">Copyright © 2003-2020 Christopher M.
|
||||
Kohlhoff<p>
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
|
||||
</p>
|
||||
</div></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="coroutine.html"><img src="../../../prev.png" alt="Prev"></a><a accesskey="u" href="../core.html"><img src="../../../up.png" alt="Up"></a><a accesskey="h" href="../../../index.html"><img src="../../../home.png" alt="Home"></a><a accesskey="n" href="coroutines_ts.html"><img src="../../../next.png" alt="Next"></a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,161 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title>Strands: Use Threads Without Explicit Locking</title>
|
||||
<link rel="stylesheet" href="../../../boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.75.2">
|
||||
<link rel="home" href="../../../index.html" title="Asio">
|
||||
<link rel="up" href="../core.html" title="Core Concepts and Functionality">
|
||||
<link rel="prev" href="threads.html" title="Threads and Asio">
|
||||
<link rel="next" href="buffers.html" title="Buffers">
|
||||
</head>
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
<table cellpadding="2" width="100%"><tr><td valign="top"><img alt="asio C++ library" width="250" height="60" src="../../../asio.png"></td></tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="threads.html"><img src="../../../prev.png" alt="Prev"></a><a accesskey="u" href="../core.html"><img src="../../../up.png" alt="Up"></a><a accesskey="h" href="../../../index.html"><img src="../../../home.png" alt="Home"></a><a accesskey="n" href="buffers.html"><img src="../../../next.png" alt="Next"></a>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="titlepage"><div><div><h4 class="title">
|
||||
<a name="asio.overview.core.strands"></a><a class="link" href="strands.html" title="Strands: Use Threads Without Explicit Locking">Strands: Use Threads Without
|
||||
Explicit Locking</a>
|
||||
</h4></div></div></div>
|
||||
<p>
|
||||
A strand is defined as a strictly sequential invocation of event handlers
|
||||
(i.e. no concurrent invocation). Use of strands allows execution of code
|
||||
in a multithreaded program without the need for explicit locking (e.g.
|
||||
using mutexes).
|
||||
</p>
|
||||
<p>
|
||||
Strands may be either implicit or explicit, as illustrated by the following
|
||||
alternative approaches:
|
||||
</p>
|
||||
<div class="itemizedlist"><ul class="itemizedlist" type="disc">
|
||||
<li class="listitem">
|
||||
Calling io_context::run() from only one thread means all event handlers
|
||||
execute in an implicit strand, due to the io_context's guarantee that
|
||||
handlers are only invoked from inside run().
|
||||
</li>
|
||||
<li class="listitem">
|
||||
Where there is a single chain of asynchronous operations associated
|
||||
with a connection (e.g. in a half duplex protocol implementation like
|
||||
HTTP) there is no possibility of concurrent execution of the handlers.
|
||||
This is an implicit strand.
|
||||
</li>
|
||||
<li class="listitem">
|
||||
An explicit strand is an instance of <code class="computeroutput"><span class="identifier">strand</span><span class="special"><></span></code> or <code class="computeroutput"><span class="identifier">io_context</span><span class="special">::</span><span class="identifier">strand</span></code>.
|
||||
All event handler function objects need to be bound to the strand using
|
||||
<code class="computeroutput"><span class="identifier">asio</span><span class="special">::</span><span class="identifier">bind_executor</span><span class="special">()</span></code>
|
||||
or otherwise posted/dispatched through the strand object.
|
||||
</li>
|
||||
</ul></div>
|
||||
<p>
|
||||
In the case of composed asynchronous operations, such as <code class="computeroutput"><span class="identifier">async_read</span><span class="special">()</span></code>
|
||||
or <code class="computeroutput"><span class="identifier">async_read_until</span><span class="special">()</span></code>,
|
||||
if a completion handler goes through a strand, then all intermediate handlers
|
||||
should also go through the same strand. This is needed to ensure thread
|
||||
safe access for any objects that are shared between the caller and the
|
||||
composed operation (in the case of <code class="computeroutput"><span class="identifier">async_read</span><span class="special">()</span></code> it's the socket, which the caller can
|
||||
<code class="computeroutput"><span class="identifier">close</span><span class="special">()</span></code>
|
||||
to cancel the operation).
|
||||
</p>
|
||||
<p>
|
||||
To achieve this, all asynchronous operations obtain the handler's associated
|
||||
executor by using the <code class="computeroutput"><span class="identifier">get_associated_executor</span></code>
|
||||
function. For example:
|
||||
</p>
|
||||
<pre class="programlisting"><span class="identifier">asio</span><span class="special">::</span><span class="identifier">associated_executor_t</span><span class="special"><</span><span class="identifier">Handler</span><span class="special">></span> <span class="identifier">a</span> <span class="special">=</span> <span class="identifier">asio</span><span class="special">::</span><span class="identifier">get_associated_executor</span><span class="special">(</span><span class="identifier">h</span><span class="special">);</span>
|
||||
</pre>
|
||||
<p>
|
||||
The associated executor must satisfy the Executor requirements. It will
|
||||
be used by the asynchronous operation to submit both intermediate and final
|
||||
handlers for execution.
|
||||
</p>
|
||||
<p>
|
||||
The executor may be customised for a particular handler type by specifying
|
||||
a nested type <code class="computeroutput"><span class="identifier">executor_type</span></code>
|
||||
and member function <code class="computeroutput"><span class="identifier">get_executor</span><span class="special">()</span></code>:
|
||||
</p>
|
||||
<pre class="programlisting"><span class="keyword">class</span> <span class="identifier">my_handler</span>
|
||||
<span class="special">{</span>
|
||||
<span class="keyword">public</span><span class="special">:</span>
|
||||
<span class="comment">// Custom implementation of Executor type requirements.</span>
|
||||
<span class="keyword">typedef</span> <span class="identifier">my_executor</span> <span class="identifier">executor_type</span><span class="special">;</span>
|
||||
|
||||
<span class="comment">// Return a custom executor implementation.</span>
|
||||
<span class="identifier">executor_type</span> <span class="identifier">get_executor</span><span class="special">()</span> <span class="keyword">const</span> <span class="keyword">noexcept</span>
|
||||
<span class="special">{</span>
|
||||
<span class="keyword">return</span> <span class="identifier">my_executor</span><span class="special">();</span>
|
||||
<span class="special">}</span>
|
||||
|
||||
<span class="keyword">void</span> <span class="keyword">operator</span><span class="special">()()</span> <span class="special">{</span> <span class="special">...</span> <span class="special">}</span>
|
||||
<span class="special">};</span>
|
||||
</pre>
|
||||
<p>
|
||||
In more complex cases, the <code class="computeroutput"><span class="identifier">associated_executor</span></code>
|
||||
template may be partially specialised directly:
|
||||
</p>
|
||||
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">my_handler</span>
|
||||
<span class="special">{</span>
|
||||
<span class="keyword">void</span> <span class="keyword">operator</span><span class="special">()()</span> <span class="special">{</span> <span class="special">...</span> <span class="special">}</span>
|
||||
<span class="special">};</span>
|
||||
|
||||
<span class="keyword">namespace</span> <span class="identifier">asio</span> <span class="special">{</span>
|
||||
|
||||
<span class="keyword">template</span> <span class="special"><</span><span class="keyword">class</span> <span class="identifier">Executor</span><span class="special">></span>
|
||||
<span class="keyword">struct</span> <span class="identifier">associated_executor</span><span class="special"><</span><span class="identifier">my_handler</span><span class="special">,</span> <span class="identifier">Executor</span><span class="special">></span>
|
||||
<span class="special">{</span>
|
||||
<span class="comment">// Custom implementation of Executor type requirements.</span>
|
||||
<span class="keyword">typedef</span> <span class="identifier">my_executor</span> <span class="identifier">type</span><span class="special">;</span>
|
||||
|
||||
<span class="comment">// Return a custom executor implementation.</span>
|
||||
<span class="keyword">static</span> <span class="identifier">type</span> <span class="identifier">get</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">my_handler</span><span class="special">&,</span>
|
||||
<span class="keyword">const</span> <span class="identifier">Executor</span><span class="special">&</span> <span class="special">=</span> <span class="identifier">Executor</span><span class="special">())</span> <span class="keyword">noexcept</span>
|
||||
<span class="special">{</span>
|
||||
<span class="keyword">return</span> <span class="identifier">my_executor</span><span class="special">();</span>
|
||||
<span class="special">}</span>
|
||||
<span class="special">};</span>
|
||||
|
||||
<span class="special">}</span> <span class="comment">// namespace asio</span>
|
||||
</pre>
|
||||
<p>
|
||||
The <code class="computeroutput"><span class="identifier">asio</span><span class="special">::</span><span class="identifier">bind_executor</span><span class="special">()</span></code>
|
||||
function is a helper to bind a specific executor object, such as a strand,
|
||||
to a completion handler. This binding automatically associates an executor
|
||||
as shown above. For example, to bind a strand to a completion handler we
|
||||
would simply write:
|
||||
</p>
|
||||
<pre class="programlisting"><span class="identifier">my_socket</span><span class="special">.</span><span class="identifier">async_read_some</span><span class="special">(</span><span class="identifier">my_buffer</span><span class="special">,</span>
|
||||
<span class="identifier">asio</span><span class="special">::</span><span class="identifier">bind_executor</span><span class="special">(</span><span class="identifier">my_strand</span><span class="special">,</span>
|
||||
<span class="special">[](</span><span class="identifier">error_code</span> <span class="identifier">ec</span><span class="special">,</span> <span class="identifier">size_t</span> <span class="identifier">length</span><span class="special">)</span>
|
||||
<span class="special">{</span>
|
||||
<span class="comment">// ...</span>
|
||||
<span class="special">}));</span>
|
||||
</pre>
|
||||
<h6>
|
||||
<a name="asio.overview.core.strands.h0"></a>
|
||||
<span><a name="asio.overview.core.strands.see_also"></a></span><a class="link" href="strands.html#asio.overview.core.strands.see_also">See
|
||||
Also</a>
|
||||
</h6>
|
||||
<p>
|
||||
<a class="link" href="../../reference/associated_executor.html" title="associated_executor">associated_executor</a>,
|
||||
<a class="link" href="../../reference/get_associated_executor.html" title="get_associated_executor">get_associated_executor</a>,
|
||||
<a class="link" href="../../reference/bind_executor.html" title="bind_executor">bind_executor</a>, <a class="link" href="../../reference/strand.html" title="strand">strand</a>, <a class="link" href="../../reference/io_context__strand.html" title="io_context::strand">io_context::strand</a>,
|
||||
<a class="link" href="../../tutorial/tuttimer5.html" title="Timer.5 - Synchronising handlers in multithreaded programs">tutorial Timer.5</a>, <a class="link" href="../../examples/cpp03_examples.html#asio.examples.cpp03_examples.http_server_3">HTTP server 3 example</a>.
|
||||
</p>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"></td>
|
||||
<td align="right"><div class="copyright-footer">Copyright © 2003-2020 Christopher M.
|
||||
Kohlhoff<p>
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
|
||||
</p>
|
||||
</div></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="threads.html"><img src="../../../prev.png" alt="Prev"></a><a accesskey="u" href="../core.html"><img src="../../../up.png" alt="Up"></a><a accesskey="h" href="../../../index.html"><img src="../../../home.png" alt="Home"></a><a accesskey="n" href="buffers.html"><img src="../../../next.png" alt="Next"></a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,121 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title>Streams, Short Reads and Short Writes</title>
|
||||
<link rel="stylesheet" href="../../../boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.75.2">
|
||||
<link rel="home" href="../../../index.html" title="Asio">
|
||||
<link rel="up" href="../core.html" title="Core Concepts and Functionality">
|
||||
<link rel="prev" href="buffers.html" title="Buffers">
|
||||
<link rel="next" href="reactor.html" title="Reactor-Style Operations">
|
||||
</head>
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
<table cellpadding="2" width="100%"><tr><td valign="top"><img alt="asio C++ library" width="250" height="60" src="../../../asio.png"></td></tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="buffers.html"><img src="../../../prev.png" alt="Prev"></a><a accesskey="u" href="../core.html"><img src="../../../up.png" alt="Up"></a><a accesskey="h" href="../../../index.html"><img src="../../../home.png" alt="Home"></a><a accesskey="n" href="reactor.html"><img src="../../../next.png" alt="Next"></a>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="titlepage"><div><div><h4 class="title">
|
||||
<a name="asio.overview.core.streams"></a><a class="link" href="streams.html" title="Streams, Short Reads and Short Writes">Streams, Short Reads and
|
||||
Short Writes</a>
|
||||
</h4></div></div></div>
|
||||
<p>
|
||||
Many I/O objects in Asio are stream-oriented. This means that:
|
||||
</p>
|
||||
<div class="itemizedlist"><ul class="itemizedlist" type="disc">
|
||||
<li class="listitem">
|
||||
There are no message boundaries. The data being transferred is a continuous
|
||||
sequence of bytes.
|
||||
</li>
|
||||
<li class="listitem">
|
||||
Read or write operations may transfer fewer bytes than requested. This
|
||||
is referred to as a short read or short write.
|
||||
</li>
|
||||
</ul></div>
|
||||
<p>
|
||||
Objects that provide stream-oriented I/O model one or more of the following
|
||||
type requirements:
|
||||
</p>
|
||||
<div class="itemizedlist"><ul class="itemizedlist" type="disc">
|
||||
<li class="listitem">
|
||||
<code class="computeroutput"><span class="identifier">SyncReadStream</span></code>, where
|
||||
synchronous read operations are performed using a member function called
|
||||
<code class="computeroutput"><span class="identifier">read_some</span><span class="special">()</span></code>.
|
||||
</li>
|
||||
<li class="listitem">
|
||||
<code class="computeroutput"><span class="identifier">AsyncReadStream</span></code>, where
|
||||
asynchronous read operations are performed using a member function
|
||||
called <code class="computeroutput"><span class="identifier">async_read_some</span><span class="special">()</span></code>.
|
||||
</li>
|
||||
<li class="listitem">
|
||||
<code class="computeroutput"><span class="identifier">SyncWriteStream</span></code>, where
|
||||
synchronous write operations are performed using a member function
|
||||
called <code class="computeroutput"><span class="identifier">write_some</span><span class="special">()</span></code>.
|
||||
</li>
|
||||
<li class="listitem">
|
||||
<code class="computeroutput"><span class="identifier">AsyncWriteStream</span></code>, where
|
||||
asynchronous write operations are performed using a member function
|
||||
called <code class="computeroutput"><span class="identifier">async_write_some</span><span class="special">()</span></code>.
|
||||
</li>
|
||||
</ul></div>
|
||||
<p>
|
||||
Examples of stream-oriented I/O objects include <code class="computeroutput"><span class="identifier">ip</span><span class="special">::</span><span class="identifier">tcp</span><span class="special">::</span><span class="identifier">socket</span></code>,
|
||||
<code class="computeroutput"><span class="identifier">ssl</span><span class="special">::</span><span class="identifier">stream</span><span class="special"><></span></code>,
|
||||
<code class="computeroutput"><span class="identifier">posix</span><span class="special">::</span><span class="identifier">stream_descriptor</span></code>, <code class="computeroutput"><span class="identifier">windows</span><span class="special">::</span><span class="identifier">stream_handle</span></code>,
|
||||
etc.
|
||||
</p>
|
||||
<p>
|
||||
Programs typically want to transfer an exact number of bytes. When a short
|
||||
read or short write occurs the program must restart the operation, and
|
||||
continue to do so until the required number of bytes has been transferred.
|
||||
Asio provides generic functions that do this automatically: <code class="computeroutput"><span class="identifier">read</span><span class="special">()</span></code>,
|
||||
<code class="computeroutput"><span class="identifier">async_read</span><span class="special">()</span></code>,
|
||||
<code class="computeroutput"><span class="identifier">write</span><span class="special">()</span></code>
|
||||
and <code class="computeroutput"><span class="identifier">async_write</span><span class="special">()</span></code>.
|
||||
</p>
|
||||
<h6>
|
||||
<a name="asio.overview.core.streams.h0"></a>
|
||||
<span><a name="asio.overview.core.streams.why_eof_is_an_error"></a></span><a class="link" href="streams.html#asio.overview.core.streams.why_eof_is_an_error">Why
|
||||
EOF is an Error</a>
|
||||
</h6>
|
||||
<div class="itemizedlist"><ul class="itemizedlist" type="disc">
|
||||
<li class="listitem">
|
||||
The end of a stream can cause <code class="computeroutput"><span class="identifier">read</span></code>,
|
||||
<code class="computeroutput"><span class="identifier">async_read</span></code>, <code class="computeroutput"><span class="identifier">read_until</span></code> or <code class="computeroutput"><span class="identifier">async_read_until</span></code>
|
||||
functions to violate their contract. E.g. a read of N bytes may finish
|
||||
early due to EOF.
|
||||
</li>
|
||||
<li class="listitem">
|
||||
An EOF error may be used to distinguish the end of a stream from a
|
||||
successful read of size 0.
|
||||
</li>
|
||||
</ul></div>
|
||||
<h6>
|
||||
<a name="asio.overview.core.streams.h1"></a>
|
||||
<span><a name="asio.overview.core.streams.see_also"></a></span><a class="link" href="streams.html#asio.overview.core.streams.see_also">See
|
||||
Also</a>
|
||||
</h6>
|
||||
<p>
|
||||
<a class="link" href="../../reference/async_read.html" title="async_read">async_read()</a>, <a class="link" href="../../reference/async_write.html" title="async_write">async_write()</a>,
|
||||
<a class="link" href="../../reference/read.html" title="read">read()</a>, <a class="link" href="../../reference/write.html" title="write">write()</a>,
|
||||
<a class="link" href="../../reference/AsyncReadStream.html" title="Buffer-oriented asynchronous read stream requirements">AsyncReadStream</a>,
|
||||
<a class="link" href="../../reference/AsyncWriteStream.html" title="Buffer-oriented asynchronous write stream requirements">AsyncWriteStream</a>,
|
||||
<a class="link" href="../../reference/SyncReadStream.html" title="Buffer-oriented synchronous read stream requirements">SyncReadStream</a>, <a class="link" href="../../reference/SyncWriteStream.html" title="Buffer-oriented synchronous write stream requirements">SyncWriteStream</a>.
|
||||
</p>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"></td>
|
||||
<td align="right"><div class="copyright-footer">Copyright © 2003-2020 Christopher M.
|
||||
Kohlhoff<p>
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
|
||||
</p>
|
||||
</div></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="buffers.html"><img src="../../../prev.png" alt="Prev"></a><a accesskey="u" href="../core.html"><img src="../../../up.png" alt="Up"></a><a accesskey="h" href="../../../index.html"><img src="../../../home.png" alt="Home"></a><a accesskey="n" href="reactor.html"><img src="../../../next.png" alt="Next"></a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,124 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title>Threads and Asio</title>
|
||||
<link rel="stylesheet" href="../../../boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.75.2">
|
||||
<link rel="home" href="../../../index.html" title="Asio">
|
||||
<link rel="up" href="../core.html" title="Core Concepts and Functionality">
|
||||
<link rel="prev" href="async.html" title="The Proactor Design Pattern: Concurrency Without Threads">
|
||||
<link rel="next" href="strands.html" title="Strands: Use Threads Without Explicit Locking">
|
||||
</head>
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
<table cellpadding="2" width="100%"><tr><td valign="top"><img alt="asio C++ library" width="250" height="60" src="../../../asio.png"></td></tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="async.html"><img src="../../../prev.png" alt="Prev"></a><a accesskey="u" href="../core.html"><img src="../../../up.png" alt="Up"></a><a accesskey="h" href="../../../index.html"><img src="../../../home.png" alt="Home"></a><a accesskey="n" href="strands.html"><img src="../../../next.png" alt="Next"></a>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="titlepage"><div><div><h4 class="title">
|
||||
<a name="asio.overview.core.threads"></a><a class="link" href="threads.html" title="Threads and Asio">Threads and Asio</a>
|
||||
</h4></div></div></div>
|
||||
<h6>
|
||||
<a name="asio.overview.core.threads.h0"></a>
|
||||
<span><a name="asio.overview.core.threads.thread_safety"></a></span><a class="link" href="threads.html#asio.overview.core.threads.thread_safety">Thread
|
||||
Safety</a>
|
||||
</h6>
|
||||
<p>
|
||||
In general, it is safe to make concurrent use of distinct objects, but
|
||||
unsafe to make concurrent use of a single object. However, types such as
|
||||
<code class="computeroutput"><span class="identifier">io_context</span></code> provide a stronger
|
||||
guarantee that it is safe to use a single object concurrently.
|
||||
</p>
|
||||
<h6>
|
||||
<a name="asio.overview.core.threads.h1"></a>
|
||||
<span><a name="asio.overview.core.threads.thread_pools"></a></span><a class="link" href="threads.html#asio.overview.core.threads.thread_pools">Thread
|
||||
Pools</a>
|
||||
</h6>
|
||||
<p>
|
||||
Multiple threads may call <code class="computeroutput"><span class="identifier">io_context</span><span class="special">::</span><span class="identifier">run</span><span class="special">()</span></code> to set up a pool of threads from which
|
||||
completion handlers may be invoked. This approach may also be used with
|
||||
<code class="computeroutput"><span class="identifier">post</span><span class="special">()</span></code>
|
||||
as a means to perform arbitrary computational tasks across a thread pool.
|
||||
</p>
|
||||
<p>
|
||||
Note that all threads that have joined an <code class="computeroutput"><span class="identifier">io_context</span></code>'s
|
||||
pool are considered equivalent, and the <code class="computeroutput"><span class="identifier">io_context</span></code>
|
||||
may distribute work across them in an arbitrary fashion.
|
||||
</p>
|
||||
<h6>
|
||||
<a name="asio.overview.core.threads.h2"></a>
|
||||
<span><a name="asio.overview.core.threads.internal_threads"></a></span><a class="link" href="threads.html#asio.overview.core.threads.internal_threads">Internal
|
||||
Threads</a>
|
||||
</h6>
|
||||
<p>
|
||||
The implementation of this library for a particular platform may make use
|
||||
of one or more internal threads to emulate asynchronicity. As far as possible,
|
||||
these threads must be invisible to the library user. In particular, the
|
||||
threads:
|
||||
</p>
|
||||
<div class="itemizedlist"><ul class="itemizedlist" type="disc">
|
||||
<li class="listitem">
|
||||
must not call the user's code directly; and
|
||||
</li>
|
||||
<li class="listitem">
|
||||
must block all signals.
|
||||
</li>
|
||||
</ul></div>
|
||||
<p>
|
||||
This approach is complemented by the following guarantee:
|
||||
</p>
|
||||
<div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem">
|
||||
Asynchronous completion handlers will only be called from threads that
|
||||
are currently calling <code class="computeroutput"><span class="identifier">io_context</span><span class="special">::</span><span class="identifier">run</span><span class="special">()</span></code>.
|
||||
</li></ul></div>
|
||||
<p>
|
||||
Consequently, it is the library user's responsibility to create and manage
|
||||
all threads to which the notifications will be delivered.
|
||||
</p>
|
||||
<p>
|
||||
The reasons for this approach include:
|
||||
</p>
|
||||
<div class="itemizedlist"><ul class="itemizedlist" type="disc">
|
||||
<li class="listitem">
|
||||
By only calling <code class="computeroutput"><span class="identifier">io_context</span><span class="special">::</span><span class="identifier">run</span><span class="special">()</span></code> from a single thread, the user's
|
||||
code can avoid the development complexity associated with synchronisation.
|
||||
For example, a library user can implement scalable servers that are
|
||||
single-threaded (from the user's point of view).
|
||||
</li>
|
||||
<li class="listitem">
|
||||
A library user may need to perform initialisation in a thread shortly
|
||||
after the thread starts and before any other application code is executed.
|
||||
For example, users of Microsoft's COM must call <code class="computeroutput"><span class="identifier">CoInitializeEx</span></code>
|
||||
before any other COM operations can be called from that thread.
|
||||
</li>
|
||||
<li class="listitem">
|
||||
The library interface is decoupled from interfaces for thread creation
|
||||
and management, and permits implementations on platforms where threads
|
||||
are not available.
|
||||
</li>
|
||||
</ul></div>
|
||||
<h6>
|
||||
<a name="asio.overview.core.threads.h3"></a>
|
||||
<span><a name="asio.overview.core.threads.see_also"></a></span><a class="link" href="threads.html#asio.overview.core.threads.see_also">See
|
||||
Also</a>
|
||||
</h6>
|
||||
<p>
|
||||
<a class="link" href="../../reference/io_context.html" title="io_context">io_context</a>, <a class="link" href="../../reference/post.html" title="post">post</a>.
|
||||
</p>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"></td>
|
||||
<td align="right"><div class="copyright-footer">Copyright © 2003-2020 Christopher M.
|
||||
Kohlhoff<p>
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
|
||||
</p>
|
||||
</div></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="async.html"><img src="../../../prev.png" alt="Prev"></a><a accesskey="u" href="../core.html"><img src="../../../up.png" alt="Up"></a><a accesskey="h" href="../../../index.html"><img src="../../../home.png" alt="Home"></a><a accesskey="n" href="strands.html"><img src="../../../next.png" alt="Next"></a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
Reference in new issue
Block a user