summaryrefslogtreecommitdiffstatshomepage
path: root/3rdparty/asio/include/asio/experimental/parallel_group.hpp
diff options
context:
space:
mode:
Diffstat (limited to '3rdparty/asio/include/asio/experimental/parallel_group.hpp')
-rw-r--r--3rdparty/asio/include/asio/experimental/parallel_group.hpp457
1 files changed, 457 insertions, 0 deletions
diff --git a/3rdparty/asio/include/asio/experimental/parallel_group.hpp b/3rdparty/asio/include/asio/experimental/parallel_group.hpp
new file mode 100644
index 00000000000..967fc8802db
--- /dev/null
+++ b/3rdparty/asio/include/asio/experimental/parallel_group.hpp
@@ -0,0 +1,457 @@
+//
+// experimental/parallel_group.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_EXPERIMENTAL_PARALLEL_GROUP_HPP
+#define ASIO_EXPERIMENTAL_PARALLEL_GROUP_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+#include <vector>
+#include "asio/async_result.hpp"
+#include "asio/detail/array.hpp"
+#include "asio/detail/memory.hpp"
+#include "asio/detail/type_traits.hpp"
+#include "asio/detail/utility.hpp"
+#include "asio/experimental/cancellation_condition.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace experimental {
+namespace detail {
+
+// Helper trait for getting a tuple from a completion signature.
+
+template <typename Signature>
+struct parallel_op_signature_as_tuple;
+
+template <typename R, typename... Args>
+struct parallel_op_signature_as_tuple<R(Args...)>
+{
+ typedef std::tuple<decay_t<Args>...> type;
+};
+
+// Helper trait for concatenating completion signatures.
+
+template <std::size_t N, typename Offsets, typename... Signatures>
+struct parallel_group_signature;
+
+template <std::size_t N, typename R0, typename... Args0>
+struct parallel_group_signature<N, R0(Args0...)>
+{
+ typedef asio::detail::array<std::size_t, N> order_type;
+ typedef R0 raw_type(Args0...);
+ typedef R0 type(order_type, Args0...);
+};
+
+template <std::size_t N,
+ typename R0, typename... Args0,
+ typename R1, typename... Args1>
+struct parallel_group_signature<N, R0(Args0...), R1(Args1...)>
+{
+ typedef asio::detail::array<std::size_t, N> order_type;
+ typedef R0 raw_type(Args0..., Args1...);
+ typedef R0 type(order_type, Args0..., Args1...);
+};
+
+template <std::size_t N, typename Sig0,
+ typename Sig1, typename... SigN>
+struct parallel_group_signature<N, Sig0, Sig1, SigN...>
+{
+ typedef asio::detail::array<std::size_t, N> order_type;
+ typedef typename parallel_group_signature<N,
+ typename parallel_group_signature<N, Sig0, Sig1>::raw_type,
+ SigN...>::raw_type raw_type;
+ typedef typename parallel_group_signature<N,
+ typename parallel_group_signature<N, Sig0, Sig1>::raw_type,
+ SigN...>::type type;
+};
+
+template <typename Condition, typename Handler,
+ typename... Ops, std::size_t... I>
+void parallel_group_launch(Condition cancellation_condition, Handler handler,
+ std::tuple<Ops...>& ops, asio::detail::index_sequence<I...>);
+
+// Helper trait for determining ranged parallel group completion signatures.
+
+template <typename Signature, typename Allocator>
+struct ranged_parallel_group_signature;
+
+template <typename R, typename... Args, typename Allocator>
+struct ranged_parallel_group_signature<R(Args...), Allocator>
+{
+ typedef std::vector<std::size_t,
+ ASIO_REBIND_ALLOC(Allocator, std::size_t)> order_type;
+ typedef R raw_type(
+ std::vector<Args, ASIO_REBIND_ALLOC(Allocator, Args)>...);
+ typedef R type(order_type,
+ std::vector<Args, ASIO_REBIND_ALLOC(Allocator, Args)>...);
+};
+
+template <typename Condition, typename Handler,
+ typename Range, typename Allocator>
+void ranged_parallel_group_launch(Condition cancellation_condition,
+ Handler handler, Range&& range, const Allocator& allocator);
+
+char (&parallel_group_has_iterator_helper(...))[2];
+
+template <typename T>
+char parallel_group_has_iterator_helper(T*, typename T::iterator* = 0);
+
+template <typename T>
+struct parallel_group_has_iterator_typedef
+{
+ enum { value = (sizeof((parallel_group_has_iterator_helper)((T*)(0))) == 1) };
+};
+
+} // namespace detail
+
+/// Type trait used to determine whether a type is a range of asynchronous
+/// operations that can be used with with @c make_parallel_group.
+template <typename T>
+struct is_async_operation_range
+{
+#if defined(GENERATING_DOCUMENTATION)
+ /// The value member is true if the type may be used as a range of
+ /// asynchronous operations.
+ static const bool value;
+#else
+ enum
+ {
+ value = detail::parallel_group_has_iterator_typedef<T>::value
+ };
+#endif
+};
+
+/// A group of asynchronous operations that may be launched in parallel.
+/**
+ * See the documentation for asio::experimental::make_parallel_group for
+ * a usage example.
+ */
+template <typename... Ops>
+class parallel_group
+{
+private:
+ struct initiate_async_wait
+ {
+ template <typename Handler, typename Condition>
+ void operator()(Handler&& h, Condition&& c, std::tuple<Ops...>&& ops) const
+ {
+ detail::parallel_group_launch(
+ std::forward<Condition>(c), std::forward<Handler>(h),
+ ops, asio::detail::index_sequence_for<Ops...>());
+ }
+ };
+
+ std::tuple<Ops...> ops_;
+
+public:
+ /// Constructor.
+ explicit parallel_group(Ops... ops)
+ : ops_(std::move(ops)...)
+ {
+ }
+
+ /// The completion signature for the group of operations.
+ typedef typename detail::parallel_group_signature<sizeof...(Ops),
+ completion_signature_of_t<Ops>...>::type signature;
+
+ /// Initiate an asynchronous wait for the group of operations.
+ /**
+ * Launches the group and asynchronously waits for completion.
+ *
+ * @param cancellation_condition A function object, called on completion of
+ * an operation within the group, that is used to determine whether to cancel
+ * the remaining operations. The function object is passed the arguments of
+ * the completed operation's handler. To trigger cancellation of the remaining
+ * operations, it must return a asio::cancellation_type value other
+ * than <tt>asio::cancellation_type::none</tt>.
+ *
+ * @param token A @ref completion_token whose signature is comprised of
+ * a @c std::array<std::size_t, N> indicating the completion order of the
+ * operations, followed by all operations' completion handler arguments.
+ *
+ * The library provides the following @c cancellation_condition types:
+ *
+ * @li asio::experimental::wait_for_all
+ * @li asio::experimental::wait_for_one
+ * @li asio::experimental::wait_for_one_error
+ * @li asio::experimental::wait_for_one_success
+ */
+ template <typename CancellationCondition,
+ ASIO_COMPLETION_TOKEN_FOR(signature) CompletionToken>
+ auto async_wait(CancellationCondition cancellation_condition,
+ CompletionToken&& token)
+ -> decltype(
+ asio::async_initiate<CompletionToken, signature>(
+ declval<initiate_async_wait>(), token,
+ std::move(cancellation_condition), std::move(ops_)))
+ {
+ return asio::async_initiate<CompletionToken, signature>(
+ initiate_async_wait(), token,
+ std::move(cancellation_condition), std::move(ops_));
+ }
+};
+
+/// Create a group of operations that may be launched in parallel.
+/**
+ * For example:
+ * @code asio::experimental::make_parallel_group(
+ * [&](auto token)
+ * {
+ * return in.async_read_some(asio::buffer(data), token);
+ * },
+ * [&](auto token)
+ * {
+ * return timer.async_wait(token);
+ * }
+ * ).async_wait(
+ * asio::experimental::wait_for_all(),
+ * [](
+ * std::array<std::size_t, 2> completion_order,
+ * std::error_code ec1, std::size_t n1,
+ * std::error_code ec2
+ * )
+ * {
+ * switch (completion_order[0])
+ * {
+ * case 0:
+ * {
+ * std::cout << "descriptor finished: " << ec1 << ", " << n1 << "\n";
+ * }
+ * break;
+ * case 1:
+ * {
+ * std::cout << "timer finished: " << ec2 << "\n";
+ * }
+ * break;
+ * }
+ * }
+ * );
+ * @endcode
+ */
+template <typename... Ops>
+ASIO_NODISCARD inline parallel_group<Ops...>
+make_parallel_group(Ops... ops)
+{
+ return parallel_group<Ops...>(std::move(ops)...);
+}
+
+/// A range-based group of asynchronous operations that may be launched in
+/// parallel.
+/**
+ * See the documentation for asio::experimental::make_parallel_group for
+ * a usage example.
+ */
+template <typename Range, typename Allocator = std::allocator<void>>
+class ranged_parallel_group
+{
+private:
+ struct initiate_async_wait
+ {
+ template <typename Handler, typename Condition>
+ void operator()(Handler&& h, Condition&& c,
+ Range&& range, const Allocator& allocator) const
+ {
+ detail::ranged_parallel_group_launch(std::move(c),
+ std::move(h), std::forward<Range>(range), allocator);
+ }
+ };
+
+ Range range_;
+ Allocator allocator_;
+
+public:
+ /// Constructor.
+ explicit ranged_parallel_group(Range range,
+ const Allocator& allocator = Allocator())
+ : range_(std::move(range)),
+ allocator_(allocator)
+ {
+ }
+
+ /// The completion signature for the group of operations.
+ typedef typename detail::ranged_parallel_group_signature<
+ completion_signature_of_t<
+ decay_t<decltype(*std::declval<typename Range::iterator>())>>,
+ Allocator>::type signature;
+
+ /// Initiate an asynchronous wait for the group of operations.
+ /**
+ * Launches the group and asynchronously waits for completion.
+ *
+ * @param cancellation_condition A function object, called on completion of
+ * an operation within the group, that is used to determine whether to cancel
+ * the remaining operations. The function object is passed the arguments of
+ * the completed operation's handler. To trigger cancellation of the remaining
+ * operations, it must return a asio::cancellation_type value other
+ * than <tt>asio::cancellation_type::none</tt>.
+ *
+ * @param token A @ref completion_token whose signature is comprised of
+ * a @c std::vector<std::size_t, Allocator> indicating the completion order of
+ * the operations, followed by a vector for each of the completion signature's
+ * arguments.
+ *
+ * The library provides the following @c cancellation_condition types:
+ *
+ * @li asio::experimental::wait_for_all
+ * @li asio::experimental::wait_for_one
+ * @li asio::experimental::wait_for_one_error
+ * @li asio::experimental::wait_for_one_success
+ */
+ template <typename CancellationCondition,
+ ASIO_COMPLETION_TOKEN_FOR(signature) CompletionToken>
+ auto async_wait(CancellationCondition cancellation_condition,
+ CompletionToken&& token)
+ -> decltype(
+ asio::async_initiate<CompletionToken, signature>(
+ declval<initiate_async_wait>(), token,
+ std::move(cancellation_condition),
+ std::move(range_), allocator_))
+ {
+ return asio::async_initiate<CompletionToken, signature>(
+ initiate_async_wait(), token,
+ std::move(cancellation_condition),
+ std::move(range_), allocator_);
+ }
+};
+
+/// Create a group of operations that may be launched in parallel.
+/**
+ * @param range A range containing the operations to be launched.
+ *
+ * For example:
+ * @code
+ * using op_type = decltype(
+ * socket1.async_read_some(
+ * asio::buffer(data1),
+ * asio::deferred
+ * )
+ * );
+ *
+ * std::vector<op_type> ops;
+ *
+ * ops.push_back(
+ * socket1.async_read_some(
+ * asio::buffer(data1),
+ * asio::deferred
+ * )
+ * );
+ *
+ * ops.push_back(
+ * socket2.async_read_some(
+ * asio::buffer(data2),
+ * asio::deferred
+ * )
+ * );
+ *
+ * asio::experimental::make_parallel_group(ops).async_wait(
+ * asio::experimental::wait_for_all(),
+ * [](
+ * std::vector<std::size_t> completion_order,
+ * std::vector<std::error_code> e,
+ * std::vector<std::size_t> n
+ * )
+ * {
+ * for (std::size_t i = 0; i < completion_order.size(); ++i)
+ * {
+ * std::size_t idx = completion_order[i];
+ * std::cout << "socket " << idx << " finished: ";
+ * std::cout << e[idx] << ", " << n[idx] << "\n";
+ * }
+ * }
+ * );
+ * @endcode
+ */
+template <typename Range>
+ASIO_NODISCARD inline ranged_parallel_group<decay_t<Range>>
+make_parallel_group(Range&& range,
+ constraint_t<
+ is_async_operation_range<decay_t<Range>>::value
+ > = 0)
+{
+ return ranged_parallel_group<decay_t<Range>>(std::forward<Range>(range));
+}
+
+/// Create a group of operations that may be launched in parallel.
+/**
+ * @param allocator Specifies the allocator to be used with the result vectors.
+ *
+ * @param range A range containing the operations to be launched.
+ *
+ * For example:
+ * @code
+ * using op_type = decltype(
+ * socket1.async_read_some(
+ * asio::buffer(data1),
+ * asio::deferred
+ * )
+ * );
+ *
+ * std::vector<op_type> ops;
+ *
+ * ops.push_back(
+ * socket1.async_read_some(
+ * asio::buffer(data1),
+ * asio::deferred
+ * )
+ * );
+ *
+ * ops.push_back(
+ * socket2.async_read_some(
+ * asio::buffer(data2),
+ * asio::deferred
+ * )
+ * );
+ *
+ * asio::experimental::make_parallel_group(
+ * std::allocator_arg_t,
+ * my_allocator,
+ * ops
+ * ).async_wait(
+ * asio::experimental::wait_for_all(),
+ * [](
+ * std::vector<std::size_t> completion_order,
+ * std::vector<std::error_code> e,
+ * std::vector<std::size_t> n
+ * )
+ * {
+ * for (std::size_t i = 0; i < completion_order.size(); ++i)
+ * {
+ * std::size_t idx = completion_order[i];
+ * std::cout << "socket " << idx << " finished: ";
+ * std::cout << e[idx] << ", " << n[idx] << "\n";
+ * }
+ * }
+ * );
+ * @endcode
+ */
+template <typename Allocator, typename Range>
+ASIO_NODISCARD inline ranged_parallel_group<decay_t<Range>, Allocator>
+make_parallel_group(allocator_arg_t, const Allocator& allocator, Range&& range,
+ constraint_t<
+ is_async_operation_range<decay_t<Range>>::value
+ > = 0)
+{
+ return ranged_parallel_group<decay_t<Range>, Allocator>(
+ std::forward<Range>(range), allocator);
+}
+
+} // namespace experimental
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#include "asio/experimental/impl/parallel_group.hpp"
+
+#endif // ASIO_EXPERIMENTAL_PARALLEL_GROUP_HPP