1 //
2 // execution/context_as.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_EXECUTION_CONTEXT_AS_HPP
12 #define BOOST_ASIO_EXECUTION_CONTEXT_AS_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/context.hpp>
21 #include <boost/asio/execution/executor.hpp>
22 #include <boost/asio/execution/scheduler.hpp>
23 #include <boost/asio/execution/sender.hpp>
24 #include <boost/asio/is_applicable_property.hpp>
25 #include <boost/asio/query.hpp>
26 #include <boost/asio/traits/query_static_constexpr_member.hpp>
27 #include <boost/asio/traits/static_query.hpp>
28 
29 #include <boost/asio/detail/push_options.hpp>
30 
31 namespace boost {
32 namespace asio {
33 
34 #if defined(GENERATING_DOCUMENTATION)
35 
36 namespace execution {
37 
38 /// A property that is used to obtain the execution context that is associated
39 /// with an executor.
40 template <typename U>
41 struct context_as_t
42 {
43   /// The context_as_t property applies to executors, senders, and schedulers.
44   template <typename T>
45   static constexpr bool is_applicable_property_v =
46     is_executor_v<T> || is_sender_v<T> || is_scheduler_v<T>;
47 
48   /// The context_t property cannot be required.
49   static constexpr bool is_requirable = false;
50 
51   /// The context_t property cannot be preferred.
52   static constexpr bool is_preferable = false;
53 
54   /// The type returned by queries against an @c any_executor.
55   typedef T polymorphic_query_result_type;
56 };
57 
58 /// A special value used for accessing the context_as_t property.
59 template <typename U>
60 constexpr context_as_t context_as;
61 
62 } // namespace execution
63 
64 #else // defined(GENERATING_DOCUMENTATION)
65 
66 namespace execution {
67 
68 template <typename T>
69 struct context_as_t
70 {
71 #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
72   template <typename U>
73   BOOST_ASIO_STATIC_CONSTEXPR(bool,
74     is_applicable_property_v = (
75       is_executor<U>::value
76         || conditional<
77             is_executor<U>::value,
78             false_type,
79             is_sender<U>
80           >::type::value
81         || conditional<
82             is_executor<U>::value,
83             false_type,
84             is_scheduler<U>
85           >::type::value));
86 #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
87 
88   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_requirable = false);
89   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_preferable = false);
90 
91   typedef T polymorphic_query_result_type;
92 
93   BOOST_ASIO_CONSTEXPR context_as_t()
94   {
95   }
96 
97   BOOST_ASIO_CONSTEXPR context_as_t(context_t)
98   {
99   }
100 
101 #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
102   && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
103   template <typename E>
104   static BOOST_ASIO_CONSTEXPR
105   typename context_t::query_static_constexpr_member<E>::result_type
106   static_query()
107     BOOST_ASIO_NOEXCEPT_IF((
108       context_t::query_static_constexpr_member<E>::is_noexcept))
109   {
110     return context_t::query_static_constexpr_member<E>::value();
111   }
112 
113   template <typename E, typename U = decltype(context_as_t::static_query<E>())>
114   static BOOST_ASIO_CONSTEXPR const U static_query_v
115     = context_as_t::static_query<E>();
116 #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
117        //   && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
118 
119   template <typename Executor, typename U>
120   friend BOOST_ASIO_CONSTEXPR U query(
121       const Executor& ex, const context_as_t<U>&,
122       typename enable_if<
123         is_same<T, U>::value
124       >::type* = 0,
125       typename enable_if<
126         can_query<const Executor&, const context_t&>::value
127       >::type* = 0)
128 #if !defined(__clang__) // Clang crashes if noexcept is used here.
129 #if defined(BOOST_ASIO_MSVC) // Visual C++ wants the type to be qualified.
130     BOOST_ASIO_NOEXCEPT_IF((
131       is_nothrow_query<const Executor&, const context_t&>::value))
132 #else // defined(BOOST_ASIO_MSVC)
133     BOOST_ASIO_NOEXCEPT_IF((
134       is_nothrow_query<const Executor&, const context_t&>::value))
135 #endif // defined(BOOST_ASIO_MSVC)
136 #endif // !defined(__clang__)
137   {
138     return boost::asio::query(ex, context);
139   }
140 };
141 
142 #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
143   && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
144 template <typename T> template <typename E, typename U>
145 const U context_as_t<T>::static_query_v;
146 #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
147        //   && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
148 
149 #if (defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) \
150     && defined(BOOST_ASIO_HAS_CONSTEXPR)) \
151   || defined(GENERATING_DOCUMENTATION)
152 template <typename T>
153 constexpr context_as_t<T> context_as{};
154 #endif // (defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
155        //     && defined(BOOST_ASIO_HAS_CONSTEXPR))
156        //   || defined(GENERATING_DOCUMENTATION)
157 
158 } // namespace execution
159 
160 #if !defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
161 
162 template <typename T, typename U>
163 struct is_applicable_property<T, execution::context_as_t<U> >
164   : integral_constant<bool,
165       execution::is_executor<T>::value
166         || conditional<
167             execution::is_executor<T>::value,
168             false_type,
169             execution::is_sender<T>
170           >::type::value
171         || conditional<
172             execution::is_executor<T>::value,
173             false_type,
174             execution::is_scheduler<T>
175           >::type::value>
176 {
177 };
178 
179 #endif // !defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
180 
181 namespace traits {
182 
183 #if !defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
184   || !defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
185 
186 template <typename T, typename U>
187 struct static_query<T, execution::context_as_t<U>,
188   typename enable_if<
189     static_query<T, execution::context_t>::is_valid
190   >::type> : static_query<T, execution::context_t>
191 {
192 };
193 
194 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
195        //   || !defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
196 
197 #if !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_FREE_TRAIT)
198 
199 template <typename T, typename U>
200 struct query_free<T, execution::context_as_t<U>,
201     typename enable_if<
202       can_query<const T&, const execution::context_t&>::value
203     >::type>
204 {
205   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
206   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept =
207     (is_nothrow_query<const T&, const execution::context_t&>::value));
208 
209   typedef U result_type;
210 };
211 
212 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_FREE_TRAIT)
213 
214 } // namespace traits
215 
216 #endif // defined(GENERATING_DOCUMENTATION)
217 
218 } // namespace asio
219 } // namespace boost
220 
221 #include <boost/asio/detail/pop_options.hpp>
222 
223 #endif // BOOST_ASIO_EXECUTION_CONTEXT_AS_HPP
224