From 6d35000c17d96819184f344183b07104f5b7eb16 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Mon, 18 Dec 2023 13:47:15 -0800 Subject: [PATCH] [promises] Log errors in TrySeq (#35319) When an error occurs in `TrySeq`, log the error. Also, in the trace statements, capture the file/line that the sequence was constructed at, and log that with the traces. Closes #35319 COPYBARA_INTEGRATE_REVIEW=https://github.com/grpc/grpc/pull/35319 from ctiller:trace-seq bc0d47395fb6c8ea373b416a29878bda9b1b8a91 PiperOrigin-RevId: 591999228 --- BUILD | 1 + src/core/BUILD | 8 +- src/core/lib/gprpp/debug_location.h | 4 + src/core/lib/promise/detail/seq_state.h | 567 +++++++++++++++++------- src/core/lib/promise/seq.h | 69 ++- src/core/lib/promise/try_seq.h | 81 +++- tools/codegen/core/gen_seq.py | 25 +- 7 files changed, 584 insertions(+), 171 deletions(-) diff --git a/BUILD b/BUILD index afff44dfd0d..9aedd896979 100644 --- a/BUILD +++ b/BUILD @@ -2511,6 +2511,7 @@ grpc_cc_library( language = "c++", public_hdrs = ["//src/core:lib/gprpp/debug_location.h"], visibility = ["@grpc:debug_location"], + deps = ["gpr_platform"], ) grpc_cc_library( diff --git a/src/core/BUILD b/src/core/BUILD index b7c2cdf9c9d..e5be1db3486 100644 --- a/src/core/BUILD +++ b/src/core/BUILD @@ -754,7 +754,10 @@ grpc_cc_library( grpc_cc_library( name = "seq_state", - external_deps = ["absl/base:core_headers"], + external_deps = [ + "absl/base:core_headers", + "absl/strings", + ], language = "c++", public_hdrs = [ "lib/promise/detail/seq_state.h", @@ -765,6 +768,7 @@ grpc_cc_library( "promise_factory", "promise_like", "promise_trace", + "//:debug_location", "//:gpr", ], ) @@ -780,6 +784,7 @@ grpc_cc_library( "poll", "promise_like", "seq_state", + "//:debug_location", "//:gpr_platform", ], ) @@ -801,6 +806,7 @@ grpc_cc_library( "promise_like", "promise_status", "seq_state", + "//:debug_location", "//:gpr_platform", ], ) diff --git a/src/core/lib/gprpp/debug_location.h b/src/core/lib/gprpp/debug_location.h index 1a29f495383..7e021fd9f78 100644 --- a/src/core/lib/gprpp/debug_location.h +++ b/src/core/lib/gprpp/debug_location.h @@ -19,6 +19,10 @@ #ifndef GRPC_SRC_CORE_LIB_GPRPP_DEBUG_LOCATION_H #define GRPC_SRC_CORE_LIB_GPRPP_DEBUG_LOCATION_H +#include + +#include + #if defined(__has_builtin) #if __has_builtin(__builtin_FILE) #define GRPC_DEFAULT_FILE __builtin_FILE() diff --git a/src/core/lib/promise/detail/seq_state.h b/src/core/lib/promise/detail/seq_state.h index 18616a942b1..97547465fcc 100644 --- a/src/core/lib/promise/detail/seq_state.h +++ b/src/core/lib/promise/detail/seq_state.h @@ -24,10 +24,12 @@ #include #include "absl/base/attributes.h" +#include "absl/strings/str_cat.h" #include #include "src/core/lib/gprpp/construct_destruct.h" +#include "src/core/lib/gprpp/debug_location.h" #include "src/core/lib/promise/detail/promise_factory.h" #include "src/core/lib/promise/detail/promise_like.h" #include "src/core/lib/promise/poll.h" @@ -98,8 +100,9 @@ struct SeqState { }; enum class State : uint8_t { kState0, kState1 }; GPR_NO_UNIQUE_ADDRESS State state = State::kState0; + GPR_NO_UNIQUE_ADDRESS DebugLocation whence; - SeqState(P&& p, F0&& f0) noexcept { + SeqState(P&& p, F0&& f0, DebugLocation whence) noexcept : whence(whence) { Construct(&prior.current_promise, std::forward

(p)); Construct(&prior.next_factory, std::forward(f0)); } @@ -115,13 +118,15 @@ struct SeqState { tail0: Destruct(&prior.next_factory); } - SeqState(const SeqState& other) noexcept : state(other.state) { + SeqState(const SeqState& other) noexcept + : state(other.state), whence(other.whence) { GPR_ASSERT(state == State::kState0); Construct(&prior.current_promise, other.prior.current_promise); Construct(&prior.next_factory, other.prior.next_factory); } SeqState& operator=(const SeqState& other) = delete; - SeqState(SeqState&& other) noexcept : state(other.state) { + SeqState(SeqState&& other) noexcept + : state(other.state), whence(other.whence) { switch (state) { case State::kState0: Construct(&prior.current_promise, @@ -139,15 +144,21 @@ struct SeqState { switch (state) { case State::kState0: { if (grpc_trace_promise_primitives.enabled()) { - gpr_log(GPR_DEBUG, "seq[%p]: begin poll step 1/2", this); + gpr_log(whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: begin poll step 1/2", this); } auto result = prior.current_promise(); PromiseResult0* p = result.value_if_ready(); if (grpc_trace_promise_primitives.enabled()) { gpr_log( - GPR_DEBUG, "seq[%p]: poll step 1/2 gets %s", this, + whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: poll step 1/2 gets %s", this, p != nullptr - ? (PromiseResultTraits0::IsOk(*p) ? "ready" : "early-error") + ? (PromiseResultTraits0::IsOk(*p) + ? "ready" + : absl::StrCat("early-error:", + PromiseResultTraits0::ErrorString(*p)) + .c_str()) : "pending"); } if (p == nullptr) return Pending{}; @@ -166,11 +177,13 @@ struct SeqState { default: case State::kState1: { if (grpc_trace_promise_primitives.enabled()) { - gpr_log(GPR_DEBUG, "seq[%p]: begin poll step 2/2", this); + gpr_log(whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: begin poll step 2/2", this); } auto result = current_promise(); if (grpc_trace_promise_primitives.enabled()) { - gpr_log(GPR_DEBUG, "seq[%p]: poll step 2/2 gets %s", this, + gpr_log(whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: poll step 2/2 gets %s", this, result.ready() ? "ready" : "pending"); } auto* p = result.value_if_ready(); @@ -215,8 +228,10 @@ struct SeqState { }; enum class State : uint8_t { kState0, kState1, kState2 }; GPR_NO_UNIQUE_ADDRESS State state = State::kState0; + GPR_NO_UNIQUE_ADDRESS DebugLocation whence; - SeqState(P&& p, F0&& f0, F1&& f1) noexcept { + SeqState(P&& p, F0&& f0, F1&& f1, DebugLocation whence) noexcept + : whence(whence) { Construct(&prior.prior.current_promise, std::forward

(p)); Construct(&prior.prior.next_factory, std::forward(f0)); Construct(&prior.next_factory, std::forward(f1)); @@ -238,14 +253,16 @@ struct SeqState { tail1: Destruct(&prior.next_factory); } - SeqState(const SeqState& other) noexcept : state(other.state) { + SeqState(const SeqState& other) noexcept + : state(other.state), whence(other.whence) { GPR_ASSERT(state == State::kState0); Construct(&prior.current_promise, other.prior.current_promise); Construct(&prior.prior.next_factory, other.prior.prior.next_factory); Construct(&prior.next_factory, other.prior.next_factory); } SeqState& operator=(const SeqState& other) = delete; - SeqState(SeqState&& other) noexcept : state(other.state) { + SeqState(SeqState&& other) noexcept + : state(other.state), whence(other.whence) { switch (state) { case State::kState0: Construct(&prior.prior.current_promise, @@ -270,15 +287,21 @@ struct SeqState { switch (state) { case State::kState0: { if (grpc_trace_promise_primitives.enabled()) { - gpr_log(GPR_DEBUG, "seq[%p]: begin poll step 1/3", this); + gpr_log(whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: begin poll step 1/3", this); } auto result = prior.prior.current_promise(); PromiseResult0* p = result.value_if_ready(); if (grpc_trace_promise_primitives.enabled()) { gpr_log( - GPR_DEBUG, "seq[%p]: poll step 1/3 gets %s", this, + whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: poll step 1/3 gets %s", this, p != nullptr - ? (PromiseResultTraits0::IsOk(*p) ? "ready" : "early-error") + ? (PromiseResultTraits0::IsOk(*p) + ? "ready" + : absl::StrCat("early-error:", + PromiseResultTraits0::ErrorString(*p)) + .c_str()) : "pending"); } if (p == nullptr) return Pending{}; @@ -296,15 +319,21 @@ struct SeqState { ABSL_FALLTHROUGH_INTENDED; case State::kState1: { if (grpc_trace_promise_primitives.enabled()) { - gpr_log(GPR_DEBUG, "seq[%p]: begin poll step 2/3", this); + gpr_log(whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: begin poll step 2/3", this); } auto result = prior.current_promise(); PromiseResult1* p = result.value_if_ready(); if (grpc_trace_promise_primitives.enabled()) { gpr_log( - GPR_DEBUG, "seq[%p]: poll step 2/3 gets %s", this, + whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: poll step 2/3 gets %s", this, p != nullptr - ? (PromiseResultTraits1::IsOk(*p) ? "ready" : "early-error") + ? (PromiseResultTraits1::IsOk(*p) + ? "ready" + : absl::StrCat("early-error:", + PromiseResultTraits1::ErrorString(*p)) + .c_str()) : "pending"); } if (p == nullptr) return Pending{}; @@ -323,11 +352,13 @@ struct SeqState { default: case State::kState2: { if (grpc_trace_promise_primitives.enabled()) { - gpr_log(GPR_DEBUG, "seq[%p]: begin poll step 3/3", this); + gpr_log(whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: begin poll step 3/3", this); } auto result = current_promise(); if (grpc_trace_promise_primitives.enabled()) { - gpr_log(GPR_DEBUG, "seq[%p]: poll step 3/3 gets %s", this, + gpr_log(whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: poll step 3/3 gets %s", this, result.ready() ? "ready" : "pending"); } auto* p = result.value_if_ready(); @@ -384,8 +415,10 @@ struct SeqState { }; enum class State : uint8_t { kState0, kState1, kState2, kState3 }; GPR_NO_UNIQUE_ADDRESS State state = State::kState0; + GPR_NO_UNIQUE_ADDRESS DebugLocation whence; - SeqState(P&& p, F0&& f0, F1&& f1, F2&& f2) noexcept { + SeqState(P&& p, F0&& f0, F1&& f1, F2&& f2, DebugLocation whence) noexcept + : whence(whence) { Construct(&prior.prior.prior.current_promise, std::forward

(p)); Construct(&prior.prior.prior.next_factory, std::forward(f0)); Construct(&prior.prior.next_factory, std::forward(f1)); @@ -413,7 +446,8 @@ struct SeqState { tail2: Destruct(&prior.next_factory); } - SeqState(const SeqState& other) noexcept : state(other.state) { + SeqState(const SeqState& other) noexcept + : state(other.state), whence(other.whence) { GPR_ASSERT(state == State::kState0); Construct(&prior.current_promise, other.prior.current_promise); Construct(&prior.prior.prior.next_factory, @@ -422,7 +456,8 @@ struct SeqState { Construct(&prior.next_factory, other.prior.next_factory); } SeqState& operator=(const SeqState& other) = delete; - SeqState(SeqState&& other) noexcept : state(other.state) { + SeqState(SeqState&& other) noexcept + : state(other.state), whence(other.whence) { switch (state) { case State::kState0: Construct(&prior.prior.prior.current_promise, @@ -454,15 +489,21 @@ struct SeqState { switch (state) { case State::kState0: { if (grpc_trace_promise_primitives.enabled()) { - gpr_log(GPR_DEBUG, "seq[%p]: begin poll step 1/4", this); + gpr_log(whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: begin poll step 1/4", this); } auto result = prior.prior.prior.current_promise(); PromiseResult0* p = result.value_if_ready(); if (grpc_trace_promise_primitives.enabled()) { gpr_log( - GPR_DEBUG, "seq[%p]: poll step 1/4 gets %s", this, + whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: poll step 1/4 gets %s", this, p != nullptr - ? (PromiseResultTraits0::IsOk(*p) ? "ready" : "early-error") + ? (PromiseResultTraits0::IsOk(*p) + ? "ready" + : absl::StrCat("early-error:", + PromiseResultTraits0::ErrorString(*p)) + .c_str()) : "pending"); } if (p == nullptr) return Pending{}; @@ -480,15 +521,21 @@ struct SeqState { ABSL_FALLTHROUGH_INTENDED; case State::kState1: { if (grpc_trace_promise_primitives.enabled()) { - gpr_log(GPR_DEBUG, "seq[%p]: begin poll step 2/4", this); + gpr_log(whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: begin poll step 2/4", this); } auto result = prior.prior.current_promise(); PromiseResult1* p = result.value_if_ready(); if (grpc_trace_promise_primitives.enabled()) { gpr_log( - GPR_DEBUG, "seq[%p]: poll step 2/4 gets %s", this, + whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: poll step 2/4 gets %s", this, p != nullptr - ? (PromiseResultTraits1::IsOk(*p) ? "ready" : "early-error") + ? (PromiseResultTraits1::IsOk(*p) + ? "ready" + : absl::StrCat("early-error:", + PromiseResultTraits1::ErrorString(*p)) + .c_str()) : "pending"); } if (p == nullptr) return Pending{}; @@ -506,15 +553,21 @@ struct SeqState { ABSL_FALLTHROUGH_INTENDED; case State::kState2: { if (grpc_trace_promise_primitives.enabled()) { - gpr_log(GPR_DEBUG, "seq[%p]: begin poll step 3/4", this); + gpr_log(whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: begin poll step 3/4", this); } auto result = prior.current_promise(); PromiseResult2* p = result.value_if_ready(); if (grpc_trace_promise_primitives.enabled()) { gpr_log( - GPR_DEBUG, "seq[%p]: poll step 3/4 gets %s", this, + whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: poll step 3/4 gets %s", this, p != nullptr - ? (PromiseResultTraits2::IsOk(*p) ? "ready" : "early-error") + ? (PromiseResultTraits2::IsOk(*p) + ? "ready" + : absl::StrCat("early-error:", + PromiseResultTraits2::ErrorString(*p)) + .c_str()) : "pending"); } if (p == nullptr) return Pending{}; @@ -533,11 +586,13 @@ struct SeqState { default: case State::kState3: { if (grpc_trace_promise_primitives.enabled()) { - gpr_log(GPR_DEBUG, "seq[%p]: begin poll step 4/4", this); + gpr_log(whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: begin poll step 4/4", this); } auto result = current_promise(); if (grpc_trace_promise_primitives.enabled()) { - gpr_log(GPR_DEBUG, "seq[%p]: poll step 4/4 gets %s", this, + gpr_log(whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: poll step 4/4 gets %s", this, result.ready() ? "ready" : "pending"); } auto* p = result.value_if_ready(); @@ -606,8 +661,11 @@ struct SeqState { }; enum class State : uint8_t { kState0, kState1, kState2, kState3, kState4 }; GPR_NO_UNIQUE_ADDRESS State state = State::kState0; + GPR_NO_UNIQUE_ADDRESS DebugLocation whence; - SeqState(P&& p, F0&& f0, F1&& f1, F2&& f2, F3&& f3) noexcept { + SeqState(P&& p, F0&& f0, F1&& f1, F2&& f2, F3&& f3, + DebugLocation whence) noexcept + : whence(whence) { Construct(&prior.prior.prior.prior.current_promise, std::forward

(p)); Construct(&prior.prior.prior.prior.next_factory, std::forward(f0)); Construct(&prior.prior.prior.next_factory, std::forward(f1)); @@ -641,7 +699,8 @@ struct SeqState { tail3: Destruct(&prior.next_factory); } - SeqState(const SeqState& other) noexcept : state(other.state) { + SeqState(const SeqState& other) noexcept + : state(other.state), whence(other.whence) { GPR_ASSERT(state == State::kState0); Construct(&prior.current_promise, other.prior.current_promise); Construct(&prior.prior.prior.prior.next_factory, @@ -652,7 +711,8 @@ struct SeqState { Construct(&prior.next_factory, other.prior.next_factory); } SeqState& operator=(const SeqState& other) = delete; - SeqState(SeqState&& other) noexcept : state(other.state) { + SeqState(SeqState&& other) noexcept + : state(other.state), whence(other.whence) { switch (state) { case State::kState0: Construct(&prior.prior.prior.prior.current_promise, @@ -691,15 +751,21 @@ struct SeqState { switch (state) { case State::kState0: { if (grpc_trace_promise_primitives.enabled()) { - gpr_log(GPR_DEBUG, "seq[%p]: begin poll step 1/5", this); + gpr_log(whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: begin poll step 1/5", this); } auto result = prior.prior.prior.prior.current_promise(); PromiseResult0* p = result.value_if_ready(); if (grpc_trace_promise_primitives.enabled()) { gpr_log( - GPR_DEBUG, "seq[%p]: poll step 1/5 gets %s", this, + whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: poll step 1/5 gets %s", this, p != nullptr - ? (PromiseResultTraits0::IsOk(*p) ? "ready" : "early-error") + ? (PromiseResultTraits0::IsOk(*p) + ? "ready" + : absl::StrCat("early-error:", + PromiseResultTraits0::ErrorString(*p)) + .c_str()) : "pending"); } if (p == nullptr) return Pending{}; @@ -717,15 +783,21 @@ struct SeqState { ABSL_FALLTHROUGH_INTENDED; case State::kState1: { if (grpc_trace_promise_primitives.enabled()) { - gpr_log(GPR_DEBUG, "seq[%p]: begin poll step 2/5", this); + gpr_log(whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: begin poll step 2/5", this); } auto result = prior.prior.prior.current_promise(); PromiseResult1* p = result.value_if_ready(); if (grpc_trace_promise_primitives.enabled()) { gpr_log( - GPR_DEBUG, "seq[%p]: poll step 2/5 gets %s", this, + whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: poll step 2/5 gets %s", this, p != nullptr - ? (PromiseResultTraits1::IsOk(*p) ? "ready" : "early-error") + ? (PromiseResultTraits1::IsOk(*p) + ? "ready" + : absl::StrCat("early-error:", + PromiseResultTraits1::ErrorString(*p)) + .c_str()) : "pending"); } if (p == nullptr) return Pending{}; @@ -743,15 +815,21 @@ struct SeqState { ABSL_FALLTHROUGH_INTENDED; case State::kState2: { if (grpc_trace_promise_primitives.enabled()) { - gpr_log(GPR_DEBUG, "seq[%p]: begin poll step 3/5", this); + gpr_log(whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: begin poll step 3/5", this); } auto result = prior.prior.current_promise(); PromiseResult2* p = result.value_if_ready(); if (grpc_trace_promise_primitives.enabled()) { gpr_log( - GPR_DEBUG, "seq[%p]: poll step 3/5 gets %s", this, + whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: poll step 3/5 gets %s", this, p != nullptr - ? (PromiseResultTraits2::IsOk(*p) ? "ready" : "early-error") + ? (PromiseResultTraits2::IsOk(*p) + ? "ready" + : absl::StrCat("early-error:", + PromiseResultTraits2::ErrorString(*p)) + .c_str()) : "pending"); } if (p == nullptr) return Pending{}; @@ -769,15 +847,21 @@ struct SeqState { ABSL_FALLTHROUGH_INTENDED; case State::kState3: { if (grpc_trace_promise_primitives.enabled()) { - gpr_log(GPR_DEBUG, "seq[%p]: begin poll step 4/5", this); + gpr_log(whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: begin poll step 4/5", this); } auto result = prior.current_promise(); PromiseResult3* p = result.value_if_ready(); if (grpc_trace_promise_primitives.enabled()) { gpr_log( - GPR_DEBUG, "seq[%p]: poll step 4/5 gets %s", this, + whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: poll step 4/5 gets %s", this, p != nullptr - ? (PromiseResultTraits3::IsOk(*p) ? "ready" : "early-error") + ? (PromiseResultTraits3::IsOk(*p) + ? "ready" + : absl::StrCat("early-error:", + PromiseResultTraits3::ErrorString(*p)) + .c_str()) : "pending"); } if (p == nullptr) return Pending{}; @@ -796,11 +880,13 @@ struct SeqState { default: case State::kState4: { if (grpc_trace_promise_primitives.enabled()) { - gpr_log(GPR_DEBUG, "seq[%p]: begin poll step 5/5", this); + gpr_log(whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: begin poll step 5/5", this); } auto result = current_promise(); if (grpc_trace_promise_primitives.enabled()) { - gpr_log(GPR_DEBUG, "seq[%p]: poll step 5/5 gets %s", this, + gpr_log(whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: poll step 5/5 gets %s", this, result.ready() ? "ready" : "pending"); } auto* p = result.value_if_ready(); @@ -888,8 +974,11 @@ struct SeqState { kState5 }; GPR_NO_UNIQUE_ADDRESS State state = State::kState0; + GPR_NO_UNIQUE_ADDRESS DebugLocation whence; - SeqState(P&& p, F0&& f0, F1&& f1, F2&& f2, F3&& f3, F4&& f4) noexcept { + SeqState(P&& p, F0&& f0, F1&& f1, F2&& f2, F3&& f3, F4&& f4, + DebugLocation whence) noexcept + : whence(whence) { Construct(&prior.prior.prior.prior.prior.current_promise, std::forward

(p)); Construct(&prior.prior.prior.prior.prior.next_factory, @@ -931,7 +1020,8 @@ struct SeqState { tail4: Destruct(&prior.next_factory); } - SeqState(const SeqState& other) noexcept : state(other.state) { + SeqState(const SeqState& other) noexcept + : state(other.state), whence(other.whence) { GPR_ASSERT(state == State::kState0); Construct(&prior.current_promise, other.prior.current_promise); Construct(&prior.prior.prior.prior.prior.next_factory, @@ -944,7 +1034,8 @@ struct SeqState { Construct(&prior.next_factory, other.prior.next_factory); } SeqState& operator=(const SeqState& other) = delete; - SeqState(SeqState&& other) noexcept : state(other.state) { + SeqState(SeqState&& other) noexcept + : state(other.state), whence(other.whence) { switch (state) { case State::kState0: Construct( @@ -991,15 +1082,21 @@ struct SeqState { switch (state) { case State::kState0: { if (grpc_trace_promise_primitives.enabled()) { - gpr_log(GPR_DEBUG, "seq[%p]: begin poll step 1/6", this); + gpr_log(whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: begin poll step 1/6", this); } auto result = prior.prior.prior.prior.prior.current_promise(); PromiseResult0* p = result.value_if_ready(); if (grpc_trace_promise_primitives.enabled()) { gpr_log( - GPR_DEBUG, "seq[%p]: poll step 1/6 gets %s", this, + whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: poll step 1/6 gets %s", this, p != nullptr - ? (PromiseResultTraits0::IsOk(*p) ? "ready" : "early-error") + ? (PromiseResultTraits0::IsOk(*p) + ? "ready" + : absl::StrCat("early-error:", + PromiseResultTraits0::ErrorString(*p)) + .c_str()) : "pending"); } if (p == nullptr) return Pending{}; @@ -1018,15 +1115,21 @@ struct SeqState { ABSL_FALLTHROUGH_INTENDED; case State::kState1: { if (grpc_trace_promise_primitives.enabled()) { - gpr_log(GPR_DEBUG, "seq[%p]: begin poll step 2/6", this); + gpr_log(whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: begin poll step 2/6", this); } auto result = prior.prior.prior.prior.current_promise(); PromiseResult1* p = result.value_if_ready(); if (grpc_trace_promise_primitives.enabled()) { gpr_log( - GPR_DEBUG, "seq[%p]: poll step 2/6 gets %s", this, + whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: poll step 2/6 gets %s", this, p != nullptr - ? (PromiseResultTraits1::IsOk(*p) ? "ready" : "early-error") + ? (PromiseResultTraits1::IsOk(*p) + ? "ready" + : absl::StrCat("early-error:", + PromiseResultTraits1::ErrorString(*p)) + .c_str()) : "pending"); } if (p == nullptr) return Pending{}; @@ -1044,15 +1147,21 @@ struct SeqState { ABSL_FALLTHROUGH_INTENDED; case State::kState2: { if (grpc_trace_promise_primitives.enabled()) { - gpr_log(GPR_DEBUG, "seq[%p]: begin poll step 3/6", this); + gpr_log(whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: begin poll step 3/6", this); } auto result = prior.prior.prior.current_promise(); PromiseResult2* p = result.value_if_ready(); if (grpc_trace_promise_primitives.enabled()) { gpr_log( - GPR_DEBUG, "seq[%p]: poll step 3/6 gets %s", this, + whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: poll step 3/6 gets %s", this, p != nullptr - ? (PromiseResultTraits2::IsOk(*p) ? "ready" : "early-error") + ? (PromiseResultTraits2::IsOk(*p) + ? "ready" + : absl::StrCat("early-error:", + PromiseResultTraits2::ErrorString(*p)) + .c_str()) : "pending"); } if (p == nullptr) return Pending{}; @@ -1070,15 +1179,21 @@ struct SeqState { ABSL_FALLTHROUGH_INTENDED; case State::kState3: { if (grpc_trace_promise_primitives.enabled()) { - gpr_log(GPR_DEBUG, "seq[%p]: begin poll step 4/6", this); + gpr_log(whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: begin poll step 4/6", this); } auto result = prior.prior.current_promise(); PromiseResult3* p = result.value_if_ready(); if (grpc_trace_promise_primitives.enabled()) { gpr_log( - GPR_DEBUG, "seq[%p]: poll step 4/6 gets %s", this, + whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: poll step 4/6 gets %s", this, p != nullptr - ? (PromiseResultTraits3::IsOk(*p) ? "ready" : "early-error") + ? (PromiseResultTraits3::IsOk(*p) + ? "ready" + : absl::StrCat("early-error:", + PromiseResultTraits3::ErrorString(*p)) + .c_str()) : "pending"); } if (p == nullptr) return Pending{}; @@ -1096,15 +1211,21 @@ struct SeqState { ABSL_FALLTHROUGH_INTENDED; case State::kState4: { if (grpc_trace_promise_primitives.enabled()) { - gpr_log(GPR_DEBUG, "seq[%p]: begin poll step 5/6", this); + gpr_log(whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: begin poll step 5/6", this); } auto result = prior.current_promise(); PromiseResult4* p = result.value_if_ready(); if (grpc_trace_promise_primitives.enabled()) { gpr_log( - GPR_DEBUG, "seq[%p]: poll step 5/6 gets %s", this, + whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: poll step 5/6 gets %s", this, p != nullptr - ? (PromiseResultTraits4::IsOk(*p) ? "ready" : "early-error") + ? (PromiseResultTraits4::IsOk(*p) + ? "ready" + : absl::StrCat("early-error:", + PromiseResultTraits4::ErrorString(*p)) + .c_str()) : "pending"); } if (p == nullptr) return Pending{}; @@ -1123,11 +1244,13 @@ struct SeqState { default: case State::kState5: { if (grpc_trace_promise_primitives.enabled()) { - gpr_log(GPR_DEBUG, "seq[%p]: begin poll step 6/6", this); + gpr_log(whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: begin poll step 6/6", this); } auto result = current_promise(); if (grpc_trace_promise_primitives.enabled()) { - gpr_log(GPR_DEBUG, "seq[%p]: poll step 6/6 gets %s", this, + gpr_log(whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: poll step 6/6 gets %s", this, result.ready() ? "ready" : "pending"); } auto* p = result.value_if_ready(); @@ -1228,9 +1351,11 @@ struct SeqState { kState6 }; GPR_NO_UNIQUE_ADDRESS State state = State::kState0; + GPR_NO_UNIQUE_ADDRESS DebugLocation whence; - SeqState(P&& p, F0&& f0, F1&& f1, F2&& f2, F3&& f3, F4&& f4, - F5&& f5) noexcept { + SeqState(P&& p, F0&& f0, F1&& f1, F2&& f2, F3&& f3, F4&& f4, F5&& f5, + DebugLocation whence) noexcept + : whence(whence) { Construct(&prior.prior.prior.prior.prior.prior.current_promise, std::forward

(p)); Construct(&prior.prior.prior.prior.prior.prior.next_factory, @@ -1279,7 +1404,8 @@ struct SeqState { tail5: Destruct(&prior.next_factory); } - SeqState(const SeqState& other) noexcept : state(other.state) { + SeqState(const SeqState& other) noexcept + : state(other.state), whence(other.whence) { GPR_ASSERT(state == State::kState0); Construct(&prior.current_promise, other.prior.current_promise); Construct(&prior.prior.prior.prior.prior.prior.next_factory, @@ -1294,7 +1420,8 @@ struct SeqState { Construct(&prior.next_factory, other.prior.next_factory); } SeqState& operator=(const SeqState& other) = delete; - SeqState(SeqState&& other) noexcept : state(other.state) { + SeqState(SeqState&& other) noexcept + : state(other.state), whence(other.whence) { switch (state) { case State::kState0: Construct( @@ -1351,15 +1478,21 @@ struct SeqState { switch (state) { case State::kState0: { if (grpc_trace_promise_primitives.enabled()) { - gpr_log(GPR_DEBUG, "seq[%p]: begin poll step 1/7", this); + gpr_log(whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: begin poll step 1/7", this); } auto result = prior.prior.prior.prior.prior.prior.current_promise(); PromiseResult0* p = result.value_if_ready(); if (grpc_trace_promise_primitives.enabled()) { gpr_log( - GPR_DEBUG, "seq[%p]: poll step 1/7 gets %s", this, + whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: poll step 1/7 gets %s", this, p != nullptr - ? (PromiseResultTraits0::IsOk(*p) ? "ready" : "early-error") + ? (PromiseResultTraits0::IsOk(*p) + ? "ready" + : absl::StrCat("early-error:", + PromiseResultTraits0::ErrorString(*p)) + .c_str()) : "pending"); } if (p == nullptr) return Pending{}; @@ -1378,15 +1511,21 @@ struct SeqState { ABSL_FALLTHROUGH_INTENDED; case State::kState1: { if (grpc_trace_promise_primitives.enabled()) { - gpr_log(GPR_DEBUG, "seq[%p]: begin poll step 2/7", this); + gpr_log(whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: begin poll step 2/7", this); } auto result = prior.prior.prior.prior.prior.current_promise(); PromiseResult1* p = result.value_if_ready(); if (grpc_trace_promise_primitives.enabled()) { gpr_log( - GPR_DEBUG, "seq[%p]: poll step 2/7 gets %s", this, + whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: poll step 2/7 gets %s", this, p != nullptr - ? (PromiseResultTraits1::IsOk(*p) ? "ready" : "early-error") + ? (PromiseResultTraits1::IsOk(*p) + ? "ready" + : absl::StrCat("early-error:", + PromiseResultTraits1::ErrorString(*p)) + .c_str()) : "pending"); } if (p == nullptr) return Pending{}; @@ -1405,15 +1544,21 @@ struct SeqState { ABSL_FALLTHROUGH_INTENDED; case State::kState2: { if (grpc_trace_promise_primitives.enabled()) { - gpr_log(GPR_DEBUG, "seq[%p]: begin poll step 3/7", this); + gpr_log(whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: begin poll step 3/7", this); } auto result = prior.prior.prior.prior.current_promise(); PromiseResult2* p = result.value_if_ready(); if (grpc_trace_promise_primitives.enabled()) { gpr_log( - GPR_DEBUG, "seq[%p]: poll step 3/7 gets %s", this, + whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: poll step 3/7 gets %s", this, p != nullptr - ? (PromiseResultTraits2::IsOk(*p) ? "ready" : "early-error") + ? (PromiseResultTraits2::IsOk(*p) + ? "ready" + : absl::StrCat("early-error:", + PromiseResultTraits2::ErrorString(*p)) + .c_str()) : "pending"); } if (p == nullptr) return Pending{}; @@ -1431,15 +1576,21 @@ struct SeqState { ABSL_FALLTHROUGH_INTENDED; case State::kState3: { if (grpc_trace_promise_primitives.enabled()) { - gpr_log(GPR_DEBUG, "seq[%p]: begin poll step 4/7", this); + gpr_log(whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: begin poll step 4/7", this); } auto result = prior.prior.prior.current_promise(); PromiseResult3* p = result.value_if_ready(); if (grpc_trace_promise_primitives.enabled()) { gpr_log( - GPR_DEBUG, "seq[%p]: poll step 4/7 gets %s", this, + whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: poll step 4/7 gets %s", this, p != nullptr - ? (PromiseResultTraits3::IsOk(*p) ? "ready" : "early-error") + ? (PromiseResultTraits3::IsOk(*p) + ? "ready" + : absl::StrCat("early-error:", + PromiseResultTraits3::ErrorString(*p)) + .c_str()) : "pending"); } if (p == nullptr) return Pending{}; @@ -1457,15 +1608,21 @@ struct SeqState { ABSL_FALLTHROUGH_INTENDED; case State::kState4: { if (grpc_trace_promise_primitives.enabled()) { - gpr_log(GPR_DEBUG, "seq[%p]: begin poll step 5/7", this); + gpr_log(whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: begin poll step 5/7", this); } auto result = prior.prior.current_promise(); PromiseResult4* p = result.value_if_ready(); if (grpc_trace_promise_primitives.enabled()) { gpr_log( - GPR_DEBUG, "seq[%p]: poll step 5/7 gets %s", this, + whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: poll step 5/7 gets %s", this, p != nullptr - ? (PromiseResultTraits4::IsOk(*p) ? "ready" : "early-error") + ? (PromiseResultTraits4::IsOk(*p) + ? "ready" + : absl::StrCat("early-error:", + PromiseResultTraits4::ErrorString(*p)) + .c_str()) : "pending"); } if (p == nullptr) return Pending{}; @@ -1483,15 +1640,21 @@ struct SeqState { ABSL_FALLTHROUGH_INTENDED; case State::kState5: { if (grpc_trace_promise_primitives.enabled()) { - gpr_log(GPR_DEBUG, "seq[%p]: begin poll step 6/7", this); + gpr_log(whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: begin poll step 6/7", this); } auto result = prior.current_promise(); PromiseResult5* p = result.value_if_ready(); if (grpc_trace_promise_primitives.enabled()) { gpr_log( - GPR_DEBUG, "seq[%p]: poll step 6/7 gets %s", this, + whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: poll step 6/7 gets %s", this, p != nullptr - ? (PromiseResultTraits5::IsOk(*p) ? "ready" : "early-error") + ? (PromiseResultTraits5::IsOk(*p) + ? "ready" + : absl::StrCat("early-error:", + PromiseResultTraits5::ErrorString(*p)) + .c_str()) : "pending"); } if (p == nullptr) return Pending{}; @@ -1510,11 +1673,13 @@ struct SeqState { default: case State::kState6: { if (grpc_trace_promise_primitives.enabled()) { - gpr_log(GPR_DEBUG, "seq[%p]: begin poll step 7/7", this); + gpr_log(whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: begin poll step 7/7", this); } auto result = current_promise(); if (grpc_trace_promise_primitives.enabled()) { - gpr_log(GPR_DEBUG, "seq[%p]: poll step 7/7 gets %s", this, + gpr_log(whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: poll step 7/7 gets %s", this, result.ready() ? "ready" : "pending"); } auto* p = result.value_if_ready(); @@ -1629,9 +1794,11 @@ struct SeqState { kState7 }; GPR_NO_UNIQUE_ADDRESS State state = State::kState0; + GPR_NO_UNIQUE_ADDRESS DebugLocation whence; - SeqState(P&& p, F0&& f0, F1&& f1, F2&& f2, F3&& f3, F4&& f4, F5&& f5, - F6&& f6) noexcept { + SeqState(P&& p, F0&& f0, F1&& f1, F2&& f2, F3&& f3, F4&& f4, F5&& f5, F6&& f6, + DebugLocation whence) noexcept + : whence(whence) { Construct(&prior.prior.prior.prior.prior.prior.prior.current_promise, std::forward

(p)); Construct(&prior.prior.prior.prior.prior.prior.prior.next_factory, @@ -1687,7 +1854,8 @@ struct SeqState { tail6: Destruct(&prior.next_factory); } - SeqState(const SeqState& other) noexcept : state(other.state) { + SeqState(const SeqState& other) noexcept + : state(other.state), whence(other.whence) { GPR_ASSERT(state == State::kState0); Construct(&prior.current_promise, other.prior.current_promise); Construct(&prior.prior.prior.prior.prior.prior.prior.next_factory, @@ -1704,7 +1872,8 @@ struct SeqState { Construct(&prior.next_factory, other.prior.next_factory); } SeqState& operator=(const SeqState& other) = delete; - SeqState(SeqState&& other) noexcept : state(other.state) { + SeqState(SeqState&& other) noexcept + : state(other.state), whence(other.whence) { switch (state) { case State::kState0: Construct(&prior.prior.prior.prior.prior.prior.prior.current_promise, @@ -1771,16 +1940,22 @@ struct SeqState { switch (state) { case State::kState0: { if (grpc_trace_promise_primitives.enabled()) { - gpr_log(GPR_DEBUG, "seq[%p]: begin poll step 1/8", this); + gpr_log(whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: begin poll step 1/8", this); } auto result = prior.prior.prior.prior.prior.prior.prior.current_promise(); PromiseResult0* p = result.value_if_ready(); if (grpc_trace_promise_primitives.enabled()) { gpr_log( - GPR_DEBUG, "seq[%p]: poll step 1/8 gets %s", this, + whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: poll step 1/8 gets %s", this, p != nullptr - ? (PromiseResultTraits0::IsOk(*p) ? "ready" : "early-error") + ? (PromiseResultTraits0::IsOk(*p) + ? "ready" + : absl::StrCat("early-error:", + PromiseResultTraits0::ErrorString(*p)) + .c_str()) : "pending"); } if (p == nullptr) return Pending{}; @@ -1800,15 +1975,21 @@ struct SeqState { ABSL_FALLTHROUGH_INTENDED; case State::kState1: { if (grpc_trace_promise_primitives.enabled()) { - gpr_log(GPR_DEBUG, "seq[%p]: begin poll step 2/8", this); + gpr_log(whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: begin poll step 2/8", this); } auto result = prior.prior.prior.prior.prior.prior.current_promise(); PromiseResult1* p = result.value_if_ready(); if (grpc_trace_promise_primitives.enabled()) { gpr_log( - GPR_DEBUG, "seq[%p]: poll step 2/8 gets %s", this, + whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: poll step 2/8 gets %s", this, p != nullptr - ? (PromiseResultTraits1::IsOk(*p) ? "ready" : "early-error") + ? (PromiseResultTraits1::IsOk(*p) + ? "ready" + : absl::StrCat("early-error:", + PromiseResultTraits1::ErrorString(*p)) + .c_str()) : "pending"); } if (p == nullptr) return Pending{}; @@ -1827,15 +2008,21 @@ struct SeqState { ABSL_FALLTHROUGH_INTENDED; case State::kState2: { if (grpc_trace_promise_primitives.enabled()) { - gpr_log(GPR_DEBUG, "seq[%p]: begin poll step 3/8", this); + gpr_log(whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: begin poll step 3/8", this); } auto result = prior.prior.prior.prior.prior.current_promise(); PromiseResult2* p = result.value_if_ready(); if (grpc_trace_promise_primitives.enabled()) { gpr_log( - GPR_DEBUG, "seq[%p]: poll step 3/8 gets %s", this, + whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: poll step 3/8 gets %s", this, p != nullptr - ? (PromiseResultTraits2::IsOk(*p) ? "ready" : "early-error") + ? (PromiseResultTraits2::IsOk(*p) + ? "ready" + : absl::StrCat("early-error:", + PromiseResultTraits2::ErrorString(*p)) + .c_str()) : "pending"); } if (p == nullptr) return Pending{}; @@ -1854,15 +2041,21 @@ struct SeqState { ABSL_FALLTHROUGH_INTENDED; case State::kState3: { if (grpc_trace_promise_primitives.enabled()) { - gpr_log(GPR_DEBUG, "seq[%p]: begin poll step 4/8", this); + gpr_log(whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: begin poll step 4/8", this); } auto result = prior.prior.prior.prior.current_promise(); PromiseResult3* p = result.value_if_ready(); if (grpc_trace_promise_primitives.enabled()) { gpr_log( - GPR_DEBUG, "seq[%p]: poll step 4/8 gets %s", this, + whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: poll step 4/8 gets %s", this, p != nullptr - ? (PromiseResultTraits3::IsOk(*p) ? "ready" : "early-error") + ? (PromiseResultTraits3::IsOk(*p) + ? "ready" + : absl::StrCat("early-error:", + PromiseResultTraits3::ErrorString(*p)) + .c_str()) : "pending"); } if (p == nullptr) return Pending{}; @@ -1880,15 +2073,21 @@ struct SeqState { ABSL_FALLTHROUGH_INTENDED; case State::kState4: { if (grpc_trace_promise_primitives.enabled()) { - gpr_log(GPR_DEBUG, "seq[%p]: begin poll step 5/8", this); + gpr_log(whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: begin poll step 5/8", this); } auto result = prior.prior.prior.current_promise(); PromiseResult4* p = result.value_if_ready(); if (grpc_trace_promise_primitives.enabled()) { gpr_log( - GPR_DEBUG, "seq[%p]: poll step 5/8 gets %s", this, + whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: poll step 5/8 gets %s", this, p != nullptr - ? (PromiseResultTraits4::IsOk(*p) ? "ready" : "early-error") + ? (PromiseResultTraits4::IsOk(*p) + ? "ready" + : absl::StrCat("early-error:", + PromiseResultTraits4::ErrorString(*p)) + .c_str()) : "pending"); } if (p == nullptr) return Pending{}; @@ -1906,15 +2105,21 @@ struct SeqState { ABSL_FALLTHROUGH_INTENDED; case State::kState5: { if (grpc_trace_promise_primitives.enabled()) { - gpr_log(GPR_DEBUG, "seq[%p]: begin poll step 6/8", this); + gpr_log(whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: begin poll step 6/8", this); } auto result = prior.prior.current_promise(); PromiseResult5* p = result.value_if_ready(); if (grpc_trace_promise_primitives.enabled()) { gpr_log( - GPR_DEBUG, "seq[%p]: poll step 6/8 gets %s", this, + whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: poll step 6/8 gets %s", this, p != nullptr - ? (PromiseResultTraits5::IsOk(*p) ? "ready" : "early-error") + ? (PromiseResultTraits5::IsOk(*p) + ? "ready" + : absl::StrCat("early-error:", + PromiseResultTraits5::ErrorString(*p)) + .c_str()) : "pending"); } if (p == nullptr) return Pending{}; @@ -1932,15 +2137,21 @@ struct SeqState { ABSL_FALLTHROUGH_INTENDED; case State::kState6: { if (grpc_trace_promise_primitives.enabled()) { - gpr_log(GPR_DEBUG, "seq[%p]: begin poll step 7/8", this); + gpr_log(whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: begin poll step 7/8", this); } auto result = prior.current_promise(); PromiseResult6* p = result.value_if_ready(); if (grpc_trace_promise_primitives.enabled()) { gpr_log( - GPR_DEBUG, "seq[%p]: poll step 7/8 gets %s", this, + whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: poll step 7/8 gets %s", this, p != nullptr - ? (PromiseResultTraits6::IsOk(*p) ? "ready" : "early-error") + ? (PromiseResultTraits6::IsOk(*p) + ? "ready" + : absl::StrCat("early-error:", + PromiseResultTraits6::ErrorString(*p)) + .c_str()) : "pending"); } if (p == nullptr) return Pending{}; @@ -1959,11 +2170,13 @@ struct SeqState { default: case State::kState7: { if (grpc_trace_promise_primitives.enabled()) { - gpr_log(GPR_DEBUG, "seq[%p]: begin poll step 8/8", this); + gpr_log(whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: begin poll step 8/8", this); } auto result = current_promise(); if (grpc_trace_promise_primitives.enabled()) { - gpr_log(GPR_DEBUG, "seq[%p]: poll step 8/8 gets %s", this, + gpr_log(whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: poll step 8/8 gets %s", this, result.ready() ? "ready" : "pending"); } auto* p = result.value_if_ready(); @@ -2091,9 +2304,11 @@ struct SeqState { kState8 }; GPR_NO_UNIQUE_ADDRESS State state = State::kState0; + GPR_NO_UNIQUE_ADDRESS DebugLocation whence; SeqState(P&& p, F0&& f0, F1&& f1, F2&& f2, F3&& f3, F4&& f4, F5&& f5, F6&& f6, - F7&& f7) noexcept { + F7&& f7, DebugLocation whence) noexcept + : whence(whence) { Construct(&prior.prior.prior.prior.prior.prior.prior.prior.current_promise, std::forward

(p)); Construct(&prior.prior.prior.prior.prior.prior.prior.prior.next_factory, @@ -2157,7 +2372,8 @@ struct SeqState { tail7: Destruct(&prior.next_factory); } - SeqState(const SeqState& other) noexcept : state(other.state) { + SeqState(const SeqState& other) noexcept + : state(other.state), whence(other.whence) { GPR_ASSERT(state == State::kState0); Construct(&prior.current_promise, other.prior.current_promise); Construct( @@ -2177,7 +2393,8 @@ struct SeqState { Construct(&prior.next_factory, other.prior.next_factory); } SeqState& operator=(const SeqState& other) = delete; - SeqState(SeqState&& other) noexcept : state(other.state) { + SeqState(SeqState&& other) noexcept + : state(other.state), whence(other.whence) { switch (state) { case State::kState0: Construct( @@ -2254,16 +2471,22 @@ struct SeqState { switch (state) { case State::kState0: { if (grpc_trace_promise_primitives.enabled()) { - gpr_log(GPR_DEBUG, "seq[%p]: begin poll step 1/9", this); + gpr_log(whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: begin poll step 1/9", this); } auto result = prior.prior.prior.prior.prior.prior.prior.prior.current_promise(); PromiseResult0* p = result.value_if_ready(); if (grpc_trace_promise_primitives.enabled()) { gpr_log( - GPR_DEBUG, "seq[%p]: poll step 1/9 gets %s", this, + whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: poll step 1/9 gets %s", this, p != nullptr - ? (PromiseResultTraits0::IsOk(*p) ? "ready" : "early-error") + ? (PromiseResultTraits0::IsOk(*p) + ? "ready" + : absl::StrCat("early-error:", + PromiseResultTraits0::ErrorString(*p)) + .c_str()) : "pending"); } if (p == nullptr) return Pending{}; @@ -2284,16 +2507,22 @@ struct SeqState { ABSL_FALLTHROUGH_INTENDED; case State::kState1: { if (grpc_trace_promise_primitives.enabled()) { - gpr_log(GPR_DEBUG, "seq[%p]: begin poll step 2/9", this); + gpr_log(whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: begin poll step 2/9", this); } auto result = prior.prior.prior.prior.prior.prior.prior.current_promise(); PromiseResult1* p = result.value_if_ready(); if (grpc_trace_promise_primitives.enabled()) { gpr_log( - GPR_DEBUG, "seq[%p]: poll step 2/9 gets %s", this, + whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: poll step 2/9 gets %s", this, p != nullptr - ? (PromiseResultTraits1::IsOk(*p) ? "ready" : "early-error") + ? (PromiseResultTraits1::IsOk(*p) + ? "ready" + : absl::StrCat("early-error:", + PromiseResultTraits1::ErrorString(*p)) + .c_str()) : "pending"); } if (p == nullptr) return Pending{}; @@ -2313,15 +2542,21 @@ struct SeqState { ABSL_FALLTHROUGH_INTENDED; case State::kState2: { if (grpc_trace_promise_primitives.enabled()) { - gpr_log(GPR_DEBUG, "seq[%p]: begin poll step 3/9", this); + gpr_log(whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: begin poll step 3/9", this); } auto result = prior.prior.prior.prior.prior.prior.current_promise(); PromiseResult2* p = result.value_if_ready(); if (grpc_trace_promise_primitives.enabled()) { gpr_log( - GPR_DEBUG, "seq[%p]: poll step 3/9 gets %s", this, + whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: poll step 3/9 gets %s", this, p != nullptr - ? (PromiseResultTraits2::IsOk(*p) ? "ready" : "early-error") + ? (PromiseResultTraits2::IsOk(*p) + ? "ready" + : absl::StrCat("early-error:", + PromiseResultTraits2::ErrorString(*p)) + .c_str()) : "pending"); } if (p == nullptr) return Pending{}; @@ -2340,15 +2575,21 @@ struct SeqState { ABSL_FALLTHROUGH_INTENDED; case State::kState3: { if (grpc_trace_promise_primitives.enabled()) { - gpr_log(GPR_DEBUG, "seq[%p]: begin poll step 4/9", this); + gpr_log(whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: begin poll step 4/9", this); } auto result = prior.prior.prior.prior.prior.current_promise(); PromiseResult3* p = result.value_if_ready(); if (grpc_trace_promise_primitives.enabled()) { gpr_log( - GPR_DEBUG, "seq[%p]: poll step 4/9 gets %s", this, + whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: poll step 4/9 gets %s", this, p != nullptr - ? (PromiseResultTraits3::IsOk(*p) ? "ready" : "early-error") + ? (PromiseResultTraits3::IsOk(*p) + ? "ready" + : absl::StrCat("early-error:", + PromiseResultTraits3::ErrorString(*p)) + .c_str()) : "pending"); } if (p == nullptr) return Pending{}; @@ -2367,15 +2608,21 @@ struct SeqState { ABSL_FALLTHROUGH_INTENDED; case State::kState4: { if (grpc_trace_promise_primitives.enabled()) { - gpr_log(GPR_DEBUG, "seq[%p]: begin poll step 5/9", this); + gpr_log(whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: begin poll step 5/9", this); } auto result = prior.prior.prior.prior.current_promise(); PromiseResult4* p = result.value_if_ready(); if (grpc_trace_promise_primitives.enabled()) { gpr_log( - GPR_DEBUG, "seq[%p]: poll step 5/9 gets %s", this, + whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: poll step 5/9 gets %s", this, p != nullptr - ? (PromiseResultTraits4::IsOk(*p) ? "ready" : "early-error") + ? (PromiseResultTraits4::IsOk(*p) + ? "ready" + : absl::StrCat("early-error:", + PromiseResultTraits4::ErrorString(*p)) + .c_str()) : "pending"); } if (p == nullptr) return Pending{}; @@ -2393,15 +2640,21 @@ struct SeqState { ABSL_FALLTHROUGH_INTENDED; case State::kState5: { if (grpc_trace_promise_primitives.enabled()) { - gpr_log(GPR_DEBUG, "seq[%p]: begin poll step 6/9", this); + gpr_log(whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: begin poll step 6/9", this); } auto result = prior.prior.prior.current_promise(); PromiseResult5* p = result.value_if_ready(); if (grpc_trace_promise_primitives.enabled()) { gpr_log( - GPR_DEBUG, "seq[%p]: poll step 6/9 gets %s", this, + whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: poll step 6/9 gets %s", this, p != nullptr - ? (PromiseResultTraits5::IsOk(*p) ? "ready" : "early-error") + ? (PromiseResultTraits5::IsOk(*p) + ? "ready" + : absl::StrCat("early-error:", + PromiseResultTraits5::ErrorString(*p)) + .c_str()) : "pending"); } if (p == nullptr) return Pending{}; @@ -2419,15 +2672,21 @@ struct SeqState { ABSL_FALLTHROUGH_INTENDED; case State::kState6: { if (grpc_trace_promise_primitives.enabled()) { - gpr_log(GPR_DEBUG, "seq[%p]: begin poll step 7/9", this); + gpr_log(whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: begin poll step 7/9", this); } auto result = prior.prior.current_promise(); PromiseResult6* p = result.value_if_ready(); if (grpc_trace_promise_primitives.enabled()) { gpr_log( - GPR_DEBUG, "seq[%p]: poll step 7/9 gets %s", this, + whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: poll step 7/9 gets %s", this, p != nullptr - ? (PromiseResultTraits6::IsOk(*p) ? "ready" : "early-error") + ? (PromiseResultTraits6::IsOk(*p) + ? "ready" + : absl::StrCat("early-error:", + PromiseResultTraits6::ErrorString(*p)) + .c_str()) : "pending"); } if (p == nullptr) return Pending{}; @@ -2445,15 +2704,21 @@ struct SeqState { ABSL_FALLTHROUGH_INTENDED; case State::kState7: { if (grpc_trace_promise_primitives.enabled()) { - gpr_log(GPR_DEBUG, "seq[%p]: begin poll step 8/9", this); + gpr_log(whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: begin poll step 8/9", this); } auto result = prior.current_promise(); PromiseResult7* p = result.value_if_ready(); if (grpc_trace_promise_primitives.enabled()) { gpr_log( - GPR_DEBUG, "seq[%p]: poll step 8/9 gets %s", this, + whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: poll step 8/9 gets %s", this, p != nullptr - ? (PromiseResultTraits7::IsOk(*p) ? "ready" : "early-error") + ? (PromiseResultTraits7::IsOk(*p) + ? "ready" + : absl::StrCat("early-error:", + PromiseResultTraits7::ErrorString(*p)) + .c_str()) : "pending"); } if (p == nullptr) return Pending{}; @@ -2472,11 +2737,13 @@ struct SeqState { default: case State::kState8: { if (grpc_trace_promise_primitives.enabled()) { - gpr_log(GPR_DEBUG, "seq[%p]: begin poll step 9/9", this); + gpr_log(whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: begin poll step 9/9", this); } auto result = current_promise(); if (grpc_trace_promise_primitives.enabled()) { - gpr_log(GPR_DEBUG, "seq[%p]: poll step 9/9 gets %s", this, + gpr_log(whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, + "seq[%p]: poll step 9/9 gets %s", this, result.ready() ? "ready" : "pending"); } auto* p = result.value_if_ready(); diff --git a/src/core/lib/promise/seq.h b/src/core/lib/promise/seq.h index 1ed533299d6..0724a820575 100644 --- a/src/core/lib/promise/seq.h +++ b/src/core/lib/promise/seq.h @@ -21,6 +21,7 @@ #include +#include "src/core/lib/gprpp/debug_location.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/seq_state.h" @@ -39,6 +40,7 @@ struct SeqTraits { return next->Make(std::forward(value)); } static bool IsOk(const T&) { return true; } + static const char* ErrorString(const T&) { abort(); } template static R ReturnValue(T&&) { abort(); @@ -57,8 +59,9 @@ struct SeqTraits { template class Seq { public: - explicit Seq(P&& promise, Fs&&... factories) - : state_(std::forward

(promise), std::forward(factories)...) {} + explicit Seq(P&& promise, Fs&&... factories, DebugLocation whence) + : state_(std::forward

(promise), std::forward(factories)..., + whence) {} auto operator()() { return state_.PollOnce(); } @@ -94,16 +97,68 @@ struct SeqIterResultTraits { // Pass its result to the third, and run the returned promise. // etc // Return the final value. -template -promise_detail::Seq Seq(Functors... functors) { - return promise_detail::Seq(std::move(functors)...); -} - template F Seq(F functor) { return functor; } +template +promise_detail::Seq Seq(F0 f0, F1 f1, DebugLocation whence = {}) { + return promise_detail::Seq(std::move(f0), std::move(f1), whence); +} + +template +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 +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 +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 +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 +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 +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); +} + // Execute a sequence of operations of unknown length. // Asynchronously: // for (element in (begin, end)) { diff --git a/src/core/lib/promise/try_seq.h b/src/core/lib/promise/try_seq.h index 266a09839a7..8ef145d1814 100644 --- a/src/core/lib/promise/try_seq.h +++ b/src/core/lib/promise/try_seq.h @@ -45,6 +45,7 @@ struct TrySeqTraitsWithSfinae { return next->Make(std::forward(value)); } static bool IsOk(const T&) { return true; } + static const char* ErrorString(const T&) { abort(); } template static R ReturnValue(T&&) { abort(); @@ -69,6 +70,9 @@ struct TrySeqTraitsWithSfinae> { return next->Make(std::move(*status)); } static bool IsOk(const absl::StatusOr& status) { return status.ok(); } + static std::string ErrorString(const absl::StatusOr& status) { + return status.status().ToString(); + } template static R ReturnValue(absl::StatusOr&& status) { return StatusCast(status.status()); @@ -110,6 +114,9 @@ struct TrySeqTraitsWithSfinae< return next->Make(); } static bool IsOk(const T& status) { return IsStatusOk(status); } + static std::string ErrorString(const T& status) { + return IsStatusOk(status) ? "OK" : "FAILED"; + } template static R ReturnValue(T&& status) { return StatusCast(std::move(status)); @@ -133,6 +140,9 @@ struct TrySeqTraitsWithSfinae< return next->Make(TakeValue(std::forward(status))); } static bool IsOk(const T& status) { return IsStatusOk(status); } + static std::string ErrorString(const T& status) { + return IsStatusOk(status) ? "OK" : "FAILED"; + } template static R ReturnValue(T&& status) { GPR_DEBUG_ASSERT(!IsStatusOk(status)); @@ -153,6 +163,9 @@ struct TrySeqTraitsWithSfinae { return next->Make(); } static bool IsOk(const absl::Status& status) { return status.ok(); } + static std::string ErrorString(const absl::Status& status) { + return status.ToString(); + } template static R ReturnValue(absl::Status&& status) { return StatusCast(std::move(status)); @@ -171,8 +184,9 @@ using TrySeqTraits = TrySeqTraitsWithSfinae; template class TrySeq { public: - explicit TrySeq(P&& promise, Fs&&... factories) - : state_(std::forward

(promise), std::forward(factories)...) {} + explicit TrySeq(P&& promise, Fs&&... factories, DebugLocation whence) + : state_(std::forward

(promise), std::forward(factories)..., + whence) {} auto operator()() { return state_.PollOnce(); } @@ -214,9 +228,66 @@ struct TrySeqIterResultTraits { // 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 -promise_detail::TrySeq TrySeq(Functors... functors) { - return promise_detail::TrySeq(std::move(functors)...); +template +F TrySeq(F functor) { + return functor; +} + +template +promise_detail::TrySeq TrySeq(F0 f0, F1 f1, DebugLocation whence = {}) { + return promise_detail::TrySeq(std::move(f0), std::move(f1), whence); +} + +template +promise_detail::TrySeq TrySeq(F0 f0, F1 f1, F2 f2, + DebugLocation whence = {}) { + return promise_detail::TrySeq(std::move(f0), std::move(f1), + std::move(f2), whence); +} + +template +promise_detail::TrySeq TrySeq(F0 f0, F1 f1, F2 f2, F3 f3, + DebugLocation whence = {}) { + return promise_detail::TrySeq( + std::move(f0), std::move(f1), std::move(f2), std::move(f3), whence); +} + +template +promise_detail::TrySeq TrySeq(F0 f0, F1 f1, F2 f2, F3 f3, + F4 f4, + DebugLocation whence = {}) { + return promise_detail::TrySeq( + std::move(f0), std::move(f1), std::move(f2), std::move(f3), std::move(f4), + whence); +} + +template +promise_detail::TrySeq TrySeq( + F0 f0, F1 f1, F2 f2, F3 f3, F4 f4, F5 f5, DebugLocation whence = {}) { + return promise_detail::TrySeq( + std::move(f0), std::move(f1), std::move(f2), std::move(f3), std::move(f4), + std::move(f5), whence); +} + +template +promise_detail::TrySeq TrySeq( + F0 f0, F1 f1, F2 f2, F3 f3, F4 f4, F5 f5, F6 f6, + DebugLocation whence = {}) { + return promise_detail::TrySeq( + std::move(f0), std::move(f1), std::move(f2), std::move(f3), std::move(f4), + std::move(f5), std::move(f6), whence); +} + +template +promise_detail::TrySeq TrySeq( + F0 f0, F1 f1, F2 f2, F3 f3, F4 f4, F5 f5, F6 f6, F7 f7, + DebugLocation whence = {}) { + return promise_detail::TrySeq( + 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); } // Try a sequence of operations of unknown length. diff --git a/tools/codegen/core/gen_seq.py b/tools/codegen/core/gen_seq.py index cfe0f045906..fe3f949e7fd 100755 --- a/tools/codegen/core/gen_seq.py +++ b/tools/codegen/core/gen_seq.py @@ -83,8 +83,11 @@ union { % endif enum class State : uint8_t { ${",".join(f"kState{i}" for i in range(0,n))} }; GPR_NO_UNIQUE_ADDRESS State state = State::kState0; + GPR_NO_UNIQUE_ADDRESS DebugLocation whence; - SeqState(P&& p, ${",".join(f"F{i}&& f{i}" for i in range(0,n-1))}) noexcept { + SeqState(P&& p, + ${",".join(f"F{i}&& f{i}" for i in range(0,n-1))}, + DebugLocation whence) noexcept: whence(whence) { Construct(&${"prior."*(n-1)}current_promise, std::forward

(p)); % for i in range(0,n-1): Construct(&${"prior."*(n-1-i)}next_factory, std::forward(f${i})); @@ -106,7 +109,7 @@ tail${i}: Destruct(&${"prior."*(n-1-i)}next_factory); % endfor } - SeqState(const SeqState& other) noexcept : state(other.state) { + SeqState(const SeqState& other) noexcept : state(other.state), whence(other.whence) { GPR_ASSERT(state == State::kState0); Construct(&${"prior."*(n-1-i)}current_promise, other.${"prior."*(n-1-i)}current_promise); @@ -116,7 +119,7 @@ tail${i}: % endfor } SeqState& operator=(const SeqState& other) = delete; - SeqState(SeqState&& other) noexcept : state(other.state) { + SeqState(SeqState&& other) noexcept : state(other.state), whence(other.whence) { switch (state) { % for i in range(0,n-1): case State::kState${i}: @@ -140,13 +143,17 @@ tail${i}: % for i in range(0,n-1): case State::kState${i}: { if (grpc_trace_promise_primitives.enabled()) { - gpr_log(GPR_DEBUG, "seq[%p]: begin poll step ${i+1}/${n}", this); + gpr_log(whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, "seq[%p]: begin poll step ${i+1}/${n}", this); } auto result = ${"prior."*(n-1-i)}current_promise(); PromiseResult${i}* p = result.value_if_ready(); if (grpc_trace_promise_primitives.enabled()) { - gpr_log(GPR_DEBUG, "seq[%p]: poll step ${i+1}/${n} gets %s", this, - p != nullptr? (PromiseResultTraits${i}::IsOk(*p)? "ready" : "early-error") : "pending"); + gpr_log(whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, "seq[%p]: poll step ${i+1}/${n} gets %s", this, + p != nullptr + ? (PromiseResultTraits${i}::IsOk(*p) + ? "ready" + : absl::StrCat("early-error:", PromiseResultTraits${i}::ErrorString(*p)).c_str()) + : "pending"); } if (p == nullptr) return Pending{}; if (!PromiseResultTraits${i}::IsOk(*p)) { @@ -163,11 +170,11 @@ tail${i}: default: case State::kState${n-1}: { if (grpc_trace_promise_primitives.enabled()) { - gpr_log(GPR_DEBUG, "seq[%p]: begin poll step ${n}/${n}", this); + gpr_log(whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, "seq[%p]: begin poll step ${n}/${n}", this); } auto result = current_promise(); if (grpc_trace_promise_primitives.enabled()) { - gpr_log(GPR_DEBUG, "seq[%p]: poll step ${n}/${n} gets %s", this, result.ready()? "ready" : "pending"); + gpr_log(whence.file(), whence.line(), GPR_LOG_SEVERITY_DEBUG, "seq[%p]: poll step ${n}/${n} gets %s", this, result.ready()? "ready" : "pending"); } auto* p = result.value_if_ready(); if (p == nullptr) return Pending{}; @@ -191,10 +198,12 @@ front_matter = """ #include #include "absl/base/attributes.h" +#include "absl/strings/str_cat.h" #include #include "src/core/lib/gprpp/construct_destruct.h" +#include "src/core/lib/gprpp/debug_location.h" #include "src/core/lib/promise/detail/promise_factory.h" #include "src/core/lib/promise/detail/promise_like.h" #include "src/core/lib/promise/poll.h"