• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1<html>
2<head>
3<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
4<title>Timer.5 - Synchronising handlers in multithreaded programs</title>
5<link rel="stylesheet" href="../../../../doc/src/boostbook.css" type="text/css">
6<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
7<link rel="home" href="../../boost_asio.html" title="Boost.Asio">
8<link rel="up" href="../tutorial.html" title="Tutorial">
9<link rel="prev" href="tuttimer4/src.html" title="Source listing for Timer.4">
10<link rel="next" href="tuttimer5/src.html" title="Source listing for Timer.5">
11</head>
12<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
13<table cellpadding="2" width="100%"><tr>
14<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../boost.png"></td>
15<td align="center"><a href="../../../../index.html">Home</a></td>
16<td align="center"><a href="../../../../libs/libraries.htm">Libraries</a></td>
17<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
18<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
19<td align="center"><a href="../../../../more/index.htm">More</a></td>
20</tr></table>
21<hr>
22<div class="spirit-nav">
23<a accesskey="p" href="tuttimer4/src.html"><img src="../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../tutorial.html"><img src="../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../boost_asio.html"><img src="../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="tuttimer5/src.html"><img src="../../../../doc/src/images/next.png" alt="Next"></a>
24</div>
25<div class="section">
26<div class="titlepage"><div><div><h3 class="title">
27<a name="boost_asio.tutorial.tuttimer5"></a><a class="link" href="tuttimer5.html" title="Timer.5 - Synchronising handlers in multithreaded programs">Timer.5 - Synchronising
28      handlers in multithreaded programs</a>
29</h3></div></div></div>
30<p>
31        This tutorial demonstrates the use of the <a class="link" href="../reference/strand.html" title="strand">strand</a>
32        class template to synchronise callback handlers in a multithreaded program.
33      </p>
34<p>
35        The previous four tutorials avoided the issue of handler synchronisation
36        by calling the <a class="link" href="../reference/io_context/run.html" title="io_context::run">io_context::run()</a>
37        function from one thread only. As you already know, the asio library provides
38        a guarantee that callback handlers will only be called from threads that
39        are currently calling <a class="link" href="../reference/io_context/run.html" title="io_context::run">io_context::run()</a>.
40        Consequently, calling <a class="link" href="../reference/io_context/run.html" title="io_context::run">io_context::run()</a>
41        from only one thread ensures that callback handlers cannot run concurrently.
42      </p>
43<p>
44        The single threaded approach is usually the best place to start when developing
45        applications using asio. The downside is the limitations it places on programs,
46        particularly servers, including:
47      </p>
48<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
49<li class="listitem">
50            Poor responsiveness when handlers can take a long time to complete.
51          </li>
52<li class="listitem">
53            An inability to scale on multiprocessor systems.
54          </li>
55</ul></div>
56<p>
57        If you find yourself running into these limitations, an alternative approach
58        is to have a pool of threads calling <a class="link" href="../reference/io_context/run.html" title="io_context::run">io_context::run()</a>.
59        However, as this allows handlers to execute concurrently, we need a method
60        of synchronisation when handlers might be accessing a shared, thread-unsafe
61        resource.
62      </p>
63<pre class="programlisting">#include &lt;iostream&gt;
64#include &lt;boost/asio.hpp&gt;
65#include &lt;boost/thread/thread.hpp&gt;
66#include &lt;boost/bind/bind.hpp&gt;
67</pre>
68<p>
69        We start by defining a class called <code class="computeroutput">printer</code>, similar to the
70        class in the previous tutorial. This class will extend the previous tutorial
71        by running two timers in parallel.
72      </p>
73<pre class="programlisting">class printer
74{
75public:
76</pre>
77<p>
78        In addition to initialising a pair of boost::asio::steady_timer members,
79        the constructor initialises the <code class="computeroutput">strand_</code> member, an object of
80        type boost::asio::strand&lt;boost::asio::io_context::executor_type&gt;.
81      </p>
82<p>
83        The <a class="link" href="../reference/strand.html" title="strand">strand</a> class template
84        is an executor adapter that guarantees that, for those handlers that are
85        dispatched through it, an executing handler will be allowed to complete before
86        the next one is started. This is guaranteed irrespective of the number of
87        threads that are calling <a class="link" href="../reference/io_context/run.html" title="io_context::run">io_context::run()</a>.
88        Of course, the handlers may still execute concurrently with other handlers
89        that were not dispatched through an <a class="link" href="../reference/strand.html" title="strand">strand</a>,
90        or were dispatched through a different <a class="link" href="../reference/strand.html" title="strand">strand</a>
91        object.
92      </p>
93<pre class="programlisting">  printer(boost::asio::io_context&amp; io)
94    : strand_(boost::asio::make_strand(io)),
95      timer1_(io, boost::asio::chrono::seconds(1)),
96      timer2_(io, boost::asio::chrono::seconds(1)),
97      count_(0)
98  {
99</pre>
100<p>
101        When initiating the asynchronous operations, each callback handler is "bound"
102        to an boost::asio::strand&lt;boost::asio::io_context::executor_type&gt; object.
103        The boost::asio::bind_executor() function returns a new handler that automatically
104        dispatches its contained handler through the <a class="link" href="../reference/strand.html" title="strand">strand</a>
105        object. By binding the handlers to the same <a class="link" href="../reference/strand.html" title="strand">strand</a>,
106        we are ensuring that they cannot execute concurrently.
107      </p>
108<pre class="programlisting">    timer1_.async_wait(boost::asio::bind_executor(strand_,
109          boost::bind(&amp;printer::print1, this)));
110
111    timer2_.async_wait(boost::asio::bind_executor(strand_,
112          boost::bind(&amp;printer::print2, this)));
113  }
114
115  ~printer()
116  {
117    std::cout &lt;&lt; "Final count is " &lt;&lt; count_ &lt;&lt; std::endl;
118  }
119</pre>
120<p>
121        In a multithreaded program, the handlers for asynchronous operations should
122        be synchronised if they access shared resources. In this tutorial, the shared
123        resources used by the handlers (<code class="computeroutput">print1</code> and <code class="computeroutput">print2</code>)
124        are <code class="computeroutput">std::cout</code> and the <code class="computeroutput">count_</code> data member.
125      </p>
126<pre class="programlisting">  void print1()
127  {
128    if (count_ &lt; 10)
129    {
130      std::cout &lt;&lt; "Timer 1: " &lt;&lt; count_ &lt;&lt; std::endl;
131      ++count_;
132
133      timer1_.expires_at(timer1_.expiry() + boost::asio::chrono::seconds(1));
134
135      timer1_.async_wait(boost::asio::bind_executor(strand_,
136            boost::bind(&amp;printer::print1, this)));
137    }
138  }
139
140  void print2()
141  {
142    if (count_ &lt; 10)
143    {
144      std::cout &lt;&lt; "Timer 2: " &lt;&lt; count_ &lt;&lt; std::endl;
145      ++count_;
146
147      timer2_.expires_at(timer2_.expiry() + boost::asio::chrono::seconds(1));
148
149      timer2_.async_wait(boost::asio::bind_executor(strand_,
150            boost::bind(&amp;printer::print2, this)));
151    }
152  }
153
154private:
155  boost::asio::strand&lt;boost::asio::io_context::executor_type&gt; strand_;
156  boost::asio::steady_timer timer1_;
157  boost::asio::steady_timer timer2_;
158  int count_;
159};
160</pre>
161<p>
162        The <code class="computeroutput">main</code> function now causes <a class="link" href="../reference/io_context/run.html" title="io_context::run">io_context::run()</a>
163        to be called from two threads: the main thread and one additional thread.
164        This is accomplished using an boost::thread object.
165      </p>
166<p>
167        Just as it would with a call from a single thread, concurrent calls to <a class="link" href="../reference/io_context/run.html" title="io_context::run">io_context::run()</a> will
168        continue to execute while there is "work" left to do. The background
169        thread will not exit until all asynchronous operations have completed.
170      </p>
171<pre class="programlisting">int main()
172{
173  boost::asio::io_context io;
174  printer p(io);
175  boost::thread t(boost::bind(&amp;boost::asio::io_context::run, &amp;io));
176  io.run();
177  t.join();
178
179  return 0;
180}
181</pre>
182<p>
183        See the <a class="link" href="tuttimer5/src.html" title="Source listing for Timer.5">full source listing</a>
184      </p>
185<p>
186        Return to the <a class="link" href="../tutorial.html" title="Tutorial">tutorial index</a>
187      </p>
188<p>
189        Previous: <a class="link" href="tuttimer4.html" title="Timer.4 - Using a member function as a handler">Timer.4 - Using a
190        member function as a handler</a>
191      </p>
192</div>
193<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
194<td align="left"></td>
195<td align="right"><div class="copyright-footer">Copyright © 2003-2020 Christopher M.
196      Kohlhoff<p>
197        Distributed under the Boost Software License, Version 1.0. (See accompanying
198        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>)
199      </p>
200</div></td>
201</tr></table>
202<hr>
203<div class="spirit-nav">
204<a accesskey="p" href="tuttimer4/src.html"><img src="../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../tutorial.html"><img src="../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../boost_asio.html"><img src="../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="tuttimer5/src.html"><img src="../../../../doc/src/images/next.png" alt="Next"></a>
205</div>
206</body>
207</html>
208