// 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_SEQ_H #define GRPC_SRC_CORE_LIB_PROMISE_SEQ_H #include #include #include #include "src/core/lib/promise/detail/basic_seq.h" #include "src/core/lib/promise/detail/promise_like.h" #include "src/core/lib/promise/detail/seq_state.h" #include "src/core/lib/promise/poll.h" #include "src/core/util/debug_location.h" namespace grpc_core { namespace promise_detail { template struct SeqTraits { using UnwrappedType = T; using WrappedType = T; template GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION static auto CallFactory(Next* next, T&& value) { return next->Make(std::forward(value)); } GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION static bool IsOk(const T&) { return true; } static const char* ErrorString(const T&) { abort(); } template static R ReturnValue(T&&) { abort(); } template GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION static Poll CheckResultAndRunNext(PriorResult prior, RunNext run_next) { return run_next(std::move(prior)); } }; template class Seq { public: GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION explicit Seq(P&& promise, Fs&&... factories, DebugLocation whence) : state_(std::forward

(promise), std::forward(factories)..., whence) {} GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION auto operator()() { return state_.PollOnce(); } private: SeqState state_; }; template using SeqIter = BasicSeqIter; } // namespace promise_detail // Sequencing combinator. // Run the first promise. // Pass its result to the second, and run the returned promise. // Pass its result to the third, and run the returned promise. // etc // Return the final value. template GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION inline F Seq(F functor) { return functor; } template GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION inline promise_detail::Seq Seq( F0 f0, F1 f1, DebugLocation whence = {}) { return promise_detail::Seq(std::move(f0), std::move(f1), whence); } template GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION inline promise_detail::Seq Seq( F0 f0, F1 f1, F2 f2, DebugLocation whence = {}) { return promise_detail::Seq(std::move(f0), std::move(f1), std::move(f2), whence); } template GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION inline promise_detail::Seq Seq(F0 f0, F1 f1, F2 f2, F3 f3, DebugLocation whence = {}) { return promise_detail::Seq( std::move(f0), std::move(f1), std::move(f2), std::move(f3), whence); } template GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION inline promise_detail::Seq Seq(F0 f0, F1 f1, F2 f2, F3 f3, F4 f4, DebugLocation whence = {}) { return promise_detail::Seq(std::move(f0), std::move(f1), std::move(f2), std::move(f3), std::move(f4), whence); } template GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION inline promise_detail::Seq Seq(F0 f0, F1 f1, F2 f2, F3 f3, F4 f4, F5 f5, DebugLocation whence = {}) { return promise_detail::Seq( std::move(f0), std::move(f1), std::move(f2), std::move(f3), std::move(f4), std::move(f5), whence); } template GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION promise_detail::Seq Seq(F0 f0, F1 f1, F2 f2, F3 f3, F4 f4, F5 f5, F6 f6, DebugLocation whence = {}) { return promise_detail::Seq( std::move(f0), std::move(f1), std::move(f2), std::move(f3), std::move(f4), std::move(f5), std::move(f6), whence); } template GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION promise_detail::Seq Seq(F0 f0, F1 f1, F2 f2, F3 f3, F4 f4, F5 f5, F6 f6, F7 f7, DebugLocation whence = {}) { return promise_detail::Seq( std::move(f0), std::move(f1), std::move(f2), std::move(f3), std::move(f4), std::move(f5), std::move(f6), std::move(f7), whence); } template GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION promise_detail::Seq Seq(F0 f0, F1 f1, F2 f2, F3 f3, F4 f4, F5 f5, F6 f6, F7 f7, F8 f8, DebugLocation whence = {}) { return promise_detail::Seq( std::move(f0), std::move(f1), std::move(f2), std::move(f3), std::move(f4), std::move(f5), std::move(f6), std::move(f7), std::move(f8), whence); } template GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION promise_detail::Seq Seq(F0 f0, F1 f1, F2 f2, F3 f3, F4 f4, F5 f5, F6 f6, F7 f7, F8 f8, F9 f9, DebugLocation whence = {}) { return promise_detail::Seq( std::move(f0), std::move(f1), std::move(f2), std::move(f3), std::move(f4), std::move(f5), std::move(f6), std::move(f7), std::move(f8), std::move(f9), whence); } template GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION promise_detail::Seq Seq(F0 f0, F1 f1, F2 f2, F3 f3, F4 f4, F5 f5, F6 f6, F7 f7, F8 f8, F9 f9, F10 f10, DebugLocation whence = {}) { return promise_detail::Seq( std::move(f0), std::move(f1), std::move(f2), std::move(f3), std::move(f4), std::move(f5), std::move(f6), std::move(f7), std::move(f8), std::move(f9), std::move(f10), whence); } template GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION promise_detail::Seq Seq(F0 f0, F1 f1, F2 f2, F3 f3, F4 f4, F5 f5, F6 f6, F7 f7, F8 f8, F9 f9, F10 f10, F11 f11, DebugLocation whence = {}) { return promise_detail::Seq( std::move(f0), std::move(f1), std::move(f2), std::move(f3), std::move(f4), std::move(f5), std::move(f6), std::move(f7), std::move(f8), std::move(f9), std::move(f10), std::move(f11), whence); } // Execute a sequence of operations of unknown length. // Asynchronously: // for (element in (begin, end)) { // argument = wait_for factory(element, argument); // } // return argument; template GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION auto SeqIter(Iter begin, Iter end, Argument argument, Factory factory) { return promise_detail::SeqIter( begin, end, std::move(factory), std::move(argument)); } } // namespace grpc_core #endif // GRPC_SRC_CORE_LIB_PROMISE_SEQ_H