1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
|
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Timer.3 - Binding arguments to a handler</title>
<link rel="stylesheet" href="../../../../doc/src/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
<link rel="home" href="../../boost_asio.html" title="Boost.Asio">
<link rel="up" href="../tutorial.html" title="Tutorial">
<link rel="prev" href="tuttimer2/src.html" title="Source listing for Timer.2">
<link rel="next" href="tuttimer3/src.html" title="Source listing for Timer.3">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../boost.png"></td>
<td align="center"><a href="../../../../index.html">Home</a></td>
<td align="center"><a href="../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="tuttimer2/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="tuttimer3/src.html"><img src="../../../../doc/src/images/next.png" alt="Next"></a>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="boost_asio.tutorial.tuttimer3"></a><a class="link" href="tuttimer3.html" title="Timer.3 - Binding arguments to a handler">Timer.3 - Binding arguments
to a handler</a>
</h3></div></div></div>
<p>
In this tutorial we will modify the program from tutorial Timer.2 so that
the timer fires once a second. This will show how to pass additional parameters
to your handler function.
</p>
<pre class="programlisting">#include <iostream>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
</pre>
<p>
To implement a repeating timer using asio you need to change the timer's
expiry time in your callback function, and to then start a new asynchronous
wait. Obviously this means that the callback function will need to be able
to access the timer object. To this end we add two new parameters to the
<code class="computeroutput">print</code> function:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
A pointer to a timer object.
</li>
<li class="listitem">
A counter so that we can stop the program when the timer fires for the
sixth time.
</li>
</ul></div>
<pre class="programlisting">void print(const boost::system::error_code& /*e*/,
boost::asio::steady_timer* t, int* count)
{
</pre>
<p>
As mentioned above, this tutorial program uses a counter to stop running
when the timer fires for the sixth time. However you will observe that there
is no explicit call to ask the io_context to stop. Recall that in tutorial
Timer.2 we learnt that the <a class="link" href="../reference/io_context/run.html" title="io_context::run">io_context::run()</a>
function completes when there is no more "work" to do. By not starting
a new asynchronous wait on the timer when <code class="computeroutput">count</code> reaches 5, the
io_context will run out of work and stop running.
</p>
<pre class="programlisting"> if (*count < 5)
{
std::cout << *count << std::endl;
++(*count);
</pre>
<p>
Next we move the expiry time for the timer along by one second from the previous
expiry time. By calculating the new expiry time relative to the old, we can
ensure that the timer does not drift away from the whole-second mark due
to any delays in processing the handler.
</p>
<pre class="programlisting"> t->expires_at(t->expiry() + boost::asio::chrono::seconds(1));
</pre>
<p>
Then we start a new asynchronous wait on the timer. As you can see, the boost::bind()
function is used to associate the extra parameters with your callback handler.
The <a class="link" href="../reference/basic_waitable_timer/async_wait.html" title="basic_waitable_timer::async_wait">steady_timer::async_wait()</a>
function expects a handler function (or function object) with the signature
<code class="computeroutput">void(const boost::system::error_code&)</code>. Binding the additional
parameters converts your <code class="computeroutput">print</code> function into a function object
that matches the signature correctly.
</p>
<p>
See the <a href="http://www.boost.org/libs/bind/bind.html" target="_top">Boost.Bind
documentation</a> for more information on how to use boost::bind().
</p>
<p>
In this example, the boost::asio::placeholders::error argument to boost::bind()
is a named placeholder for the error object passed to the handler. When initiating
the asynchronous operation, and if using boost::bind(), you must specify
only the arguments that match the handler's parameter list. In tutorial Timer.4
you will see that this placeholder may be elided if the parameter is not
needed by the callback handler.
</p>
<pre class="programlisting"> t->async_wait(boost::bind(print,
boost::asio::placeholders::error, t, count));
}
}
int main()
{
boost::asio::io_context io;
</pre>
<p>
A new <code class="computeroutput">count</code> variable is added so that we can stop the program
when the timer fires for the sixth time.
</p>
<pre class="programlisting"> int count = 0;
boost::asio::steady_timer t(io, boost::asio::chrono::seconds(1));
</pre>
<p>
As in Step 4, when making the call to <a class="link" href="../reference/basic_waitable_timer/async_wait.html" title="basic_waitable_timer::async_wait">steady_timer::async_wait()</a>
from <code class="computeroutput">main</code> we bind the additional parameters needed for the
<code class="computeroutput">print</code> function.
</p>
<pre class="programlisting"> t.async_wait(boost::bind(print,
boost::asio::placeholders::error, &t, &count));
io.run();
</pre>
<p>
Finally, just to prove that the <code class="computeroutput">count</code> variable was being used
in the <code class="computeroutput">print</code> handler function, we will print out its new value.
</p>
<pre class="programlisting"> std::cout << "Final count is " << count << std::endl;
return 0;
}
</pre>
<p>
See the <a class="link" href="tuttimer3/src.html" title="Source listing for Timer.3">full source listing</a>
</p>
<p>
Return to the <a class="link" href="../tutorial.html" title="Tutorial">tutorial index</a>
</p>
<p>
Previous: <a class="link" href="tuttimer2.html" title="Timer.2 - Using a timer asynchronously">Timer.2 - Using a
timer asynchronously</a>
</p>
<p>
Next: <a class="link" href="tuttimer4.html" title="Timer.4 - Using a member function as a handler">Timer.4 - Using a member
function as a handler</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-2018 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="tuttimer2/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="tuttimer3/src.html"><img src="../../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>
|