1 //
2 // execution/detail/submit_receiver.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_DETAIL_SUBMIT_RECEIVER_HPP
12 #define BOOST_ASIO_EXECUTION_DETAIL_SUBMIT_RECEIVER_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/detail/variadic_templates.hpp>
21 #include <boost/asio/execution/connect.hpp>
22 #include <boost/asio/execution/receiver.hpp>
23 #include <boost/asio/execution/set_done.hpp>
24 #include <boost/asio/execution/set_error.hpp>
25 #include <boost/asio/execution/set_value.hpp>
26 #include <boost/asio/traits/set_done_member.hpp>
27 #include <boost/asio/traits/set_error_member.hpp>
28 #include <boost/asio/traits/set_value_member.hpp>
29 
30 #include <boost/asio/detail/push_options.hpp>
31 
32 namespace boost {
33 namespace asio {
34 namespace execution {
35 namespace detail {
36 
37 template <typename Sender, typename Receiver>
38 struct submit_receiver;
39 
40 template <typename Sender, typename Receiver>
41 struct submit_receiver_wrapper
42 {
43   submit_receiver<Sender, Receiver>* p_;
44 
submit_receiver_wrapperboost::asio::execution::detail::submit_receiver_wrapper45   explicit submit_receiver_wrapper(submit_receiver<Sender, Receiver>* p)
46     : p_(p)
47   {
48   }
49 
50 #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
51 
52   template <typename... Args>
53   typename enable_if<is_receiver_of<Receiver, Args...>::value>::type
set_valueboost::asio::execution::detail::submit_receiver_wrapper54   set_value(BOOST_ASIO_MOVE_ARG(Args)... args) BOOST_ASIO_RVALUE_REF_QUAL
55     BOOST_ASIO_NOEXCEPT_IF((is_nothrow_receiver_of<Receiver, Args...>::value))
56   {
57     execution::set_value(
58         BOOST_ASIO_MOVE_OR_LVALUE(
59           typename remove_cvref<Receiver>::type)(p_->r_),
60         BOOST_ASIO_MOVE_CAST(Args)(args)...);
61     delete p_;
62   }
63 
64 #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
65 
set_valueboost::asio::execution::detail::submit_receiver_wrapper66   void set_value() BOOST_ASIO_RVALUE_REF_QUAL
67     BOOST_ASIO_NOEXCEPT_IF((is_nothrow_receiver_of<Receiver>::value))
68   {
69     execution::set_value(
70         BOOST_ASIO_MOVE_OR_LVALUE(
71           typename remove_cvref<Receiver>::type)(p_->r_));
72     delete p_;
73   }
74 
75 #define BOOST_ASIO_PRIVATE_SUBMIT_RECEIVER_SET_VALUE_DEF(n) \
76   template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \
77   typename enable_if<is_receiver_of<Receiver, \
78     BOOST_ASIO_VARIADIC_TARGS(n)>::value>::type \
79   set_value(BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) BOOST_ASIO_RVALUE_REF_QUAL \
80     BOOST_ASIO_NOEXCEPT_IF((is_nothrow_receiver_of< \
81       Receiver, BOOST_ASIO_VARIADIC_TARGS(n)>::value)) \
82   { \
83     execution::set_value( \
84         BOOST_ASIO_MOVE_OR_LVALUE( \
85           typename remove_cvref<Receiver>::type)(p_->r_), \
86         BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \
87     delete p_; \
88   } \
89   /**/
BOOST_ASIO_VARIADIC_GENERATEboost::asio::execution::detail::submit_receiver_wrapper90 BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_SUBMIT_RECEIVER_SET_VALUE_DEF)
91 #undef BOOST_ASIO_PRIVATE_SUBMIT_RECEIVER_SET_VALUE_DEF
92 
93 #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
94 
95   template <typename E>
96   void set_error(BOOST_ASIO_MOVE_ARG(E) e)
97     BOOST_ASIO_RVALUE_REF_QUAL BOOST_ASIO_NOEXCEPT
98   {
99     execution::set_error(
100         BOOST_ASIO_MOVE_OR_LVALUE(
101           typename remove_cvref<Receiver>::type)(p_->r_),
102         BOOST_ASIO_MOVE_CAST(E)(e));
103     delete p_;
104   }
105 
set_doneboost::asio::execution::detail::submit_receiver_wrapper106   void set_done() BOOST_ASIO_RVALUE_REF_QUAL BOOST_ASIO_NOEXCEPT
107   {
108     execution::set_done(
109         BOOST_ASIO_MOVE_OR_LVALUE(
110           typename remove_cvref<Receiver>::type)(p_->r_));
111     delete p_;
112   }
113 };
114 
115 template <typename Sender, typename Receiver>
116 struct submit_receiver
117 {
118   typename remove_cvref<Receiver>::type r_;
119 #if defined(BOOST_ASIO_HAS_MOVE)
120   typename connect_result<Sender,
121       submit_receiver_wrapper<Sender, Receiver> >::type state_;
122 #else // defined(BOOST_ASIO_HAS_MOVE)
123   typename connect_result<Sender,
124       const submit_receiver_wrapper<Sender, Receiver>& >::type state_;
125 #endif // defined(BOOST_ASIO_HAS_MOVE)
126 
127 #if defined(BOOST_ASIO_HAS_MOVE)
128   template <typename S, typename R>
submit_receiverboost::asio::execution::detail::submit_receiver129   explicit submit_receiver(BOOST_ASIO_MOVE_ARG(S) s, BOOST_ASIO_MOVE_ARG(R) r)
130     : r_(BOOST_ASIO_MOVE_CAST(R)(r)),
131       state_(execution::connect(BOOST_ASIO_MOVE_CAST(S)(s),
132             submit_receiver_wrapper<Sender, Receiver>(this)))
133   {
134   }
135 #else // defined(BOOST_ASIO_HAS_MOVE)
submit_receiverboost::asio::execution::detail::submit_receiver136   explicit submit_receiver(Sender s, Receiver r)
137     : r_(r),
138       state_(execution::connect(s,
139             submit_receiver_wrapper<Sender, Receiver>(this)))
140   {
141   }
142 #endif // defined(BOOST_ASIO_HAS_MOVE)
143 };
144 
145 } // namespace detail
146 } // namespace execution
147 namespace traits {
148 
149 #if !defined(BOOST_ASIO_HAS_DEDUCED_SET_VALUE_MEMBER_TRAIT)
150 
151 #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
152 
153 template <typename Sender, typename Receiver, typename... Args>
154 struct set_value_member<
155     boost::asio::execution::detail::submit_receiver_wrapper<
156       Sender, Receiver>,
157     void(Args...)>
158 {
159   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
160   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept =
161     (boost::asio::execution::is_nothrow_receiver_of<Receiver, Args...>::value));
162   typedef void result_type;
163 };
164 
165 #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
166 
167 template <typename Sender, typename Receiver>
168 struct set_value_member<
169     boost::asio::execution::detail::submit_receiver_wrapper<
170       Sender, Receiver>,
171     void()>
172 {
173   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
174   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept =
175     boost::asio::execution::is_nothrow_receiver_of<Receiver>::value);
176   typedef void result_type;
177 };
178 
179 #define BOOST_ASIO_PRIVATE_SUBMIT_RECEIVER_TRAIT_DEF(n) \
180   template <typename Sender, typename Receiver, \
181       BOOST_ASIO_VARIADIC_TPARAMS(n)> \
182   struct set_value_member< \
183       boost::asio::execution::detail::submit_receiver_wrapper< \
184         Sender, Receiver>, \
185       void(BOOST_ASIO_VARIADIC_TARGS(n))> \
186   { \
187     BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); \
188     BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = \
189       (boost::asio::execution::is_nothrow_receiver_of<Receiver, \
190         BOOST_ASIO_VARIADIC_TARGS(n)>::value)); \
191     typedef void result_type; \
192   }; \
193   /**/
194 BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_SUBMIT_RECEIVER_TRAIT_DEF)
195 #undef BOOST_ASIO_PRIVATE_SUBMIT_RECEIVER_TRAIT_DEF
196 
197 #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
198 
199 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_SET_VALUE_MEMBER_TRAIT)
200 
201 #if !defined(BOOST_ASIO_HAS_DEDUCED_SET_ERROR_MEMBER_TRAIT)
202 
203 template <typename Sender, typename Receiver, typename E>
204 struct set_error_member<
205     boost::asio::execution::detail::submit_receiver_wrapper<
206       Sender, Receiver>, E>
207 {
208   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
209   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
210   typedef void result_type;
211 };
212 
213 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_SET_ERROR_MEMBER_TRAIT)
214 
215 #if !defined(BOOST_ASIO_HAS_DEDUCED_SET_DONE_MEMBER_TRAIT)
216 
217 template <typename Sender, typename Receiver>
218 struct set_done_member<
219     boost::asio::execution::detail::submit_receiver_wrapper<
220       Sender, Receiver> >
221 {
222   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
223   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
224   typedef void result_type;
225 };
226 
227 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_SET_DONE_MEMBER_TRAIT)
228 
229 } // namespace traits
230 } // namespace asio
231 } // namespace boost
232 
233 #include <boost/asio/detail/pop_options.hpp>
234 
235 #endif // BOOST_ASIO_EXECUTION_DETAIL_SUBMIT_RECEIVER_HPP
236