1//
2// cancellation_signal.hpp
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#ifndef BOOST_ASIO_CANCELLATION_SIGNAL_HPP
12#define BOOST_ASIO_CANCELLATION_SIGNAL_HPP
13
14#if defined(_MSC_VER) && (_MSC_VER >= 1200)
15# pragma once
16#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
17
18#include <boost/asio/detail/config.hpp>
19#include <cassert>
20#include <new>
21#include <utility>
22#include <boost/asio/cancellation_type.hpp>
23#include <boost/asio/detail/cstddef.hpp>
24#include <boost/asio/detail/type_traits.hpp>
25
26#include <boost/asio/detail/push_options.hpp>
27
28namespace boost {
29namespace asio {
30namespace detail {
31
32class cancellation_handler_base
33{
34public:
35 virtual void call(cancellation_type_t) = 0;
36 virtual std::pair<void*, std::size_t> destroy() noexcept = 0;
37
38protected:
39 ~cancellation_handler_base() {}
40};
41
42template <typename Handler>
43class cancellation_handler
44 : public cancellation_handler_base
45{
46public:
47 template <typename... Args>
48 cancellation_handler(std::size_t size, Args&&... args)
49 : handler_(static_cast<Args&&>(args)...),
50 size_(size)
51 {
52 }
53
54 void call(cancellation_type_t type)
55 {
56 handler_(type);
57 }
58
59 std::pair<void*, std::size_t> destroy() noexcept
60 {
61 std::pair<void*, std::size_t> mem(this, size_);
62 this->cancellation_handler::~cancellation_handler();
63 return mem;
64 }
65
66 Handler& handler() noexcept
67 {
68 return handler_;
69 }
70
71private:
72 ~cancellation_handler()
73 {
74 }
75
76 Handler handler_;
77 std::size_t size_;
78};
79
80} // namespace detail
81
82class cancellation_slot;
83
84/// A cancellation signal with a single slot.
85class cancellation_signal
86{
87public:
88 constexpr cancellation_signal()
89 : handler_(0)
90 {
91 }
92
93 BOOST_ASIO_DECL ~cancellation_signal();
94
95 /// Emits the signal and causes invocation of the slot's handler, if any.
96 void emit(cancellation_type_t type)
97 {
98 if (handler_)
99 handler_->call(type);
100 }
101
102 /// Returns the single slot associated with the signal.
103 /**
104 * The signal object must remain valid for as long the slot may be used.
105 * Destruction of the signal invalidates the slot.
106 */
107 cancellation_slot slot() noexcept;
108
109private:
110 cancellation_signal(const cancellation_signal&) = delete;
111 cancellation_signal& operator=(const cancellation_signal&) = delete;
112
113 detail::cancellation_handler_base* handler_;
114};
115
116/// A slot associated with a cancellation signal.
117class cancellation_slot
118{
119public:
120 /// Creates a slot that is not connected to any cancellation signal.
121 constexpr cancellation_slot()
122 : handler_(0)
123 {
124 }
125
126 /// Installs a handler into the slot, constructing the new object directly.
127 /**
128 * Destroys any existing handler in the slot, then installs the new handler,
129 * constructing it with the supplied @c args.
130 *
131 * The handler is a function object to be called when the signal is emitted.
132 * The signature of the handler must be
133 * @code void handler(boost::asio::cancellation_type_t); @endcode
134 *
135 * @param args Arguments to be passed to the @c CancellationHandler object's
136 * constructor.
137 *
138 * @returns A reference to the newly installed handler.
139 *
140 * @note Handlers installed into the slot via @c emplace are not required to
141 * be copy constructible or move constructible.
142 */
143 template <typename CancellationHandler, typename... Args>
144 CancellationHandler& emplace(Args&&... args)
145 {
146 typedef detail::cancellation_handler<CancellationHandler>
147 cancellation_handler_type;
148 auto_delete_helper del = { .mem: prepare_memory(
149 size: sizeof(cancellation_handler_type),
150 align: alignof(CancellationHandler)) };
151 cancellation_handler_type* handler_obj =
152 new (del.mem.first) cancellation_handler_type(
153 del.mem.second, static_cast<Args&&>(args)...);
154 del.mem.first = 0;
155 *handler_ = handler_obj;
156 return handler_obj->handler();
157 }
158
159 /// Installs a handler into the slot.
160 /**
161 * Destroys any existing handler in the slot, then installs the new handler,
162 * constructing it as a decay-copy of the supplied handler.
163 *
164 * The handler is a function object to be called when the signal is emitted.
165 * The signature of the handler must be
166 * @code void handler(boost::asio::cancellation_type_t); @endcode
167 *
168 * @param handler The handler to be installed.
169 *
170 * @returns A reference to the newly installed handler.
171 */
172 template <typename CancellationHandler>
173 decay_t<CancellationHandler>& assign(CancellationHandler&& handler)
174 {
175 return this->emplace<decay_t<CancellationHandler>>(
176 static_cast<CancellationHandler&&>(handler));
177 }
178
179 /// Clears the slot.
180 /**
181 * Destroys any existing handler in the slot.
182 */
183 BOOST_ASIO_DECL void clear();
184
185 /// Returns whether the slot is connected to a signal.
186 constexpr bool is_connected() const noexcept
187 {
188 return handler_ != 0;
189 }
190
191 /// Returns whether the slot is connected and has an installed handler.
192 constexpr bool has_handler() const noexcept
193 {
194 return handler_ != 0 && *handler_ != 0;
195 }
196
197 /// Compare two slots for equality.
198 friend constexpr bool operator==(const cancellation_slot& lhs,
199 const cancellation_slot& rhs) noexcept
200 {
201 return lhs.handler_ == rhs.handler_;
202 }
203
204 /// Compare two slots for inequality.
205 friend constexpr bool operator!=(const cancellation_slot& lhs,
206 const cancellation_slot& rhs) noexcept
207 {
208 return lhs.handler_ != rhs.handler_;
209 }
210
211private:
212 friend class cancellation_signal;
213
214 constexpr cancellation_slot(int,
215 detail::cancellation_handler_base** handler)
216 : handler_(handler)
217 {
218 }
219
220 BOOST_ASIO_DECL std::pair<void*, std::size_t> prepare_memory(
221 std::size_t size, std::size_t align);
222
223 struct auto_delete_helper
224 {
225 std::pair<void*, std::size_t> mem;
226
227 BOOST_ASIO_DECL ~auto_delete_helper();
228 };
229
230 detail::cancellation_handler_base** handler_;
231};
232
233inline cancellation_slot cancellation_signal::slot() noexcept
234{
235 return cancellation_slot(0, &handler_);
236}
237
238} // namespace asio
239} // namespace boost
240
241#include <boost/asio/detail/pop_options.hpp>
242
243#if defined(BOOST_ASIO_HEADER_ONLY)
244# include <boost/asio/impl/cancellation_signal.ipp>
245#endif // defined(BOOST_ASIO_HEADER_ONLY)
246
247#endif // BOOST_ASIO_CANCELLATION_SIGNAL_HPP
248

source code of boost/libs/asio/include/boost/asio/cancellation_signal.hpp