1 //
2 // execution/detail/bulk_sender.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_BULK_SENDER_HPP
12 #define BOOST_ASIO_EXECUTION_DETAIL_BULK_SENDER_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/connect.hpp>
21 #include <boost/asio/execution/executor.hpp>
22 #include <boost/asio/execution/set_done.hpp>
23 #include <boost/asio/execution/set_error.hpp>
24 #include <boost/asio/traits/connect_member.hpp>
25 #include <boost/asio/traits/set_done_member.hpp>
26 #include <boost/asio/traits/set_error_member.hpp>
27 #include <boost/asio/traits/set_value_member.hpp>
28 
29 #include <boost/asio/detail/push_options.hpp>
30 
31 namespace boost {
32 namespace asio {
33 namespace execution {
34 namespace detail {
35 
36 template <typename Receiver, typename Function, typename Number, typename Index>
37 struct bulk_receiver
38 {
39   typename remove_cvref<Receiver>::type receiver_;
40   typename decay<Function>::type f_;
41   typename decay<Number>::type n_;
42 
43   template <typename R, typename F, typename N>
bulk_receiverboost::asio::execution::detail::bulk_receiver44   explicit bulk_receiver(BOOST_ASIO_MOVE_ARG(R) r,
45       BOOST_ASIO_MOVE_ARG(F) f, BOOST_ASIO_MOVE_ARG(N) n)
46     : receiver_(BOOST_ASIO_MOVE_CAST(R)(r)),
47       f_(BOOST_ASIO_MOVE_CAST(F)(f)),
48       n_(BOOST_ASIO_MOVE_CAST(N)(n))
49   {
50   }
51 
set_valueboost::asio::execution::detail::bulk_receiver52   void set_value()
53   {
54     for (Index i = 0; i < n_; ++i)
55       f_(i);
56 
57     execution::set_value(
58         BOOST_ASIO_MOVE_OR_LVALUE(
59           typename remove_cvref<Receiver>::type)(receiver_));
60   }
61 
62   template <typename Error>
set_errorboost::asio::execution::detail::bulk_receiver63   void set_error(BOOST_ASIO_MOVE_ARG(Error) e) BOOST_ASIO_NOEXCEPT
64   {
65     execution::set_error(
66         BOOST_ASIO_MOVE_OR_LVALUE(
67           typename remove_cvref<Receiver>::type)(receiver_),
68         BOOST_ASIO_MOVE_CAST(Error)(e));
69   }
70 
set_doneboost::asio::execution::detail::bulk_receiver71   void set_done() BOOST_ASIO_NOEXCEPT
72   {
73     execution::set_done(
74         BOOST_ASIO_MOVE_OR_LVALUE(
75           typename remove_cvref<Receiver>::type)(receiver_));
76   }
77 };
78 
79 template <typename Sender, typename Receiver,
80   typename Function, typename Number>
81 struct bulk_receiver_traits
82 {
83   typedef bulk_receiver<
84       Receiver, Function, Number,
85       typename execution::executor_index<
86         typename remove_cvref<Sender>::type
87       >::type
88     > type;
89 
90 #if defined(BOOST_ASIO_HAS_MOVE)
91   typedef type arg_type;
92 #else // defined(BOOST_ASIO_HAS_MOVE)
93   typedef const type& arg_type;
94 #endif // defined(BOOST_ASIO_HAS_MOVE)
95 };
96 
97 template <typename Sender, typename Function, typename Number>
98 struct bulk_sender : sender_base
99 {
100   typename remove_cvref<Sender>::type sender_;
101   typename decay<Function>::type f_;
102   typename decay<Number>::type n_;
103 
104   template <typename S, typename F, typename N>
bulk_senderboost::asio::execution::detail::bulk_sender105   explicit bulk_sender(BOOST_ASIO_MOVE_ARG(S) s,
106       BOOST_ASIO_MOVE_ARG(F) f, BOOST_ASIO_MOVE_ARG(N) n)
107     : sender_(BOOST_ASIO_MOVE_CAST(S)(s)),
108       f_(BOOST_ASIO_MOVE_CAST(F)(f)),
109       n_(BOOST_ASIO_MOVE_CAST(N)(n))
110   {
111   }
112 
113   template <typename Receiver>
114   typename connect_result<
115       BOOST_ASIO_MOVE_OR_LVALUE_TYPE(typename remove_cvref<Sender>::type),
116       typename bulk_receiver_traits<
117         Sender, Receiver, Function, Number
118       >::arg_type
connectboost::asio::execution::detail::bulk_sender119   >::type connect(BOOST_ASIO_MOVE_ARG(Receiver) r,
120       typename enable_if<
121         can_connect<
122           typename remove_cvref<Sender>::type,
123           typename bulk_receiver_traits<
124             Sender, Receiver, Function, Number
125           >::arg_type
126         >::value
127       >::type* = 0) BOOST_ASIO_RVALUE_REF_QUAL BOOST_ASIO_NOEXCEPT
128   {
129     return execution::connect(
130         BOOST_ASIO_MOVE_OR_LVALUE(typename remove_cvref<Sender>::type)(sender_),
131         typename bulk_receiver_traits<Sender, Receiver, Function, Number>::type(
132           BOOST_ASIO_MOVE_CAST(Receiver)(r),
133           BOOST_ASIO_MOVE_CAST(typename decay<Function>::type)(f_),
134           BOOST_ASIO_MOVE_CAST(typename decay<Number>::type)(n_)));
135   }
136 
137   template <typename Receiver>
138   typename connect_result<
139       const typename remove_cvref<Sender>::type&,
140       typename bulk_receiver_traits<
141         Sender, Receiver, Function, Number
142       >::arg_type
connectboost::asio::execution::detail::bulk_sender143   >::type connect(BOOST_ASIO_MOVE_ARG(Receiver) r,
144       typename enable_if<
145         can_connect<
146           const typename remove_cvref<Sender>::type&,
147           typename bulk_receiver_traits<
148             Sender, Receiver, Function, Number
149           >::arg_type
150         >::value
151       >::type* = 0) const BOOST_ASIO_LVALUE_REF_QUAL BOOST_ASIO_NOEXCEPT
152   {
153     return execution::connect(sender_,
154         typename bulk_receiver_traits<Sender, Receiver, Function, Number>::type(
155           BOOST_ASIO_MOVE_CAST(Receiver)(r), f_, n_));
156   }
157 };
158 
159 } // namespace detail
160 } // namespace execution
161 namespace traits {
162 
163 #if !defined(BOOST_ASIO_HAS_DEDUCED_SET_VALUE_MEMBER_TRAIT)
164 
165 template <typename Receiver, typename Function, typename Number, typename Index>
166 struct set_value_member<
167     execution::detail::bulk_receiver<Receiver, Function, Number, Index>,
168     void()>
169 {
170   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
171   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);
172   typedef void result_type;
173 };
174 
175 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_SET_VALUE_MEMBER_TRAIT)
176 
177 #if !defined(BOOST_ASIO_HAS_DEDUCED_SET_ERROR_MEMBER_TRAIT)
178 
179 template <typename Receiver, typename Function,
180     typename Number, typename Index, typename Error>
181 struct set_error_member<
182     execution::detail::bulk_receiver<Receiver, Function, Number, Index>,
183     Error>
184 {
185   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
186   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
187   typedef void result_type;
188 };
189 
190 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_SET_ERROR_MEMBER_TRAIT)
191 
192 #if !defined(BOOST_ASIO_HAS_DEDUCED_SET_DONE_MEMBER_TRAIT)
193 
194 template <typename Receiver, typename Function, typename Number, typename Index>
195 struct set_done_member<
196     execution::detail::bulk_receiver<Receiver, Function, Number, Index> >
197 {
198   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
199   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
200   typedef void result_type;
201 };
202 
203 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_SET_DONE_MEMBER_TRAIT)
204 
205 #if !defined(BOOST_ASIO_HAS_DEDUCED_CONNECT_MEMBER_TRAIT)
206 
207 template <typename Sender, typename Function,
208     typename Number, typename Receiver>
209 struct connect_member<
210     execution::detail::bulk_sender<Sender, Function, Number>,
211     Receiver,
212     typename enable_if<
213       execution::can_connect<
214         BOOST_ASIO_MOVE_OR_LVALUE_TYPE(typename remove_cvref<Sender>::type),
215         typename execution::detail::bulk_receiver_traits<
216           Sender, Receiver, Function, Number
217         >::arg_type
218       >::value
219     >::type>
220 {
221   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
222   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);
223   typedef typename execution::connect_result<
224       BOOST_ASIO_MOVE_OR_LVALUE_TYPE(typename remove_cvref<Sender>::type),
225       typename execution::detail::bulk_receiver_traits<
226         Sender, Receiver, Function, Number
227       >::arg_type
228     >::type result_type;
229 };
230 
231 template <typename Sender, typename Function,
232     typename Number, typename Receiver>
233 struct connect_member<
234     const execution::detail::bulk_sender<Sender, Function, Number>,
235     Receiver,
236     typename enable_if<
237       execution::can_connect<
238         const typename remove_cvref<Sender>::type&,
239         typename execution::detail::bulk_receiver_traits<
240           Sender, Receiver, Function, Number
241         >::arg_type
242       >::value
243     >::type>
244 {
245   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
246   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);
247   typedef typename execution::connect_result<
248       const typename remove_cvref<Sender>::type&,
249       typename execution::detail::bulk_receiver_traits<
250         Sender, Receiver, Function, Number
251       >::arg_type
252     >::type result_type;
253 };
254 
255 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_CONNECT_MEMBER_TRAIT)
256 
257 } // namespace traits
258 } // namespace asio
259 } // namespace boost
260 
261 #include <boost/asio/detail/pop_options.hpp>
262 
263 #endif // BOOST_ASIO_EXECUTION_DETAIL_BULK_SENDER_HPP
264