1//
2// associated_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_ASSOCIATED_EXECUTOR_HPP
12#define BOOST_ASIO_ASSOCIATED_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/associator.hpp>
20#include <boost/asio/detail/functional.hpp>
21#include <boost/asio/detail/type_traits.hpp>
22#include <boost/asio/execution/executor.hpp>
23#include <boost/asio/is_executor.hpp>
24#include <boost/asio/system_executor.hpp>
25
26#include <boost/asio/detail/push_options.hpp>
27
28namespace boost {
29namespace asio {
30
31template <typename T, typename Executor>
32struct associated_executor;
33
34namespace detail {
35
36template <typename T, typename = void>
37struct has_executor_type : false_type
38{
39};
40
41template <typename T>
42struct has_executor_type<T, void_t<typename T::executor_type>>
43 : true_type
44{
45};
46
47template <typename T, typename E, typename = void, typename = void>
48struct associated_executor_impl
49{
50 typedef void asio_associated_executor_is_unspecialised;
51
52 typedef E type;
53
54 static type get(const T&) noexcept
55 {
56 return type();
57 }
58
59 static const type& get(const T&, const E& e) noexcept
60 {
61 return e;
62 }
63};
64
65template <typename T, typename E>
66struct associated_executor_impl<T, E, void_t<typename T::executor_type>>
67{
68 typedef typename T::executor_type type;
69
70 static auto get(const T& t) noexcept
71 -> decltype(t.get_executor())
72 {
73 return t.get_executor();
74 }
75
76 static auto get(const T& t, const E&) noexcept
77 -> decltype(t.get_executor())
78 {
79 return t.get_executor();
80 }
81};
82
83template <typename T, typename E>
84struct associated_executor_impl<T, E,
85 enable_if_t<
86 !has_executor_type<T>::value
87 >,
88 void_t<
89 typename associator<associated_executor, T, E>::type
90 >> : associator<associated_executor, T, E>
91{
92};
93
94} // namespace detail
95
96/// Traits type used to obtain the executor associated with an object.
97/**
98 * A program may specialise this traits type if the @c T template parameter in
99 * the specialisation is a user-defined type. The template parameter @c
100 * Executor shall be a type meeting the Executor requirements.
101 *
102 * Specialisations shall meet the following requirements, where @c t is a const
103 * reference to an object of type @c T, and @c e is an object of type @c
104 * Executor.
105 *
106 * @li Provide a nested typedef @c type that identifies a type meeting the
107 * Executor requirements.
108 *
109 * @li Provide a noexcept static member function named @c get, callable as @c
110 * get(t) and with return type @c type or a (possibly const) reference to @c
111 * type.
112 *
113 * @li Provide a noexcept static member function named @c get, callable as @c
114 * get(t,e) and with return type @c type or a (possibly const) reference to @c
115 * type.
116 */
117template <typename T, typename Executor = system_executor>
118struct associated_executor
119#if !defined(GENERATING_DOCUMENTATION)
120 : detail::associated_executor_impl<T, Executor>
121#endif // !defined(GENERATING_DOCUMENTATION)
122{
123#if defined(GENERATING_DOCUMENTATION)
124 /// If @c T has a nested type @c executor_type, <tt>T::executor_type</tt>.
125 /// Otherwise @c Executor.
126 typedef see_below type;
127
128 /// If @c T has a nested type @c executor_type, returns
129 /// <tt>t.get_executor()</tt>. Otherwise returns @c type().
130 static decltype(auto) get(const T& t) noexcept;
131
132 /// If @c T has a nested type @c executor_type, returns
133 /// <tt>t.get_executor()</tt>. Otherwise returns @c ex.
134 static decltype(auto) get(const T& t, const Executor& ex) noexcept;
135#endif // defined(GENERATING_DOCUMENTATION)
136};
137
138/// Helper function to obtain an object's associated executor.
139/**
140 * @returns <tt>associated_executor<T>::get(t)</tt>
141 */
142template <typename T>
143BOOST_ASIO_NODISCARD inline typename associated_executor<T>::type
144get_associated_executor(const T& t) noexcept
145{
146 return associated_executor<T>::get(t);
147}
148
149/// Helper function to obtain an object's associated executor.
150/**
151 * @returns <tt>associated_executor<T, Executor>::get(t, ex)</tt>
152 */
153template <typename T, typename Executor>
154BOOST_ASIO_NODISCARD inline auto get_associated_executor(
155 const T& t, const Executor& ex,
156 constraint_t<
157 is_executor<Executor>::value || execution::is_executor<Executor>::value
158 > = 0) noexcept
159 -> decltype(associated_executor<T, Executor>::get(t, ex))
160{
161 return associated_executor<T, Executor>::get(t, ex);
162}
163
164/// Helper function to obtain an object's associated executor.
165/**
166 * @returns <tt>associated_executor<T, typename
167 * ExecutionContext::executor_type>::get(t, ctx.get_executor())</tt>
168 */
169template <typename T, typename ExecutionContext>
170BOOST_ASIO_NODISCARD inline typename associated_executor<T,
171 typename ExecutionContext::executor_type>::type
172get_associated_executor(const T& t, ExecutionContext& ctx,
173 constraint_t<is_convertible<ExecutionContext&,
174 execution_context&>::value> = 0) noexcept
175{
176 return associated_executor<T,
177 typename ExecutionContext::executor_type>::get(t, ctx.get_executor());
178}
179
180template <typename T, typename Executor = system_executor>
181using associated_executor_t = typename associated_executor<T, Executor>::type;
182
183namespace detail {
184
185template <typename T, typename E, typename = void>
186struct associated_executor_forwarding_base
187{
188};
189
190template <typename T, typename E>
191struct associated_executor_forwarding_base<T, E,
192 enable_if_t<
193 is_same<
194 typename associated_executor<T,
195 E>::asio_associated_executor_is_unspecialised,
196 void
197 >::value
198 >>
199{
200 typedef void asio_associated_executor_is_unspecialised;
201};
202
203} // namespace detail
204
205/// Specialisation of associated_executor for @c std::reference_wrapper.
206template <typename T, typename Executor>
207struct associated_executor<reference_wrapper<T>, Executor>
208#if !defined(GENERATING_DOCUMENTATION)
209 : detail::associated_executor_forwarding_base<T, Executor>
210#endif // !defined(GENERATING_DOCUMENTATION)
211{
212 /// Forwards @c type to the associator specialisation for the unwrapped type
213 /// @c T.
214 typedef typename associated_executor<T, Executor>::type type;
215
216 /// Forwards the request to get the executor to the associator specialisation
217 /// for the unwrapped type @c T.
218 static type get(reference_wrapper<T> t) noexcept
219 {
220 return associated_executor<T, Executor>::get(t.get());
221 }
222
223 /// Forwards the request to get the executor to the associator specialisation
224 /// for the unwrapped type @c T.
225 static auto get(reference_wrapper<T> t, const Executor& ex) noexcept
226 -> decltype(associated_executor<T, Executor>::get(t.get(), ex))
227 {
228 return associated_executor<T, Executor>::get(t.get(), ex);
229 }
230};
231
232} // namespace asio
233} // namespace boost
234
235#include <boost/asio/detail/pop_options.hpp>
236
237#endif // BOOST_ASIO_ASSOCIATED_EXECUTOR_HPP
238

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