252 lines
26 KiB
HTML
252 lines
26 KiB
HTML
<html>
|
|
<head>
|
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
|
<title>Proposed Standard Executors</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="../index.html" title="Asio">
|
|
<link rel="prev" href="net_ts.html" title="Networking TS compatibility">
|
|
<link rel="next" href="history.html" title="Revision History">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
</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="net_ts.html"><img src="../prev.png" alt="Prev"></a><a accesskey="u" href="../index.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="history.html"><img src="../next.png" alt="Next"></a>
|
|
</div>
|
|
<div class="section">
|
|
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
|
<a name="asio.std_executors"></a><a class="link" href="std_executors.html" title="Proposed Standard Executors">Proposed Standard Executors</a>
|
|
</h2></div></div></div>
|
|
<p>
|
|
Asio provides a complete implementation of the proposed standard executors,
|
|
as described in <a href="http://wg21.link/P0443r13" target="_top">P0443r13</a>, <a href="http://wg21.link/P1348r0" target="_top">P1348r0</a>, and <a href="http://wg21.link/P1393r0" target="_top">P1393r0</a>.
|
|
</p>
|
|
<p>
|
|
Just as with executors under the Networking TS model, a standard executor represents
|
|
a policy as to how, when, and where a piece of code should be executed. Most
|
|
existing code should continue to work with little or no change.
|
|
</p>
|
|
<h4>
|
|
<a name="asio.std_executors.h0"></a>
|
|
<span><a name="asio.std_executors.standard_executor_implementations_in_asio"></a></span><a class="link" href="std_executors.html#asio.std_executors.standard_executor_implementations_in_asio">Standard
|
|
Executor Implementations in Asio</a>
|
|
</h4>
|
|
<p>
|
|
The <a class="link" href="reference/io_context/executor_type.html" title="io_context::executor_type"><code class="computeroutput"><span class="identifier">io_context</span><span class="special">::</span><span class="identifier">executor_type</span></code></a>,
|
|
<a class="link" href="reference/thread_pool/executor_type.html" title="thread_pool::executor_type"><code class="computeroutput"><span class="identifier">thread_pool</span><span class="special">::</span><span class="identifier">executor_type</span></code></a>,
|
|
<a class="link" href="reference/system_executor.html" title="system_executor"><code class="computeroutput"><span class="identifier">system_executor</span></code></a>,
|
|
and <a class="link" href="reference/strand.html" title="strand"><code class="computeroutput"><span class="identifier">strand</span></code></a>
|
|
executors meet the requirements for the proposed standard executors. For compatibility,
|
|
these classes also meet the requirements for the Networking TS model of executors.
|
|
</p>
|
|
<h4>
|
|
<a name="asio.std_executors.h1"></a>
|
|
<span><a name="asio.std_executors.standard_executor_use_in_asio"></a></span><a class="link" href="std_executors.html#asio.std_executors.standard_executor_use_in_asio">Standard
|
|
Executor Use in Asio</a>
|
|
</h4>
|
|
<p>
|
|
All I/O objects such as <a class="link" href="reference/ip__tcp/socket.html" title="ip::tcp::socket"><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></a>,
|
|
asynchronous operations, and utilities including <a class="link" href="reference/dispatch.html" title="dispatch"><code class="computeroutput"><span class="identifier">dispatch</span></code></a>, <a class="link" href="reference/post.html" title="post"><code class="computeroutput"><span class="identifier">post</span></code></a>, <a class="link" href="reference/defer.html" title="defer"><code class="computeroutput"><span class="identifier">defer</span></code></a>, <a class="link" href="reference/get_associated_executor.html" title="get_associated_executor"><code class="computeroutput"><span class="identifier">get_associated_executor</span></code></a>, <a class="link" href="reference/bind_executor.html" title="bind_executor"><code class="computeroutput"><span class="identifier">bind_executor</span></code></a>, <a class="link" href="reference/make_work_guard.html" title="make_work_guard"><code class="computeroutput"><span class="identifier">make_work_guard</span></code></a>, <a class="link" href="reference/spawn.html" title="spawn"><code class="computeroutput"><span class="identifier">spawn</span></code></a>, <a class="link" href="reference/co_spawn.html" title="co_spawn"><code class="computeroutput"><span class="identifier">co_spawn</span></code></a>, <a class="link" href="reference/async_compose.html" title="async_compose"><code class="computeroutput"><span class="identifier">async_compose</span></code></a>, <a class="link" href="reference/use_future.html" title="use_future"><code class="computeroutput"><span class="identifier">use_future</span></code></a>, etc., can interoperate
|
|
with both proposed standard executors, and with Networking TS executors. Asio's
|
|
implementation determines at compile time which model a particular executor
|
|
meets; the proposed standard executor model is used in preference if both are
|
|
detected.
|
|
</p>
|
|
<p>
|
|
Support for the existing Networking TS model of executors can be disabled by
|
|
defining <code class="computeroutput"><span class="identifier">ASIO_NO_TS_EXECUTORS</span></code>.
|
|
</p>
|
|
<h4>
|
|
<a name="asio.std_executors.h2"></a>
|
|
<span><a name="asio.std_executors.polymorphic_i_o_executor"></a></span><a class="link" href="std_executors.html#asio.std_executors.polymorphic_i_o_executor">Polymorphic
|
|
I/O Executor</a>
|
|
</h4>
|
|
<p>
|
|
The <a class="link" href="reference/any_io_executor.html" title="any_io_executor"><code class="computeroutput"><span class="identifier">any_io_executor</span></code></a>
|
|
type alias is the default runtime-polymorphic executor for all I/O objects.
|
|
This type alias points to the <a class="link" href="reference/execution__any_executor.html" title="execution::any_executor"><code class="computeroutput"><span class="identifier">execution</span><span class="special">::</span><span class="identifier">any_executor</span><span class="special"><></span></code></a>
|
|
template with a set of supportable properties specified for use with I/O.
|
|
</p>
|
|
<p>
|
|
This new name may break existing code that directly uses the old polymorphic
|
|
wrapper, <a class="link" href="reference/executor.html" title="executor"><code class="computeroutput"><span class="identifier">executor</span></code></a>.
|
|
If required for backward compatibility, <code class="computeroutput"><span class="identifier">ASIO_USE_TS_EXECUTOR_AS_DEFAULT</span></code>
|
|
can be defined, which changes the <code class="computeroutput"><span class="identifier">any_io_executor</span></code>
|
|
type alias to instead point to the <code class="computeroutput"><span class="identifier">executor</span></code>
|
|
polymorphic wrapper.
|
|
</p>
|
|
<h4>
|
|
<a name="asio.std_executors.h3"></a>
|
|
<span><a name="asio.std_executors.implementing_a_minimal_i_o_executor"></a></span><a class="link" href="std_executors.html#asio.std_executors.implementing_a_minimal_i_o_executor">Implementing
|
|
a Minimal I/O Executor</a>
|
|
</h4>
|
|
<p>
|
|
Standard executor properties make what were previously hard requirements on
|
|
an executor (such as work counting, or the ability to distinguish between
|
|
<code class="computeroutput"><span class="identifier">post</span></code>, <code class="computeroutput"><span class="identifier">dispatch</span></code>,
|
|
and <code class="computeroutput"><span class="identifier">defer</span></code>) into optional facilities.
|
|
With this relaxation, the minimal requirements for an I/O executor are:
|
|
</p>
|
|
<div class="itemizedlist"><ul class="itemizedlist" type="disc">
|
|
<li class="listitem">
|
|
Conformance to the <a class="link" href="reference/Executor1.html#asio.reference.Executor1.standard_executors"><code class="computeroutput"><span class="identifier">executor</span></code></a> concept.
|
|
</li>
|
|
<li class="listitem">
|
|
The ability to query the <a class="link" href="reference/execution__context.html" title="execution::context"><code class="computeroutput"><span class="identifier">execution</span><span class="special">::</span><span class="identifier">context</span></code></a> property, with the result
|
|
being <a class="link" href="reference/execution_context.html" title="execution_context"><code class="computeroutput"><span class="identifier">execution_context</span><span class="special">&</span></code></a> or a reference to a class that
|
|
is derived from <code class="computeroutput"><span class="identifier">execution_context</span></code>.
|
|
</li>
|
|
<li class="listitem">
|
|
The <code class="computeroutput"><span class="identifier">execute</span></code> operation having,
|
|
at minimum, the <a class="link" href="reference/execution__blocking_t/never.html" title="execution::blocking_t::never"><code class="computeroutput"><span class="identifier">execution</span><span class="special">::</span><span class="identifier">blocking</span><span class="special">.</span><span class="identifier">never</span></code></a> semantic.
|
|
</li>
|
|
</ul></div>
|
|
<p>
|
|
The following example shows a minimal I/O executor. Given a queue submission
|
|
operation implemented elsewhere:
|
|
</p>
|
|
<pre class="programlisting"><span class="identifier">queue_t</span> <span class="identifier">queue_create</span><span class="special">();</span>
|
|
<span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">F</span><span class="special">></span> <span class="keyword">void</span> <span class="identifier">queue_submit</span><span class="special">(</span><span class="identifier">queue_t</span> <span class="identifier">q</span><span class="special">,</span> <span class="identifier">F</span> <span class="identifier">f</span><span class="special">);</span>
|
|
</pre>
|
|
<p>
|
|
the executor may be defined as follows:
|
|
</p>
|
|
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">minimal_io_executor</span>
|
|
<span class="special">{</span>
|
|
<span class="identifier">asio</span><span class="special">::</span><span class="identifier">execution_context</span><span class="special">*</span> <span class="identifier">context_</span><span class="special">;</span>
|
|
<span class="identifier">queue_t</span> <span class="identifier">queue_</span><span class="special">;</span>
|
|
|
|
<span class="keyword">bool</span> <span class="keyword">operator</span><span class="special">==(</span><span class="keyword">const</span> <span class="identifier">minimal_io_executor</span><span class="special">&</span> <span class="identifier">other</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">context_</span> <span class="special">==</span> <span class="identifier">other</span><span class="special">.</span><span class="identifier">context_</span> <span class="special">&&</span> <span class="identifier">queue_</span> <span class="special">==</span> <span class="identifier">other</span><span class="special">.</span><span class="identifier">queue_</span><span class="special">;</span>
|
|
<span class="special">}</span>
|
|
|
|
<span class="keyword">bool</span> <span class="keyword">operator</span><span class="special">!=(</span><span class="keyword">const</span> <span class="identifier">minimal_io_executor</span><span class="special">&</span> <span class="identifier">other</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="special">!(*</span><span class="keyword">this</span> <span class="special">==</span> <span class="identifier">other</span><span class="special">);</span>
|
|
<span class="special">}</span>
|
|
|
|
<span class="identifier">asio</span><span class="special">::</span><span class="identifier">execution_context</span><span class="special">&</span> <span class="identifier">query</span><span class="special">(</span>
|
|
<span class="identifier">asio</span><span class="special">::</span><span class="identifier">execution</span><span class="special">::</span><span class="identifier">context_t</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="special">*</span><span class="identifier">context_</span><span class="special">;</span>
|
|
<span class="special">}</span>
|
|
|
|
<span class="keyword">static</span> <span class="keyword">constexpr</span> <span class="identifier">asio</span><span class="special">::</span><span class="identifier">execution</span><span class="special">::</span><span class="identifier">blocking_t</span><span class="special">::</span><span class="identifier">never_t</span> <span class="identifier">query</span><span class="special">(</span>
|
|
<span class="identifier">asio</span><span class="special">::</span><span class="identifier">execution</span><span class="special">::</span><span class="identifier">blocking_t</span><span class="special">)</span> <span class="keyword">noexcept</span>
|
|
<span class="special">{</span>
|
|
<span class="comment">// This executor always has blocking.never semantics.</span>
|
|
<span class="keyword">return</span> <span class="identifier">asio</span><span class="special">::</span><span class="identifier">execution</span><span class="special">::</span><span class="identifier">blocking</span><span class="special">.</span><span class="identifier">never</span><span class="special">;</span>
|
|
<span class="special">}</span>
|
|
|
|
<span class="keyword">template</span> <span class="special"><</span><span class="keyword">class</span> <span class="identifier">F</span><span class="special">></span>
|
|
<span class="keyword">void</span> <span class="identifier">execute</span><span class="special">(</span><span class="identifier">F</span> <span class="identifier">f</span><span class="special">)</span> <span class="keyword">const</span>
|
|
<span class="special">{</span>
|
|
<span class="identifier">queue_submit</span><span class="special">(</span><span class="identifier">queue_</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">move</span><span class="special">(</span><span class="identifier">f</span><span class="special">));</span>
|
|
<span class="special">}</span>
|
|
<span class="special">};</span>
|
|
</pre>
|
|
<p>
|
|
This executor may be created as follows:
|
|
</p>
|
|
<pre class="programlisting"><span class="identifier">asio</span><span class="special">::</span><span class="identifier">execution_context</span> <span class="identifier">context</span><span class="special">;</span>
|
|
<span class="identifier">queue_t</span> <span class="identifier">queue</span> <span class="special">=</span> <span class="identifier">queue_create</span><span class="special">();</span>
|
|
<span class="identifier">minimal_io_executor</span> <span class="identifier">executor</span><span class="special">{&</span><span class="identifier">context</span><span class="special">,</span> <span class="identifier">queue</span><span class="special">};</span>
|
|
</pre>
|
|
<p>
|
|
and then used with I/O objects:
|
|
</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">acceptor</span> <span class="identifier">acceptor</span><span class="special">(</span><span class="identifier">executor</span><span class="special">);</span>
|
|
</pre>
|
|
<p>
|
|
or assigned into the <a class="link" href="reference/any_io_executor.html" title="any_io_executor"><code class="computeroutput"><span class="identifier">any_io_executor</span></code></a> polymorphic wrapper:
|
|
</p>
|
|
<pre class="programlisting"><span class="identifier">asio</span><span class="special">::</span><span class="identifier">any_io_executor</span> <span class="identifier">poly_executor</span> <span class="special">=</span> <span class="identifier">executor</span><span class="special">;</span>
|
|
</pre>
|
|
<h4>
|
|
<a name="asio.std_executors.h4"></a>
|
|
<span><a name="asio.std_executors.traits_for_deducing_conformance_to_the_executor_concept"></a></span><a class="link" href="std_executors.html#asio.std_executors.traits_for_deducing_conformance_to_the_executor_concept">Traits
|
|
for Deducing Conformance to the Executor Concept</a>
|
|
</h4>
|
|
<p>
|
|
Older C++ standards and compilers require some assistance to determine whether
|
|
an executor implementation conforms to the <code class="computeroutput"><span class="identifier">executor</span></code>
|
|
concept and type requirements. This is achieved through specialisation of traits.
|
|
The following code shows a specialisation of these traits for the <code class="computeroutput"><span class="identifier">minimal_io_executor</span></code> example from above:
|
|
</p>
|
|
<pre class="programlisting"><span class="keyword">namespace</span> <span class="identifier">asio</span> <span class="special">{</span>
|
|
<span class="keyword">namespace</span> <span class="identifier">traits</span> <span class="special">{</span>
|
|
|
|
<span class="preprocessor">#if</span> <span class="special">!</span><span class="identifier">defined</span><span class="special">(</span><span class="identifier">ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT</span><span class="special">)</span>
|
|
|
|
<span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">F</span><span class="special">></span>
|
|
<span class="keyword">struct</span> <span class="identifier">execute_member</span><span class="special"><</span><span class="identifier">minimal_io_executor</span><span class="special">,</span> <span class="identifier">F</span><span class="special">></span>
|
|
<span class="special">{</span>
|
|
<span class="keyword">static</span> <span class="keyword">constexpr</span> <span class="keyword">bool</span> <span class="identifier">is_valid</span> <span class="special">=</span> <span class="keyword">true</span><span class="special">;</span>
|
|
<span class="keyword">static</span> <span class="keyword">constexpr</span> <span class="keyword">bool</span> <span class="identifier">is_noexcept</span> <span class="special">=</span> <span class="keyword">true</span><span class="special">;</span>
|
|
<span class="keyword">typedef</span> <span class="keyword">void</span> <span class="identifier">result_type</span><span class="special">;</span>
|
|
<span class="special">};</span>
|
|
|
|
<span class="preprocessor">#endif</span> <span class="comment">// !defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)</span>
|
|
<span class="preprocessor">#if</span> <span class="special">!</span><span class="identifier">defined</span><span class="special">(</span><span class="identifier">ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT</span><span class="special">)</span>
|
|
|
|
<span class="keyword">template</span> <span class="special"><></span>
|
|
<span class="keyword">struct</span> <span class="identifier">equality_comparable</span><span class="special"><</span><span class="identifier">minimal_io_executor</span><span class="special">></span>
|
|
<span class="special">{</span>
|
|
<span class="keyword">static</span> <span class="keyword">constexpr</span> <span class="keyword">bool</span> <span class="identifier">is_valid</span> <span class="special">=</span> <span class="keyword">true</span><span class="special">;</span>
|
|
<span class="keyword">static</span> <span class="keyword">constexpr</span> <span class="keyword">bool</span> <span class="identifier">is_noexcept</span> <span class="special">=</span> <span class="keyword">true</span><span class="special">;</span>
|
|
<span class="special">};</span>
|
|
|
|
<span class="preprocessor">#endif</span> <span class="comment">// !defined(ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)</span>
|
|
<span class="preprocessor">#if</span> <span class="special">!</span><span class="identifier">defined</span><span class="special">(</span><span class="identifier">ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT</span><span class="special">)</span>
|
|
|
|
<span class="keyword">template</span> <span class="special"><></span>
|
|
<span class="keyword">struct</span> <span class="identifier">query_member</span><span class="special"><</span><span class="identifier">minimal_io_executor</span><span class="special">,</span>
|
|
<span class="identifier">asio</span><span class="special">::</span><span class="identifier">execution</span><span class="special">::</span><span class="identifier">context_t</span><span class="special">></span>
|
|
<span class="special">{</span>
|
|
<span class="keyword">static</span> <span class="keyword">constexpr</span> <span class="keyword">bool</span> <span class="identifier">is_valid</span> <span class="special">=</span> <span class="keyword">true</span><span class="special">;</span>
|
|
<span class="keyword">static</span> <span class="keyword">constexpr</span> <span class="keyword">bool</span> <span class="identifier">is_noexcept</span> <span class="special">=</span> <span class="keyword">true</span><span class="special">;</span>
|
|
<span class="keyword">typedef</span> <span class="identifier">asio</span><span class="special">::</span><span class="identifier">execution_context</span><span class="special">&</span> <span class="identifier">result_type</span><span class="special">;</span>
|
|
<span class="special">};</span>
|
|
|
|
<span class="preprocessor">#endif</span> <span class="comment">// !defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)</span>
|
|
<span class="preprocessor">#if</span> <span class="special">!</span><span class="identifier">defined</span><span class="special">(</span><span class="identifier">ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT</span><span class="special">)</span>
|
|
|
|
<span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">Property</span><span class="special">></span>
|
|
<span class="keyword">struct</span> <span class="identifier">query_static_constexpr_member</span><span class="special"><</span><span class="identifier">minimal_io_executor</span><span class="special">,</span> <span class="identifier">Property</span><span class="special">,</span>
|
|
<span class="keyword">typename</span> <span class="identifier">enable_if</span><span class="special"><</span>
|
|
<span class="identifier">std</span><span class="special">::</span><span class="identifier">is_convertible</span><span class="special"><</span><span class="identifier">Property</span><span class="special">,</span> <span class="identifier">asio</span><span class="special">::</span><span class="identifier">execution</span><span class="special">::</span><span class="identifier">blocking_t</span><span class="special">>::</span><span class="identifier">value</span>
|
|
<span class="special">>::</span><span class="identifier">type</span><span class="special">></span>
|
|
<span class="special">{</span>
|
|
<span class="keyword">static</span> <span class="keyword">constexpr</span> <span class="keyword">bool</span> <span class="identifier">is_valid</span> <span class="special">=</span> <span class="keyword">true</span><span class="special">;</span>
|
|
<span class="keyword">static</span> <span class="keyword">constexpr</span> <span class="keyword">bool</span> <span class="identifier">is_noexcept</span> <span class="special">=</span> <span class="keyword">true</span><span class="special">;</span>
|
|
<span class="keyword">typedef</span> <span class="identifier">asio</span><span class="special">::</span><span class="identifier">execution</span><span class="special">::</span><span class="identifier">blocking_t</span><span class="special">::</span><span class="identifier">never_t</span> <span class="identifier">result_type</span><span class="special">;</span>
|
|
<span class="keyword">static</span> <span class="keyword">constexpr</span> <span class="identifier">result_type</span> <span class="identifier">value</span><span class="special">()</span> <span class="keyword">noexcept</span> <span class="special">{</span> <span class="keyword">return</span> <span class="identifier">result_type</span><span class="special">();</span> <span class="special">}</span>
|
|
<span class="special">};</span>
|
|
|
|
<span class="preprocessor">#endif</span> <span class="comment">// !defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)</span>
|
|
|
|
<span class="special">}</span> <span class="comment">// namespace traits</span>
|
|
<span class="special">}</span> <span class="comment">// namespace asio</span>
|
|
</pre>
|
|
<p>
|
|
Asio uses an extensive set of traits to implement all of the proposed standard
|
|
executor functionality on older C++ standards. These traits may be found under
|
|
the <code class="literal">asio/traits</code> include directory.
|
|
</p>
|
|
</div>
|
|
<div class="copyright-footer">Copyright © 2003-2023 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>
|
|
<hr>
|
|
<div class="spirit-nav">
|
|
<a accesskey="p" href="net_ts.html"><img src="../prev.png" alt="Prev"></a><a accesskey="u" href="../index.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="history.html"><img src="../next.png" alt="Next"></a>
|
|
</div>
|
|
</body>
|
|
</html>
|