1//
2// bind_cancellation_slot.cpp
3// ~~~~~~~~~~~~~~~~~~~~~~~~~~
4//
5// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com)
6//
7// Distributed under the Boost Software License, Version 1.0. (See accompanying
8// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9//
10
11// Disable autolinking for unit tests.
12#if !defined(BOOST_ALL_NO_LIB)
13#define BOOST_ALL_NO_LIB 1
14#endif // !defined(BOOST_ALL_NO_LIB)
15
16// Test that header file is self-contained.
17#include <boost/asio/bind_cancellation_slot.hpp>
18
19#include <functional>
20#include <boost/asio/cancellation_signal.hpp>
21#include <boost/asio/io_context.hpp>
22#include <boost/asio/steady_timer.hpp>
23#include "unit_test.hpp"
24
25#if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
26# include <boost/asio/deadline_timer.hpp>
27#else // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
28# include <boost/asio/steady_timer.hpp>
29#endif // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
30
31using namespace boost::asio;
32namespace bindns = std;
33
34#if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
35typedef deadline_timer timer;
36namespace chronons = boost::posix_time;
37#else // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
38typedef steady_timer timer;
39namespace chronons = boost::asio::chrono;
40#endif // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
41
42void increment_on_cancel(int* count, const boost::system::error_code& error)
43{
44 if (error == boost::asio::error::operation_aborted)
45 ++(*count);
46}
47
48void bind_cancellation_slot_to_function_object_test()
49{
50 io_context ioc;
51 cancellation_signal sig;
52
53 int count = 0;
54
55 timer t(ioc, chronons::seconds(5));
56 t.async_wait(
57 token: bind_cancellation_slot(s: sig.slot(),
58 t: bindns::bind(f: &increment_on_cancel,
59 args: &count, args: bindns::placeholders::_1)));
60
61 ioc.poll();
62
63 BOOST_ASIO_CHECK(count == 0);
64
65 sig.emit(type: boost::asio::cancellation_type::all);
66
67 ioc.run();
68
69 BOOST_ASIO_CHECK(count == 1);
70
71 t.async_wait(
72 token: bind_cancellation_slot(s: sig.slot(),
73 t: bind_cancellation_slot(s: sig.slot(),
74 t: bindns::bind(f: &increment_on_cancel,
75 args: &count, args: bindns::placeholders::_1))));
76
77 ioc.restart();
78 ioc.poll();
79
80 BOOST_ASIO_CHECK(count == 1);
81
82 sig.emit(type: boost::asio::cancellation_type::all);
83
84 ioc.run();
85
86 BOOST_ASIO_CHECK(count == 2);
87}
88
89struct incrementer_token_v1
90{
91 explicit incrementer_token_v1(int* c) : count(c) {}
92 int* count;
93};
94
95struct incrementer_handler_v1
96{
97 explicit incrementer_handler_v1(incrementer_token_v1 t) : count(t.count) {}
98
99 void operator()(boost::system::error_code error)
100 {
101 increment_on_cancel(count, error);
102 }
103
104 int* count;
105};
106
107namespace boost {
108namespace asio {
109
110template <>
111class async_result<incrementer_token_v1, void(boost::system::error_code)>
112{
113public:
114 typedef incrementer_handler_v1 completion_handler_type;
115 typedef void return_type;
116 explicit async_result(completion_handler_type&) {}
117 return_type get() {}
118};
119
120} // namespace asio
121} // namespace boost
122
123void bind_cancellation_slot_to_completion_token_v1_test()
124{
125 io_context ioc;
126 cancellation_signal sig;
127
128 int count = 0;
129
130 timer t(ioc, chronons::seconds(5));
131 t.async_wait(
132 token: bind_cancellation_slot(s: sig.slot(),
133 t: incrementer_token_v1(&count)));
134
135 ioc.poll();
136
137 BOOST_ASIO_CHECK(count == 0);
138
139 sig.emit(type: boost::asio::cancellation_type::all);
140
141 ioc.run();
142
143 BOOST_ASIO_CHECK(count == 1);
144}
145
146struct incrementer_token_v2
147{
148 explicit incrementer_token_v2(int* c) : count(c) {}
149 int* count;
150};
151
152namespace boost {
153namespace asio {
154
155template <>
156class async_result<incrementer_token_v2, void(boost::system::error_code)>
157{
158public:
159#if !defined(BOOST_ASIO_HAS_RETURN_TYPE_DEDUCTION)
160 typedef void return_type;
161#endif // !defined(BOOST_ASIO_HAS_RETURN_TYPE_DEDUCTION)
162
163 template <typename Initiation, typename... Args>
164 static void initiate(Initiation initiation,
165 incrementer_token_v2 token, Args&&... args)
166 {
167 initiation(
168 bindns::bind(f: &increment_on_cancel,
169 args&: token.count, args: bindns::placeholders::_1),
170 static_cast<Args&&>(args)...);
171 }
172};
173
174} // namespace asio
175} // namespace boost
176
177void bind_cancellation_slot_to_completion_token_v2_test()
178{
179 io_context ioc;
180 cancellation_signal sig;
181
182 int count = 0;
183
184 timer t(ioc, chronons::seconds(5));
185 t.async_wait(
186 token: bind_cancellation_slot(s: sig.slot(),
187 t: incrementer_token_v2(&count)));
188
189 ioc.poll();
190
191 BOOST_ASIO_CHECK(count == 0);
192
193 sig.emit(type: boost::asio::cancellation_type::all);
194
195 ioc.run();
196
197 BOOST_ASIO_CHECK(count == 1);
198}
199
200BOOST_ASIO_TEST_SUITE
201(
202 "bind_cancellation_slot",
203 BOOST_ASIO_TEST_CASE(bind_cancellation_slot_to_function_object_test)
204 BOOST_ASIO_TEST_CASE(bind_cancellation_slot_to_completion_token_v1_test)
205 BOOST_ASIO_TEST_CASE(bind_cancellation_slot_to_completion_token_v2_test)
206)
207

source code of boost/libs/asio/test/bind_cancellation_slot.cpp