1//
2// system_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_SYSTEM_EXECUTOR_HPP
12#define BOOST_ASIO_SYSTEM_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#include <boost/asio/detail/memory.hpp>
20#include <boost/asio/execution.hpp>
21
22#include <boost/asio/detail/push_options.hpp>
23
24namespace boost {
25namespace asio {
26
27class system_context;
28
29/// An executor that uses arbitrary threads.
30/**
31 * The system executor represents an execution context where functions are
32 * permitted to run on arbitrary threads. When the blocking.never property is
33 * established, the system executor will schedule the function to run on an
34 * unspecified system thread pool. When either blocking.possibly or
35 * blocking.always is established, the executor invokes the function
36 * immediately.
37 */
38template <typename Blocking, typename Relationship, typename Allocator>
39class basic_system_executor
40{
41public:
42 /// Default constructor.
43 basic_system_executor() noexcept
44 : allocator_(Allocator())
45 {
46 }
47
48#if !defined(GENERATING_DOCUMENTATION)
49private:
50 friend struct boost_asio_require_fn::impl;
51 friend struct boost_asio_prefer_fn::impl;
52#endif // !defined(GENERATING_DOCUMENTATION)
53
54 /// Obtain an executor with the @c blocking.possibly property.
55 /**
56 * Do not call this function directly. It is intended for use with the
57 * boost::asio::require customisation point.
58 *
59 * For example:
60 * @code boost::asio::system_executor ex1;
61 * auto ex2 = boost::asio::require(ex1,
62 * boost::asio::execution::blocking.possibly); @endcode
63 */
64 basic_system_executor<execution::blocking_t::possibly_t,
65 Relationship, Allocator>
66 require(execution::blocking_t::possibly_t) const
67 {
68 return basic_system_executor<execution::blocking_t::possibly_t,
69 Relationship, Allocator>(allocator_);
70 }
71
72 /// Obtain an executor with the @c blocking.always property.
73 /**
74 * Do not call this function directly. It is intended for use with the
75 * boost::asio::require customisation point.
76 *
77 * For example:
78 * @code boost::asio::system_executor ex1;
79 * auto ex2 = boost::asio::require(ex1,
80 * boost::asio::execution::blocking.always); @endcode
81 */
82 basic_system_executor<execution::blocking_t::always_t,
83 Relationship, Allocator>
84 require(execution::blocking_t::always_t) const
85 {
86 return basic_system_executor<execution::blocking_t::always_t,
87 Relationship, Allocator>(allocator_);
88 }
89
90 /// Obtain an executor with the @c blocking.never property.
91 /**
92 * Do not call this function directly. It is intended for use with the
93 * boost::asio::require customisation point.
94 *
95 * For example:
96 * @code boost::asio::system_executor ex1;
97 * auto ex2 = boost::asio::require(ex1,
98 * boost::asio::execution::blocking.never); @endcode
99 */
100 basic_system_executor<execution::blocking_t::never_t,
101 Relationship, Allocator>
102 require(execution::blocking_t::never_t) const
103 {
104 return basic_system_executor<execution::blocking_t::never_t,
105 Relationship, Allocator>(allocator_);
106 }
107
108 /// Obtain an executor with the @c relationship.continuation property.
109 /**
110 * Do not call this function directly. It is intended for use with the
111 * boost::asio::require customisation point.
112 *
113 * For example:
114 * @code boost::asio::system_executor ex1;
115 * auto ex2 = boost::asio::require(ex1,
116 * boost::asio::execution::relationship.continuation); @endcode
117 */
118 basic_system_executor<Blocking,
119 execution::relationship_t::continuation_t, Allocator>
120 require(execution::relationship_t::continuation_t) const
121 {
122 return basic_system_executor<Blocking,
123 execution::relationship_t::continuation_t, Allocator>(allocator_);
124 }
125
126 /// Obtain an executor with the @c relationship.fork property.
127 /**
128 * Do not call this function directly. It is intended for use with the
129 * boost::asio::require customisation point.
130 *
131 * For example:
132 * @code boost::asio::system_executor ex1;
133 * auto ex2 = boost::asio::require(ex1,
134 * boost::asio::execution::relationship.fork); @endcode
135 */
136 basic_system_executor<Blocking,
137 execution::relationship_t::fork_t, Allocator>
138 require(execution::relationship_t::fork_t) const
139 {
140 return basic_system_executor<Blocking,
141 execution::relationship_t::fork_t, Allocator>(allocator_);
142 }
143
144 /// Obtain an executor with the specified @c allocator property.
145 /**
146 * Do not call this function directly. It is intended for use with the
147 * boost::asio::require customisation point.
148 *
149 * For example:
150 * @code boost::asio::system_executor ex1;
151 * auto ex2 = boost::asio::require(ex1,
152 * boost::asio::execution::allocator(my_allocator)); @endcode
153 */
154 template <typename OtherAllocator>
155 basic_system_executor<Blocking, Relationship, OtherAllocator>
156 require(execution::allocator_t<OtherAllocator> a) const
157 {
158 return basic_system_executor<Blocking,
159 Relationship, OtherAllocator>(a.value());
160 }
161
162 /// Obtain an executor with the default @c allocator property.
163 /**
164 * Do not call this function directly. It is intended for use with the
165 * boost::asio::require customisation point.
166 *
167 * For example:
168 * @code boost::asio::system_executor ex1;
169 * auto ex2 = boost::asio::require(ex1,
170 * boost::asio::execution::allocator); @endcode
171 */
172 basic_system_executor<Blocking, Relationship, std::allocator<void>>
173 require(execution::allocator_t<void>) const
174 {
175 return basic_system_executor<Blocking,
176 Relationship, std::allocator<void>>();
177 }
178
179#if !defined(GENERATING_DOCUMENTATION)
180private:
181 friend struct boost_asio_query_fn::impl;
182 friend struct boost::asio::execution::detail::blocking_t<0>;
183 friend struct boost::asio::execution::detail::mapping_t<0>;
184 friend struct boost::asio::execution::detail::outstanding_work_t<0>;
185 friend struct boost::asio::execution::detail::relationship_t<0>;
186#endif // !defined(GENERATING_DOCUMENTATION)
187
188 /// Query the current value of the @c mapping property.
189 /**
190 * Do not call this function directly. It is intended for use with the
191 * boost::asio::query customisation point.
192 *
193 * For example:
194 * @code boost::asio::system_executor ex;
195 * if (boost::asio::query(ex, boost::asio::execution::mapping)
196 * == boost::asio::execution::mapping.thread)
197 * ... @endcode
198 */
199 static constexpr execution::mapping_t query(
200 execution::mapping_t) noexcept
201 {
202 return execution::mapping.thread;
203 }
204
205 /// Query the current value of the @c context property.
206 /**
207 * Do not call this function directly. It is intended for use with the
208 * boost::asio::query customisation point.
209 *
210 * For example:
211 * @code boost::asio::system_executor ex;
212 * boost::asio::system_context& pool = boost::asio::query(
213 * ex, boost::asio::execution::context); @endcode
214 */
215 static system_context& query(execution::context_t) noexcept;
216
217 /// Query the current value of the @c blocking property.
218 /**
219 * Do not call this function directly. It is intended for use with the
220 * boost::asio::query customisation point.
221 *
222 * For example:
223 * @code boost::asio::system_executor ex;
224 * if (boost::asio::query(ex, boost::asio::execution::blocking)
225 * == boost::asio::execution::blocking.always)
226 * ... @endcode
227 */
228 static constexpr execution::blocking_t query(
229 execution::blocking_t) noexcept
230 {
231 return Blocking();
232 }
233
234 /// Query the current value of the @c relationship property.
235 /**
236 * Do not call this function directly. It is intended for use with the
237 * boost::asio::query customisation point.
238 *
239 * For example:
240 * @code boost::asio::system_executor ex;
241 * if (boost::asio::query(ex, boost::asio::execution::relationship)
242 * == boost::asio::execution::relationship.continuation)
243 * ... @endcode
244 */
245 static constexpr execution::relationship_t query(
246 execution::relationship_t) noexcept
247 {
248 return Relationship();
249 }
250
251 /// Query the current value of the @c allocator property.
252 /**
253 * Do not call this function directly. It is intended for use with the
254 * boost::asio::query customisation point.
255 *
256 * For example:
257 * @code boost::asio::system_executor ex;
258 * auto alloc = boost::asio::query(ex,
259 * boost::asio::execution::allocator); @endcode
260 */
261 template <typename OtherAllocator>
262 constexpr Allocator query(
263 execution::allocator_t<OtherAllocator>) const noexcept
264 {
265 return allocator_;
266 }
267
268 /// Query the current value of the @c allocator property.
269 /**
270 * Do not call this function directly. It is intended for use with the
271 * boost::asio::query customisation point.
272 *
273 * For example:
274 * @code boost::asio::system_executor ex;
275 * auto alloc = boost::asio::query(ex,
276 * boost::asio::execution::allocator); @endcode
277 */
278 constexpr Allocator query(
279 execution::allocator_t<void>) const noexcept
280 {
281 return allocator_;
282 }
283
284 /// Query the occupancy (recommended number of work items) for the system
285 /// context.
286 /**
287 * Do not call this function directly. It is intended for use with the
288 * boost::asio::query customisation point.
289 *
290 * For example:
291 * @code boost::asio::system_executor ex;
292 * std::size_t occupancy = boost::asio::query(
293 * ex, boost::asio::execution::occupancy); @endcode
294 */
295 std::size_t query(execution::occupancy_t) const noexcept;
296
297public:
298 /// Compare two executors for equality.
299 /**
300 * Two executors are equal if they refer to the same underlying io_context.
301 */
302 friend bool operator==(const basic_system_executor&,
303 const basic_system_executor&) noexcept
304 {
305 return true;
306 }
307
308 /// Compare two executors for inequality.
309 /**
310 * Two executors are equal if they refer to the same underlying io_context.
311 */
312 friend bool operator!=(const basic_system_executor&,
313 const basic_system_executor&) noexcept
314 {
315 return false;
316 }
317
318 /// Execution function.
319 template <typename Function>
320 void execute(Function&& f) const
321 {
322 this->do_execute(static_cast<Function&&>(f), Blocking());
323 }
324
325#if !defined(BOOST_ASIO_NO_TS_EXECUTORS)
326public:
327 /// Obtain the underlying execution context.
328 system_context& context() const noexcept;
329
330 /// Inform the executor that it has some outstanding work to do.
331 /**
332 * For the system executor, this is a no-op.
333 */
334 void on_work_started() const noexcept
335 {
336 }
337
338 /// Inform the executor that some work is no longer outstanding.
339 /**
340 * For the system executor, this is a no-op.
341 */
342 void on_work_finished() const noexcept
343 {
344 }
345
346 /// Request the system executor to invoke the given function object.
347 /**
348 * This function is used to ask the executor to execute the given function
349 * object. The function object will always be executed inside this function.
350 *
351 * @param f The function object to be called. The executor will make
352 * a copy of the handler object as required. The function signature of the
353 * function object must be: @code void function(); @endcode
354 *
355 * @param a An allocator that may be used by the executor to allocate the
356 * internal storage needed for function invocation.
357 */
358 template <typename Function, typename OtherAllocator>
359 void dispatch(Function&& f, const OtherAllocator& a) const;
360
361 /// Request the system executor to invoke the given function object.
362 /**
363 * This function is used to ask the executor to execute the given function
364 * object. The function object will never be executed inside this function.
365 * Instead, it will be scheduled to run on an unspecified system thread pool.
366 *
367 * @param f The function object to be called. The executor will make
368 * a copy of the handler object as required. The function signature of the
369 * function object must be: @code void function(); @endcode
370 *
371 * @param a An allocator that may be used by the executor to allocate the
372 * internal storage needed for function invocation.
373 */
374 template <typename Function, typename OtherAllocator>
375 void post(Function&& f, const OtherAllocator& a) const;
376
377 /// Request the system executor to invoke the given function object.
378 /**
379 * This function is used to ask the executor to execute the given function
380 * object. The function object will never be executed inside this function.
381 * Instead, it will be scheduled to run on an unspecified system thread pool.
382 *
383 * @param f The function object to be called. The executor will make
384 * a copy of the handler object as required. The function signature of the
385 * function object must be: @code void function(); @endcode
386 *
387 * @param a An allocator that may be used by the executor to allocate the
388 * internal storage needed for function invocation.
389 */
390 template <typename Function, typename OtherAllocator>
391 void defer(Function&& f, const OtherAllocator& a) const;
392#endif // !defined(BOOST_ASIO_NO_TS_EXECUTORS)
393
394private:
395 template <typename, typename, typename> friend class basic_system_executor;
396
397 // Constructor used by require().
398 basic_system_executor(const Allocator& a)
399 : allocator_(a)
400 {
401 }
402
403 /// Execution helper implementation for the possibly blocking property.
404 template <typename Function>
405 void do_execute(Function&& f,
406 execution::blocking_t::possibly_t) const;
407
408 /// Execution helper implementation for the always blocking property.
409 template <typename Function>
410 void do_execute(Function&& f,
411 execution::blocking_t::always_t) const;
412
413 /// Execution helper implementation for the never blocking property.
414 template <typename Function>
415 void do_execute(Function&& f,
416 execution::blocking_t::never_t) const;
417
418 // The allocator used for execution functions.
419 Allocator allocator_;
420};
421
422/// An executor that uses arbitrary threads.
423/**
424 * The system executor represents an execution context where functions are
425 * permitted to run on arbitrary threads. When the blocking.never property is
426 * established, the system executor will schedule the function to run on an
427 * unspecified system thread pool. When either blocking.possibly or
428 * blocking.always is established, the executor invokes the function
429 * immediately.
430 */
431typedef basic_system_executor<execution::blocking_t::possibly_t,
432 execution::relationship_t::fork_t, std::allocator<void>>
433 system_executor;
434
435#if !defined(GENERATING_DOCUMENTATION)
436
437namespace traits {
438
439#if !defined(BOOST_ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)
440
441template <typename Blocking, typename Relationship, typename Allocator>
442struct equality_comparable<
443 boost::asio::basic_system_executor<Blocking, Relationship, Allocator>
444 >
445{
446 static constexpr bool is_valid = true;
447 static constexpr bool is_noexcept = true;
448};
449
450#endif // !defined(BOOST_ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)
451
452#if !defined(BOOST_ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)
453
454template <typename Blocking, typename Relationship,
455 typename Allocator, typename Function>
456struct execute_member<
457 boost::asio::basic_system_executor<Blocking, Relationship, Allocator>,
458 Function
459 >
460{
461 static constexpr bool is_valid = true;
462 static constexpr bool is_noexcept = false;
463 typedef void result_type;
464};
465
466#endif // !defined(BOOST_ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)
467
468#if !defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)
469
470template <typename Blocking, typename Relationship, typename Allocator>
471struct require_member<
472 boost::asio::basic_system_executor<Blocking, Relationship, Allocator>,
473 boost::asio::execution::blocking_t::possibly_t
474 >
475{
476 static constexpr bool is_valid = true;
477 static constexpr bool is_noexcept = false;
478 typedef boost::asio::basic_system_executor<
479 boost::asio::execution::blocking_t::possibly_t,
480 Relationship, Allocator> result_type;
481};
482
483template <typename Blocking, typename Relationship, typename Allocator>
484struct require_member<
485 boost::asio::basic_system_executor<Blocking, Relationship, Allocator>,
486 boost::asio::execution::blocking_t::always_t
487 >
488{
489 static constexpr bool is_valid = true;
490 static constexpr bool is_noexcept = false;
491 typedef boost::asio::basic_system_executor<
492 boost::asio::execution::blocking_t::always_t,
493 Relationship, Allocator> result_type;
494};
495
496template <typename Blocking, typename Relationship, typename Allocator>
497struct require_member<
498 boost::asio::basic_system_executor<Blocking, Relationship, Allocator>,
499 boost::asio::execution::blocking_t::never_t
500 >
501{
502 static constexpr bool is_valid = true;
503 static constexpr bool is_noexcept = false;
504 typedef boost::asio::basic_system_executor<
505 boost::asio::execution::blocking_t::never_t,
506 Relationship, Allocator> result_type;
507};
508
509template <typename Blocking, typename Relationship, typename Allocator>
510struct require_member<
511 boost::asio::basic_system_executor<Blocking, Relationship, Allocator>,
512 boost::asio::execution::relationship_t::fork_t
513 >
514{
515 static constexpr bool is_valid = true;
516 static constexpr bool is_noexcept = false;
517 typedef boost::asio::basic_system_executor<Blocking,
518 boost::asio::execution::relationship_t::fork_t,
519 Allocator> result_type;
520};
521
522template <typename Blocking, typename Relationship, typename Allocator>
523struct require_member<
524 boost::asio::basic_system_executor<Blocking, Relationship, Allocator>,
525 boost::asio::execution::relationship_t::continuation_t
526 >
527{
528 static constexpr bool is_valid = true;
529 static constexpr bool is_noexcept = false;
530 typedef boost::asio::basic_system_executor<Blocking,
531 boost::asio::execution::relationship_t::continuation_t,
532 Allocator> result_type;
533};
534
535template <typename Blocking, typename Relationship, typename Allocator>
536struct require_member<
537 boost::asio::basic_system_executor<Blocking, Relationship, Allocator>,
538 boost::asio::execution::allocator_t<void>
539 >
540{
541 static constexpr bool is_valid = true;
542 static constexpr bool is_noexcept = false;
543 typedef boost::asio::basic_system_executor<Blocking,
544 Relationship, std::allocator<void>> result_type;
545};
546
547template <typename Blocking, typename Relationship,
548 typename Allocator, typename OtherAllocator>
549struct require_member<
550 boost::asio::basic_system_executor<Blocking, Relationship, Allocator>,
551 boost::asio::execution::allocator_t<OtherAllocator>
552 >
553{
554 static constexpr bool is_valid = true;
555 static constexpr bool is_noexcept = false;
556 typedef boost::asio::basic_system_executor<Blocking,
557 Relationship, OtherAllocator> result_type;
558};
559
560#endif // !defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)
561
562#if !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)
563
564template <typename Blocking, typename Relationship,
565 typename Allocator, typename Property>
566struct query_static_constexpr_member<
567 boost::asio::basic_system_executor<Blocking, Relationship, Allocator>,
568 Property,
569 typename boost::asio::enable_if<
570 boost::asio::is_convertible<
571 Property,
572 boost::asio::execution::mapping_t
573 >::value
574 >::type
575 >
576{
577 static constexpr bool is_valid = true;
578 static constexpr bool is_noexcept = true;
579 typedef boost::asio::execution::mapping_t::thread_t result_type;
580
581 static constexpr result_type value() noexcept
582 {
583 return result_type();
584 }
585};
586
587#endif // !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)
588
589#if !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)
590
591template <typename Blocking, typename Relationship,
592 typename Allocator, typename Property>
593struct query_member<
594 boost::asio::basic_system_executor<Blocking, Relationship, Allocator>,
595 Property,
596 typename boost::asio::enable_if<
597 boost::asio::is_convertible<
598 Property,
599 boost::asio::execution::blocking_t
600 >::value
601 >::type
602 >
603{
604 static constexpr bool is_valid = true;
605 static constexpr bool is_noexcept = true;
606 typedef boost::asio::execution::blocking_t result_type;
607};
608
609template <typename Blocking, typename Relationship,
610 typename Allocator, typename Property>
611struct query_member<
612 boost::asio::basic_system_executor<Blocking, Relationship, Allocator>,
613 Property,
614 typename boost::asio::enable_if<
615 boost::asio::is_convertible<
616 Property,
617 boost::asio::execution::relationship_t
618 >::value
619 >::type
620 >
621{
622 static constexpr bool is_valid = true;
623 static constexpr bool is_noexcept = true;
624 typedef boost::asio::execution::relationship_t result_type;
625};
626
627template <typename Blocking, typename Relationship, typename Allocator>
628struct query_member<
629 boost::asio::basic_system_executor<Blocking, Relationship, Allocator>,
630 boost::asio::execution::context_t
631 >
632{
633 static constexpr bool is_valid = true;
634 static constexpr bool is_noexcept = true;
635 typedef boost::asio::system_context& result_type;
636};
637
638template <typename Blocking, typename Relationship, typename Allocator>
639struct query_member<
640 boost::asio::basic_system_executor<Blocking, Relationship, Allocator>,
641 boost::asio::execution::allocator_t<void>
642 >
643{
644 static constexpr bool is_valid = true;
645 static constexpr bool is_noexcept = true;
646 typedef Allocator result_type;
647};
648
649template <typename Blocking, typename Relationship, typename Allocator>
650struct query_member<
651 boost::asio::basic_system_executor<Blocking, Relationship, Allocator>,
652 boost::asio::execution::allocator_t<Allocator>
653 >
654{
655 static constexpr bool is_valid = true;
656 static constexpr bool is_noexcept = true;
657 typedef Allocator result_type;
658};
659
660#endif // !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)
661
662} // namespace traits
663
664#endif // !defined(GENERATING_DOCUMENTATION)
665
666} // namespace asio
667} // namespace boost
668
669#include <boost/asio/detail/pop_options.hpp>
670
671#include <boost/asio/impl/system_executor.hpp>
672
673#endif // BOOST_ASIO_SYSTEM_EXECUTOR_HPP
674

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