1//
2// associated_immediate_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_IMMEDIATE_EXECUTOR_HPP
12#define BOOST_ASIO_ASSOCIATED_IMMEDIATE_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/blocking.hpp>
23#include <boost/asio/execution/executor.hpp>
24#include <boost/asio/execution_context.hpp>
25#include <boost/asio/is_executor.hpp>
26#include <boost/asio/require.hpp>
27
28#include <boost/asio/detail/push_options.hpp>
29
30namespace boost {
31namespace asio {
32
33template <typename T, typename Executor>
34struct associated_immediate_executor;
35
36namespace detail {
37
38template <typename T, typename = void>
39struct has_immediate_executor_type : false_type
40{
41};
42
43template <typename T>
44struct has_immediate_executor_type<T,
45 void_t<typename T::immediate_executor_type>>
46 : true_type
47{
48};
49
50template <typename E, typename = void, typename = void>
51struct default_immediate_executor
52{
53 typedef require_result_t<E, execution::blocking_t::never_t> type;
54
55 static type get(const E& e) noexcept
56 {
57 return boost::asio::require(e, execution::blocking.never);
58 }
59};
60
61template <typename E>
62struct default_immediate_executor<E,
63 enable_if_t<
64 !execution::is_executor<E>::value
65 >,
66 enable_if_t<
67 is_executor<E>::value
68 >>
69{
70 class type : public E
71 {
72 public:
73 template <typename Executor1>
74 explicit type(const Executor1& e,
75 constraint_t<
76 conditional_t<
77 !is_same<Executor1, type>::value,
78 is_convertible<Executor1, E>,
79 false_type
80 >::value
81 > = 0) noexcept
82 : E(e)
83 {
84 }
85
86 type(const type& other) noexcept
87 : E(static_cast<const E&>(other))
88 {
89 }
90
91 type(type&& other) noexcept
92 : E(static_cast<E&&>(other))
93 {
94 }
95
96 template <typename Function, typename Allocator>
97 void dispatch(Function&& f, const Allocator& a) const
98 {
99 this->post(static_cast<Function&&>(f), a);
100 }
101
102 friend bool operator==(const type& a, const type& b) noexcept
103 {
104 return static_cast<const E&>(a) == static_cast<const E&>(b);
105 }
106
107 friend bool operator!=(const type& a, const type& b) noexcept
108 {
109 return static_cast<const E&>(a) != static_cast<const E&>(b);
110 }
111 };
112
113 static type get(const E& e) noexcept
114 {
115 return type(e);
116 }
117};
118
119template <typename T, typename E, typename = void, typename = void>
120struct associated_immediate_executor_impl
121{
122 typedef void asio_associated_immediate_executor_is_unspecialised;
123
124 typedef typename default_immediate_executor<E>::type type;
125
126 static auto get(const T&, const E& e) noexcept
127 -> decltype(default_immediate_executor<E>::get(e))
128 {
129 return default_immediate_executor<E>::get(e);
130 }
131};
132
133template <typename T, typename E>
134struct associated_immediate_executor_impl<T, E,
135 void_t<typename T::immediate_executor_type>>
136{
137 typedef typename T::immediate_executor_type type;
138
139 static auto get(const T& t, const E&) noexcept
140 -> decltype(t.get_immediate_executor())
141 {
142 return t.get_immediate_executor();
143 }
144};
145
146template <typename T, typename E>
147struct associated_immediate_executor_impl<T, E,
148 enable_if_t<
149 !has_immediate_executor_type<T>::value
150 >,
151 void_t<
152 typename associator<associated_immediate_executor, T, E>::type
153 >> : associator<associated_immediate_executor, T, E>
154{
155};
156
157} // namespace detail
158
159/// Traits type used to obtain the immediate executor associated with an object.
160/**
161 * A program may specialise this traits type if the @c T template parameter in
162 * the specialisation is a user-defined type. The template parameter @c
163 * Executor shall be a type meeting the Executor requirements.
164 *
165 * Specialisations shall meet the following requirements, where @c t is a const
166 * reference to an object of type @c T, and @c e is an object of type @c
167 * Executor.
168 *
169 * @li Provide a nested typedef @c type that identifies a type meeting the
170 * Executor requirements.
171 *
172 * @li Provide a noexcept static member function named @c get, callable as @c
173 * get(t) and with return type @c type or a (possibly const) reference to @c
174 * type.
175 *
176 * @li Provide a noexcept static member function named @c get, callable as @c
177 * get(t,e) and with return type @c type or a (possibly const) reference to @c
178 * type.
179 */
180template <typename T, typename Executor>
181struct associated_immediate_executor
182#if !defined(GENERATING_DOCUMENTATION)
183 : detail::associated_immediate_executor_impl<T, Executor>
184#endif // !defined(GENERATING_DOCUMENTATION)
185{
186#if defined(GENERATING_DOCUMENTATION)
187 /// If @c T has a nested type @c immediate_executor_type,
188 // <tt>T::immediate_executor_type</tt>. Otherwise @c Executor.
189 typedef see_below type;
190
191 /// If @c T has a nested type @c immediate_executor_type, returns
192 /// <tt>t.get_immediate_executor()</tt>. Otherwise returns
193 /// <tt>boost::asio::require(ex, boost::asio::execution::blocking.never)</tt>.
194 static decltype(auto) get(const T& t, const Executor& ex) noexcept;
195#endif // defined(GENERATING_DOCUMENTATION)
196};
197
198/// Helper function to obtain an object's associated executor.
199/**
200 * @returns <tt>associated_immediate_executor<T, Executor>::get(t, ex)</tt>
201 */
202template <typename T, typename Executor>
203BOOST_ASIO_NODISCARD inline auto get_associated_immediate_executor(
204 const T& t, const Executor& ex,
205 constraint_t<
206 is_executor<Executor>::value || execution::is_executor<Executor>::value
207 > = 0) noexcept
208 -> decltype(associated_immediate_executor<T, Executor>::get(t, ex))
209{
210 return associated_immediate_executor<T, Executor>::get(t, ex);
211}
212
213/// Helper function to obtain an object's associated executor.
214/**
215 * @returns <tt>associated_immediate_executor<T, typename
216 * ExecutionContext::executor_type>::get(t, ctx.get_executor())</tt>
217 */
218template <typename T, typename ExecutionContext>
219BOOST_ASIO_NODISCARD inline typename associated_immediate_executor<T,
220 typename ExecutionContext::executor_type>::type
221get_associated_immediate_executor(const T& t, ExecutionContext& ctx,
222 constraint_t<
223 is_convertible<ExecutionContext&, execution_context&>::value
224 > = 0) noexcept
225{
226 return associated_immediate_executor<T,
227 typename ExecutionContext::executor_type>::get(t, ctx.get_executor());
228}
229
230template <typename T, typename Executor>
231using associated_immediate_executor_t =
232 typename associated_immediate_executor<T, Executor>::type;
233
234namespace detail {
235
236template <typename T, typename E, typename = void>
237struct associated_immediate_executor_forwarding_base
238{
239};
240
241template <typename T, typename E>
242struct associated_immediate_executor_forwarding_base<T, E,
243 enable_if_t<
244 is_same<
245 typename associated_immediate_executor<T,
246 E>::asio_associated_immediate_executor_is_unspecialised,
247 void
248 >::value
249 >>
250{
251 typedef void asio_associated_immediate_executor_is_unspecialised;
252};
253
254} // namespace detail
255
256/// Specialisation of associated_immediate_executor for
257/// @c std::reference_wrapper.
258template <typename T, typename Executor>
259struct associated_immediate_executor<reference_wrapper<T>, Executor>
260#if !defined(GENERATING_DOCUMENTATION)
261 : detail::associated_immediate_executor_forwarding_base<T, Executor>
262#endif // !defined(GENERATING_DOCUMENTATION)
263{
264 /// Forwards @c type to the associator specialisation for the unwrapped type
265 /// @c T.
266 typedef typename associated_immediate_executor<T, Executor>::type type;
267
268 /// Forwards the request to get the executor to the associator specialisation
269 /// for the unwrapped type @c T.
270 static auto get(reference_wrapper<T> t, const Executor& ex) noexcept
271 -> decltype(associated_immediate_executor<T, Executor>::get(t.get(), ex))
272 {
273 return associated_immediate_executor<T, Executor>::get(t.get(), ex);
274 }
275};
276
277} // namespace asio
278} // namespace boost
279
280#include <boost/asio/detail/pop_options.hpp>
281
282#endif // BOOST_ASIO_ASSOCIATED_IMMEDIATE_EXECUTOR_HPP
283

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