Skip to content

Commit

Permalink
[promises] Add some cancellation niceties
Browse files Browse the repository at this point in the history
  • Loading branch information
ctiller committed Dec 1, 2023
1 parent 68332b0 commit a954afa
Showing 1 changed file with 42 additions and 0 deletions.
42 changes: 42 additions & 0 deletions src/core/lib/transport/transport.h
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,48 @@ class CallSpineInterface {
GRPC_MUST_USE_RESULT virtual absl::nullopt_t Cancel(
ServerMetadataHandle metadata) = 0;
virtual Party& party() = 0;

// Wrap a promise so that if it returns failure it automatically cancels
// the rest of the call.
// The resulting (returned) promise will resolve to Empty.
template <typename Promise>
auto CancelIfFails(Promise promise) {
GPR_DEBUG_ASSERT(Activity::current() == &party());
using P = promise_detail::PromiseLike<Promise>;
using ResultType = typename P::Result;
return Map(std::move(promise), [this](ResultType r) {
if (!IsStatusOk(r)) {
Cancel(StatusCast<ServerMetadataHandle>(std::move(r)));
}
return Empty{};
});
}

// Spawn a promise that returns Empty{} and save some boilerplate handling
// that detail.
template <typename PromiseFactory>
void SpawnInfallible(absl::string_view name, PromiseFactory promise_factory) {
party().Spawn(name, std::move(promise_factory), [](Empty) {});
}

// Spawn a promise that returns some status-like type; if the status
// represents failure automatically cancel the rest of the call.
template <typename PromiseFactory>
void SpawnGuarded(absl::string_view name, PromiseFactory promise_factory) {
using FactoryType =
promise_detail::OncePromiseFactory<void, PromiseFactory>;
using PromiseType = typename FactoryType::Promise;
using ResultType = typename PromiseType::Result;
static_assert(
std::is_same<bool,
decltype(IsStatusOk(std::declval<ResultType>()))>::value,
"SpawnGuarded promise must return a status-like object");
party().Spawn(name, std::move(promise_factory), [this](ResultType r) {
if (!IsStatusOk(r)) {
Cancel(StatusCast<ServerMetadataHandle>(std::move(r)));
}
});
}
};

class CallSpine final : public CallSpineInterface {
Expand Down

0 comments on commit a954afa

Please sign in to comment.