AimRT/install_x64/include/unifex/indexed_for.hpp
2025-01-12 19:51:34 +08:00

189 lines
6.5 KiB
C++

/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* Licensed under the Apache License Version 2.0 with LLVM Exceptions
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* https://llvm.org/LICENSE.txt
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <unifex/config.hpp>
#include <unifex/receiver_concepts.hpp>
#include <unifex/sender_concepts.hpp>
#include <unifex/type_traits.hpp>
#include <unifex/type_list.hpp>
#include <unifex/blocking.hpp>
#include <unifex/get_stop_token.hpp>
#include <unifex/async_trace.hpp>
#include <unifex/std_concepts.hpp>
#include <unifex/bind_back.hpp>
#include <functional>
#include <type_traits>
namespace execution {
class sequenced_policy;
class parallel_policy;
}
#include <unifex/detail/prologue.hpp>
namespace unifex {
namespace _ifor {
template <typename Policy, typename Range, typename Func, typename Receiver>
struct _receiver {
struct type;
};
template <typename Policy, typename Range, typename Func, typename Receiver>
using receiver_t =
typename _receiver<Policy, Range, Func, remove_cvref_t<Receiver>>::type;
template <typename Policy, typename Range, typename Func, typename Receiver>
struct _receiver<Policy, Range, Func, Receiver>::type {
UNIFEX_NO_UNIQUE_ADDRESS Func func_;
UNIFEX_NO_UNIQUE_ADDRESS Policy policy_;
UNIFEX_NO_UNIQUE_ADDRESS Range range_;
UNIFEX_NO_UNIQUE_ADDRESS Receiver receiver_;
// sequenced_policy version supports forward range
template <typename... Values>
static void apply_func_with_policy(const execution::sequenced_policy&, Range&& range, Func&& func, Values&... values)
noexcept(std::is_nothrow_invocable_v<Func, typename std::iterator_traits<typename Range::iterator>::reference, Values...>) {
for(auto idx : range) {
std::invoke(func, idx, values...);
}
}
// parallel_policy version requires random access range
template <typename... Values>
static void apply_func_with_policy(const execution::parallel_policy&, Range&& range, Func&& func, Values&... values)
noexcept(std::is_nothrow_invocable_v<Func, typename std::iterator_traits<typename Range::iterator>::reference, Values...>) {
auto first = range.begin();
using size_type = decltype(range.size());
for (size_type idx = 0; idx < range.size(); ++idx) {
std::invoke(func, first[idx], values...);
}
}
template <typename... Values>
void set_value(Values&&... values) && noexcept {
if constexpr (std::is_nothrow_invocable_v<Func&, typename std::iterator_traits<typename Range::iterator>::reference, Values...>) {
apply_func_with_policy(policy_, (Range&&) range_, (Func &&) func_, values...);
unifex::set_value((Receiver &&) receiver_, (Values &&) values...);
} else {
UNIFEX_TRY {
apply_func_with_policy(policy_, (Range&&) range_, (Func &&) func_, values...);
unifex::set_value((Receiver &&) receiver_, (Values &&) values...);
} UNIFEX_CATCH (...) {
unifex::set_error((Receiver &&) receiver_, std::current_exception());
}
}
}
template <typename Error>
void set_error(Error&& error) && noexcept {
unifex::set_error((Receiver &&) receiver_, (Error &&) error);
}
void set_done() && noexcept {
unifex::set_done((Receiver &&) receiver_);
}
template(typename CPO)
(requires is_receiver_query_cpo_v<CPO>)
friend auto tag_invoke(CPO cpo, const type& r) noexcept(
is_nothrow_callable_v<CPO, const Receiver&>)
-> callable_result_t<CPO, const Receiver&> {
return std::move(cpo)(std::as_const(r.receiver_));
}
template <typename Visit>
friend void tag_invoke(
tag_t<visit_continuations>,
const type& r,
Visit&& visit) {
std::invoke(visit, r.receiver_);
}
};
template <typename Predecessor, typename Policy, typename Range, typename Func>
struct _sender {
struct type;
};
template <typename Predecessor, typename Policy, typename Range, typename Func>
using sender = typename _sender<
remove_cvref_t<Predecessor>,
std::decay_t<Policy>,
std::decay_t<Range>,
std::decay_t<Func>>::type;
template <typename Predecessor, typename Policy, typename Range, typename Func>
struct _sender<Predecessor, Policy, Range, Func>::type {
using sender = type;
UNIFEX_NO_UNIQUE_ADDRESS Predecessor pred_;
UNIFEX_NO_UNIQUE_ADDRESS Policy policy_;
UNIFEX_NO_UNIQUE_ADDRESS Range range_;
UNIFEX_NO_UNIQUE_ADDRESS Func func_;
template <
template <typename...> class Variant,
template <typename...> class Tuple>
using value_types = sender_value_types_t<Predecessor, Variant, Tuple>;
template <template <typename...> class Variant>
using error_types =
typename concat_type_lists_unique_t<
sender_error_types_t<Predecessor, type_list>,
type_list<std::exception_ptr>>::template apply<Variant>;
static constexpr bool sends_done = sender_traits<Predecessor>::sends_done;
friend constexpr auto tag_invoke(
tag_t<blocking>,
const sender& sender) {
return blocking(sender.pred_);
}
template <typename Receiver>
auto connect(Receiver&& receiver) && {
return unifex::connect(
std::forward<Predecessor>(pred_),
_ifor::receiver_t<Policy, Range, Func, Receiver>{
(Func &&) func_,
(Policy &&) policy_,
(Range &&) range_,
(Receiver &&) receiver});
}
};
} // namespace _ifor
namespace _ifor_cpo {
struct _fn {
template <typename Sender, typename Policy, typename Range, typename Func>
auto operator()(Sender&& predecessor, Policy&& policy, Range&& range, Func&& func) const
-> _ifor::sender<Sender, Policy, Range, Func> {
return _ifor::sender<Sender, Policy, Range, Func>{
(Sender &&) predecessor, (Policy &&) policy, (Range &&) range, (Func &&) func};
}
template <typename Policy, typename Range, typename Func>
constexpr auto operator()(Policy&& policy, Range&& range, Func&& f) const
noexcept(is_nothrow_callable_v<
tag_t<bind_back>, _fn, Policy, Range, Func>)
-> bind_back_result_t<_fn, Policy, Range, Func> {
return bind_back(*this, (Policy&&)policy, (Range&&)range, (Func&&)f);
}
} indexed_for{};
} // namespace _ifor_cpo
using _ifor_cpo::indexed_for;
} // namespace unifex
#include <unifex/detail/epilogue.hpp>