]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/asio/experimental/parallel_group.hpp
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / boost / boost / asio / experimental / parallel_group.hpp
CommitLineData
1e59de90
TL
1//
2// experimental/parallel_group.hpp
3// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4//
5// Copyright (c) 2003-2022 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_EXPERIMENTAL_PARALLEL_GROUP_HPP
12#define BOOST_ASIO_EXPERIMENTAL_PARALLEL_GROUP_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 <utility>
20#include <boost/asio/detail/array.hpp>
21#include <boost/asio/experimental/cancellation_condition.hpp>
22
23#include <boost/asio/detail/push_options.hpp>
24
25namespace boost {
26namespace asio {
27namespace experimental {
28namespace detail {
29
30// Helper trait for getting the completion signature from an async operation.
31
32struct parallel_op_signature_probe {};
33
34template <typename T>
35struct parallel_op_signature_probe_result
36{
37 typedef T type;
38};
39
40template <typename Op>
41struct parallel_op_signature
42{
43 typedef typename decltype(declval<Op>()(
44 declval<parallel_op_signature_probe>()))::type type;
45};
46
47// Helper trait for getting a tuple from a completion signature.
48
49template <typename Signature>
50struct parallel_op_signature_as_tuple;
51
52template <typename R, typename... Args>
53struct parallel_op_signature_as_tuple<R(Args...)>
54{
55 typedef std::tuple<typename decay<Args>::type...> type;
56};
57
58// Helper trait for concatenating completion signatures.
59
60template <std::size_t N, typename Offsets, typename... Signatures>
61struct parallel_group_signature;
62
63template <std::size_t N, typename R0, typename... Args0>
64struct parallel_group_signature<N, R0(Args0...)>
65{
66 typedef boost::asio::detail::array<std::size_t, N> order_type;
67 typedef R0 raw_type(Args0...);
68 typedef R0 type(order_type, Args0...);
69};
70
71template <std::size_t N,
72 typename R0, typename... Args0,
73 typename R1, typename... Args1>
74struct parallel_group_signature<N, R0(Args0...), R1(Args1...)>
75{
76 typedef boost::asio::detail::array<std::size_t, N> order_type;
77 typedef R0 raw_type(Args0..., Args1...);
78 typedef R0 type(order_type, Args0..., Args1...);
79};
80
81template <std::size_t N, typename Sig0,
82 typename Sig1, typename... SigN>
83struct parallel_group_signature<N, Sig0, Sig1, SigN...>
84{
85 typedef boost::asio::detail::array<std::size_t, N> order_type;
86 typedef typename parallel_group_signature<N,
87 typename parallel_group_signature<N, Sig0, Sig1>::raw_type,
88 SigN...>::raw_type raw_type;
89 typedef typename parallel_group_signature<N,
90 typename parallel_group_signature<N, Sig0, Sig1>::raw_type,
91 SigN...>::type type;
92};
93
94template <typename Condition, typename Handler,
95 typename... Ops, std::size_t... I>
96void parallel_group_launch(Condition cancellation_condition, Handler handler,
97 std::tuple<Ops...>& ops, std::index_sequence<I...>);
98
99} // namespace detail
100
101/// A group of asynchronous operations that may be launched in parallel.
102/**
103 * See the documentation for boost::asio::experimental::make_parallel_group for
104 * a usage example.
105 */
106template <typename... Ops>
107class parallel_group
108{
109public:
110 /// Constructor.
111 explicit parallel_group(Ops... ops)
112 : ops_(std::move(ops)...)
113 {
114 }
115
116 /// The completion signature for the group of operations.
117 typedef typename detail::parallel_group_signature<sizeof...(Ops),
118 typename detail::parallel_op_signature<Ops>::type...>::type signature;
119
120 /// Initiate an asynchronous wait for the group of operations.
121 /**
122 * Launches the group and asynchronously waits for completion.
123 *
124 * @param cancellation_condition A function object, called on completion of
125 * an operation within the group, that is used to determine whether to cancel
126 * the remaining operations. The function object is passed the arguments of
127 * the completed operation's handler. To trigger cancellation of the remaining
128 * operations, it must return a boost::asio::cancellation_type value other
129 * than <tt>boost::asio::cancellation_type::none</tt>.
130 *
131 * @param token A @ref completion_token whose signature is comprised of
132 * a @c std::array<std::size_t, N> indicating the completion order of the
133 * operations, followed by all operations' completion handler arguments.
134 *
135 * The library provides the following @c cancellation_condition types:
136 *
137 * @li boost::asio::experimental::wait_for_all
138 * @li boost::asio::experimental::wait_for_one
139 * @li boost::asio::experimental::wait_for_one_error
140 * @li boost::asio::experimental::wait_for_one_success
141 */
142 template <typename CancellationCondition,
143 BOOST_ASIO_COMPLETION_TOKEN_FOR(signature) CompletionToken>
144 auto async_wait(CancellationCondition cancellation_condition,
145 CompletionToken&& token)
146 {
147 return boost::asio::async_initiate<CompletionToken, signature>(
148 initiate_async_wait(), token,
149 std::move(cancellation_condition), std::move(ops_));
150 }
151
152private:
153 struct initiate_async_wait
154 {
155 template <typename Handler, typename Condition>
156 void operator()(Handler&& h, Condition&& c, std::tuple<Ops...>&& ops) const
157 {
158 detail::parallel_group_launch(std::move(c), std::move(h),
159 ops, std::make_index_sequence<sizeof...(Ops)>());
160 }
161 };
162
163 std::tuple<Ops...> ops_;
164};
165
166/// Create a group of operations that may be launched in parallel.
167/**
168 * For example:
169 * @code boost::asio::experimental::make_parallel_group(
170 * [&](auto token)
171 * {
172 * return in.async_read_some(boost::asio::buffer(data), token);
173 * },
174 * [&](auto token)
175 * {
176 * return timer.async_wait(token);
177 * }
178 * ).async_wait(
179 * boost::asio::experimental::wait_for_all(),
180 * [](
181 * std::array<std::size_t, 2> completion_order,
182 * boost::system::error_code ec1, std::size_t n1,
183 * boost::system::error_code ec2
184 * )
185 * {
186 * switch (completion_order[0])
187 * {
188 * case 0:
189 * {
190 * std::cout << "descriptor finished: " << ec1 << ", " << n1 << "\n";
191 * }
192 * break;
193 * case 1:
194 * {
195 * std::cout << "timer finished: " << ec2 << "\n";
196 * }
197 * break;
198 * }
199 * }
200 * );
201 * @endcode
202 */
203template <typename... Ops>
204BOOST_ASIO_NODISCARD inline parallel_group<Ops...>
205make_parallel_group(Ops... ops)
206{
207 return parallel_group<Ops...>(std::move(ops)...);
208}
209
210} // namespace experimental
211} // namespace asio
212} // namespace boost
213
214#include <boost/asio/detail/pop_options.hpp>
215
216#include <boost/asio/experimental/impl/parallel_group.hpp>
217
218#endif // BOOST_ASIO_EXPERIMENTAL_PARALLEL_GROUP_HPP