// Copyright 2021 gRPC authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // 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. #ifndef GRPC_SRC_CORE_LIB_PROMISE_TRY_SEQ_H #define GRPC_SRC_CORE_LIB_PROMISE_TRY_SEQ_H #include <grpc/support/port_platform.h> #include <type_traits> #include <utility> #include "absl/meta/type_traits.h" #include "absl/status/status.h" #include "absl/status/statusor.h" #include "src/core/lib/promise/detail/basic_seq.h" #include "src/core/lib/promise/detail/promise_like.h" #include "src/core/lib/promise/detail/status.h" #include "src/core/lib/promise/poll.h" namespace grpc_core { namespace promise_detail { template <typename T, typename Ignored = void> struct TrySeqTraitsWithSfinae { … }; TrySeqTraitsWithSfinae<absl::StatusOr<T>>; // If there exists a function 'IsStatusOk(const T&) -> bool' then we assume that // T is a status type for the purposes of promise sequences, and a non-OK T // should terminate the sequence and return. TrySeqTraitsWithSfinae<T, absl::enable_if_t<std::is_same<decltype(IsStatusOk(std::declval<T>())), bool>::value, void>>; template <> struct TrySeqTraitsWithSfinae<absl::Status> { … }; TrySeqTraits; TrySeq; template <typename I, typename F, typename Arg> struct TrySeqIterTraits { … }; template <typename Iter, typename Factory, typename Argument> struct TrySeqIterResultTraits { … }; } // namespace promise_detail // Try a sequence of operations. // * Run the first functor as a promise. // * Feed its success result into the second functor to create a promise, // then run that. // * ... // * Feed the second-final success result into the final functor to create a // promise, then run that, with the overall success result being that // promises success result. // If any step fails, fail everything. // Functors can return StatusOr<> to signal that a value is fed forward, or // Status to indicate only success/failure. In the case of returning Status, // the construction functors take no arguments. template <typename... Functors> promise_detail::TrySeq<Functors...> TrySeq(Functors... functors) { … } // Try a sequence of operations of unknown length. // Asynchronously: // for (element in (begin, end)) { // auto r = wait_for factory(element, argument); // if (!r.ok()) return r; // argument = *r; // } // return argument; template <typename Iter, typename Factory, typename Argument> typename promise_detail::TrySeqIterResultTraits<Iter, Factory, Argument>::Result TrySeqIter(Iter begin, Iter end, Argument argument, Factory factory) { … } } // namespace grpc_core #endif // GRPC_SRC_CORE_LIB_PROMISE_TRY_SEQ_H