1 //
2 // associated_executor.hpp
3 // ~~~~~~~~~~~~~~~~~~~~~~~
4 //
5 // Copyright (c) 2003-2021 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/detail/type_traits.hpp>
20 #include <boost/asio/execution/executor.hpp>
21 #include <boost/asio/is_executor.hpp>
22 #include <boost/asio/system_executor.hpp>
23 
24 #include <boost/asio/detail/push_options.hpp>
25 
26 namespace boost {
27 namespace asio {
28 namespace detail {
29 
30 template <typename T, typename E, typename = void>
31 struct associated_executor_impl
32 {
33   typedef void asio_associated_executor_is_unspecialised;
34 
35   typedef E type;
36 
getboost::asio::detail::associated_executor_impl37   static type get(const T&, const E& e = E()) BOOST_ASIO_NOEXCEPT
38   {
39     return e;
40   }
41 };
42 
43 template <typename T, typename E>
44 struct associated_executor_impl<T, E,
45   typename void_type<typename T::executor_type>::type>
46 {
47   typedef typename T::executor_type type;
48 
getboost::asio::detail::associated_executor_impl49   static type get(const T& t, const E& = E()) BOOST_ASIO_NOEXCEPT
50   {
51     return t.get_executor();
52   }
53 };
54 
55 } // namespace detail
56 
57 /// Traits type used to obtain the executor associated with an object.
58 /**
59  * A program may specialise this traits type if the @c T template parameter in
60  * the specialisation is a user-defined type. The template parameter @c
61  * Executor shall be a type meeting the Executor requirements.
62  *
63  * Specialisations shall meet the following requirements, where @c t is a const
64  * reference to an object of type @c T, and @c e is an object of type @c
65  * Executor.
66  *
67  * @li Provide a nested typedef @c type that identifies a type meeting the
68  * Executor requirements.
69  *
70  * @li Provide a noexcept static member function named @c get, callable as @c
71  * get(t) and with return type @c type.
72  *
73  * @li Provide a noexcept static member function named @c get, callable as @c
74  * get(t,e) and with return type @c type.
75  */
76 template <typename T, typename Executor = system_executor>
77 struct associated_executor
78 #if !defined(GENERATING_DOCUMENTATION)
79   : detail::associated_executor_impl<T, Executor>
80 #endif // !defined(GENERATING_DOCUMENTATION)
81 {
82 #if defined(GENERATING_DOCUMENTATION)
83   /// If @c T has a nested type @c executor_type, <tt>T::executor_type</tt>.
84   /// Otherwise @c Executor.
85   typedef see_below type;
86 
87   /// If @c T has a nested type @c executor_type, returns
88   /// <tt>t.get_executor()</tt>. Otherwise returns @c ex.
89   static type get(const T& t,
90       const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT;
91 #endif // defined(GENERATING_DOCUMENTATION)
92 };
93 
94 /// Helper function to obtain an object's associated executor.
95 /**
96  * @returns <tt>associated_executor<T>::get(t)</tt>
97  */
98 template <typename T>
99 inline typename associated_executor<T>::type
get_associated_executor(const T & t)100 get_associated_executor(const T& t) BOOST_ASIO_NOEXCEPT
101 {
102   return associated_executor<T>::get(t);
103 }
104 
105 /// Helper function to obtain an object's associated executor.
106 /**
107  * @returns <tt>associated_executor<T, Executor>::get(t, ex)</tt>
108  */
109 template <typename T, typename Executor>
110 inline typename associated_executor<T, Executor>::type
get_associated_executor(const T & t,const Executor & ex,typename constraint<is_executor<Executor>::value||execution::is_executor<Executor>::value>::type=0)111 get_associated_executor(const T& t, const Executor& ex,
112     typename constraint<
113       is_executor<Executor>::value || execution::is_executor<Executor>::value
114     >::type = 0) BOOST_ASIO_NOEXCEPT
115 {
116   return associated_executor<T, Executor>::get(t, ex);
117 }
118 
119 /// Helper function to obtain an object's associated executor.
120 /**
121  * @returns <tt>associated_executor<T, typename
122  * ExecutionContext::executor_type>::get(t, ctx.get_executor())</tt>
123  */
124 template <typename T, typename ExecutionContext>
125 inline typename associated_executor<T,
126   typename ExecutionContext::executor_type>::type
get_associated_executor(const T & t,ExecutionContext & ctx,typename constraint<is_convertible<ExecutionContext &,execution_context &>::value>::type=0)127 get_associated_executor(const T& t, ExecutionContext& ctx,
128     typename constraint<is_convertible<ExecutionContext&,
129       execution_context&>::value>::type = 0) BOOST_ASIO_NOEXCEPT
130 {
131   return associated_executor<T,
132     typename ExecutionContext::executor_type>::get(t, ctx.get_executor());
133 }
134 
135 #if defined(BOOST_ASIO_HAS_ALIAS_TEMPLATES)
136 
137 template <typename T, typename Executor = system_executor>
138 using associated_executor_t = typename associated_executor<T, Executor>::type;
139 
140 #endif // defined(BOOST_ASIO_HAS_ALIAS_TEMPLATES)
141 
142 namespace detail {
143 
144 template <typename T, typename E, typename = void>
145 struct associated_executor_forwarding_base
146 {
147 };
148 
149 template <typename T, typename E>
150 struct associated_executor_forwarding_base<T, E,
151     typename enable_if<
152       is_same<
153         typename associated_executor<T,
154           E>::asio_associated_executor_is_unspecialised,
155         void
156       >::value
157     >::type>
158 {
159   typedef void asio_associated_executor_is_unspecialised;
160 };
161 
162 } // namespace detail
163 } // namespace asio
164 } // namespace boost
165 
166 #include <boost/asio/detail/pop_options.hpp>
167 
168 #endif // BOOST_ASIO_ASSOCIATED_EXECUTOR_HPP
169