1//
2// executor.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_EXECUTOR_HPP
12#define BOOST_ASIO_EXECUTOR_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
20#if !defined(BOOST_ASIO_NO_TS_EXECUTORS)
21
22#include <new>
23#include <typeinfo>
24#include <boost/asio/detail/cstddef.hpp>
25#include <boost/asio/detail/executor_function.hpp>
26#include <boost/asio/detail/memory.hpp>
27#include <boost/asio/detail/throw_exception.hpp>
28#include <boost/asio/execution_context.hpp>
29
30#include <boost/asio/detail/push_options.hpp>
31
32namespace boost {
33namespace asio {
34
35/// Exception thrown when trying to access an empty polymorphic executor.
36class bad_executor
37 : public std::exception
38{
39public:
40 /// Constructor.
41 BOOST_ASIO_DECL bad_executor() noexcept;
42
43 /// Obtain message associated with exception.
44 BOOST_ASIO_DECL virtual const char* what() const
45 noexcept;
46};
47
48/// Polymorphic wrapper for executors.
49class executor
50{
51public:
52 /// Default constructor.
53 executor() noexcept
54 : impl_(0)
55 {
56 }
57
58 /// Construct from nullptr.
59 executor(nullptr_t) noexcept
60 : impl_(0)
61 {
62 }
63
64 /// Copy constructor.
65 executor(const executor& other) noexcept
66 : impl_(other.clone())
67 {
68 }
69
70 /// Move constructor.
71 executor(executor&& other) noexcept
72 : impl_(other.impl_)
73 {
74 other.impl_ = 0;
75 }
76
77 /// Construct a polymorphic wrapper for the specified executor.
78 template <typename Executor>
79 executor(Executor e);
80
81 /// Construct a polymorphic executor that points to the same target as
82 /// another polymorphic executor.
83 executor(std::nothrow_t, const executor& other) noexcept
84 : impl_(other.clone())
85 {
86 }
87
88 /// Construct a polymorphic executor that moves the target from another
89 /// polymorphic executor.
90 executor(std::nothrow_t, executor&& other) noexcept
91 : impl_(other.impl_)
92 {
93 other.impl_ = 0;
94 }
95
96 /// Construct a polymorphic wrapper for the specified executor.
97 template <typename Executor>
98 executor(std::nothrow_t, Executor e) noexcept;
99
100 /// Allocator-aware constructor to create a polymorphic wrapper for the
101 /// specified executor.
102 template <typename Executor, typename Allocator>
103 executor(allocator_arg_t, const Allocator& a, Executor e);
104
105 /// Destructor.
106 ~executor()
107 {
108 destroy();
109 }
110
111 /// Assignment operator.
112 executor& operator=(const executor& other) noexcept
113 {
114 destroy();
115 impl_ = other.clone();
116 return *this;
117 }
118
119 // Move assignment operator.
120 executor& operator=(executor&& other) noexcept
121 {
122 destroy();
123 impl_ = other.impl_;
124 other.impl_ = 0;
125 return *this;
126 }
127
128 /// Assignment operator for nullptr_t.
129 executor& operator=(nullptr_t) noexcept
130 {
131 destroy();
132 impl_ = 0;
133 return *this;
134 }
135
136 /// Assignment operator to create a polymorphic wrapper for the specified
137 /// executor.
138 template <typename Executor>
139 executor& operator=(Executor&& e) noexcept
140 {
141 executor tmp(static_cast<Executor&&>(e));
142 destroy();
143 impl_ = tmp.impl_;
144 tmp.impl_ = 0;
145 return *this;
146 }
147
148 /// Obtain the underlying execution context.
149 execution_context& context() const noexcept
150 {
151 return get_impl()->context();
152 }
153
154 /// Inform the executor that it has some outstanding work to do.
155 void on_work_started() const noexcept
156 {
157 get_impl()->on_work_started();
158 }
159
160 /// Inform the executor that some work is no longer outstanding.
161 void on_work_finished() const noexcept
162 {
163 get_impl()->on_work_finished();
164 }
165
166 /// Request the executor to invoke the given function object.
167 /**
168 * This function is used to ask the executor to execute the given function
169 * object. The function object is executed according to the rules of the
170 * target executor object.
171 *
172 * @param f The function object to be called. The executor will make a copy
173 * of the handler object as required. The function signature of the function
174 * object must be: @code void function(); @endcode
175 *
176 * @param a An allocator that may be used by the executor to allocate the
177 * internal storage needed for function invocation.
178 */
179 template <typename Function, typename Allocator>
180 void dispatch(Function&& f, const Allocator& a) const;
181
182 /// Request the executor to invoke the given function object.
183 /**
184 * This function is used to ask the executor to execute the given function
185 * object. The function object is executed according to the rules of the
186 * target executor object.
187 *
188 * @param f The function object to be called. The executor will make
189 * a copy of the handler object as required. The function signature of the
190 * function object must be: @code void function(); @endcode
191 *
192 * @param a An allocator that may be used by the executor to allocate the
193 * internal storage needed for function invocation.
194 */
195 template <typename Function, typename Allocator>
196 void post(Function&& f, const Allocator& a) const;
197
198 /// Request the executor to invoke the given function object.
199 /**
200 * This function is used to ask the executor to execute the given function
201 * object. The function object is executed according to the rules of the
202 * target executor object.
203 *
204 * @param f The function object to be called. The executor will make
205 * a copy of the handler object as required. The function signature of the
206 * function object must be: @code void function(); @endcode
207 *
208 * @param a An allocator that may be used by the executor to allocate the
209 * internal storage needed for function invocation.
210 */
211 template <typename Function, typename Allocator>
212 void defer(Function&& f, const Allocator& a) const;
213
214 struct unspecified_bool_type_t {};
215 typedef void (*unspecified_bool_type)(unspecified_bool_type_t);
216 static void unspecified_bool_true(unspecified_bool_type_t) {}
217
218 /// Operator to test if the executor contains a valid target.
219 operator unspecified_bool_type() const noexcept
220 {
221 return impl_ ? &executor::unspecified_bool_true : 0;
222 }
223
224 /// Obtain type information for the target executor object.
225 /**
226 * @returns If @c *this has a target type of type @c T, <tt>typeid(T)</tt>;
227 * otherwise, <tt>typeid(void)</tt>.
228 */
229#if !defined(BOOST_ASIO_NO_TYPEID) || defined(GENERATING_DOCUMENTATION)
230 const std::type_info& target_type() const noexcept
231 {
232 return impl_ ? impl_->target_type() : typeid(void);
233 }
234#else // !defined(BOOST_ASIO_NO_TYPEID) || defined(GENERATING_DOCUMENTATION)
235 const void* target_type() const noexcept
236 {
237 return impl_ ? impl_->target_type() : 0;
238 }
239#endif // !defined(BOOST_ASIO_NO_TYPEID) || defined(GENERATING_DOCUMENTATION)
240
241 /// Obtain a pointer to the target executor object.
242 /**
243 * @returns If <tt>target_type() == typeid(T)</tt>, a pointer to the stored
244 * executor target; otherwise, a null pointer.
245 */
246 template <typename Executor>
247 Executor* target() noexcept;
248
249 /// Obtain a pointer to the target executor object.
250 /**
251 * @returns If <tt>target_type() == typeid(T)</tt>, a pointer to the stored
252 * executor target; otherwise, a null pointer.
253 */
254 template <typename Executor>
255 const Executor* target() const noexcept;
256
257 /// Compare two executors for equality.
258 friend bool operator==(const executor& a,
259 const executor& b) noexcept
260 {
261 if (a.impl_ == b.impl_)
262 return true;
263 if (!a.impl_ || !b.impl_)
264 return false;
265 return a.impl_->equals(e: b.impl_);
266 }
267
268 /// Compare two executors for inequality.
269 friend bool operator!=(const executor& a,
270 const executor& b) noexcept
271 {
272 return !(a == b);
273 }
274
275private:
276#if !defined(GENERATING_DOCUMENTATION)
277 typedef detail::executor_function function;
278 template <typename, typename> class impl;
279
280#if !defined(BOOST_ASIO_NO_TYPEID)
281 typedef const std::type_info& type_id_result_type;
282#else // !defined(BOOST_ASIO_NO_TYPEID)
283 typedef const void* type_id_result_type;
284#endif // !defined(BOOST_ASIO_NO_TYPEID)
285
286 template <typename T>
287 static type_id_result_type type_id()
288 {
289#if !defined(BOOST_ASIO_NO_TYPEID)
290 return typeid(T);
291#else // !defined(BOOST_ASIO_NO_TYPEID)
292 static int unique_id;
293 return &unique_id;
294#endif // !defined(BOOST_ASIO_NO_TYPEID)
295 }
296
297 // Base class for all polymorphic executor implementations.
298 class impl_base
299 {
300 public:
301 virtual impl_base* clone() const noexcept = 0;
302 virtual void destroy() noexcept = 0;
303 virtual execution_context& context() noexcept = 0;
304 virtual void on_work_started() noexcept = 0;
305 virtual void on_work_finished() noexcept = 0;
306 virtual void dispatch(function&&) = 0;
307 virtual void post(function&&) = 0;
308 virtual void defer(function&&) = 0;
309 virtual type_id_result_type target_type() const noexcept = 0;
310 virtual void* target() noexcept = 0;
311 virtual const void* target() const noexcept = 0;
312 virtual bool equals(const impl_base* e) const noexcept = 0;
313
314 protected:
315 impl_base(bool fast_dispatch) : fast_dispatch_(fast_dispatch) {}
316 virtual ~impl_base() {}
317
318 private:
319 friend class executor;
320 const bool fast_dispatch_;
321 };
322
323 // Helper function to check and return the implementation pointer.
324 impl_base* get_impl() const
325 {
326 if (!impl_)
327 {
328 bad_executor ex;
329 boost::asio::detail::throw_exception(e: ex);
330 }
331 return impl_;
332 }
333
334 // Helper function to clone another implementation.
335 impl_base* clone() const noexcept
336 {
337 return impl_ ? impl_->clone() : 0;
338 }
339
340 // Helper function to destroy an implementation.
341 void destroy() noexcept
342 {
343 if (impl_)
344 impl_->destroy();
345 }
346
347 impl_base* impl_;
348#endif // !defined(GENERATING_DOCUMENTATION)
349};
350
351} // namespace asio
352} // namespace boost
353
354BOOST_ASIO_USES_ALLOCATOR(boost::asio::executor)
355
356#include <boost/asio/detail/pop_options.hpp>
357
358#include <boost/asio/impl/executor.hpp>
359#if defined(BOOST_ASIO_HEADER_ONLY)
360# include <boost/asio/impl/executor.ipp>
361#endif // defined(BOOST_ASIO_HEADER_ONLY)
362
363#endif // !defined(BOOST_ASIO_NO_TS_EXECUTORS)
364
365#endif // BOOST_ASIO_EXECUTOR_HPP
366

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