mirror of https://github.com/grpc/grpc.git
[promises] Cancellation callback (#31863)
* [promises] Cancellation callback * Automated change: Fix sanity tests * Automated change: Fix sanity tests Co-authored-by: ctiller <ctiller@users.noreply.github.com>pull/31866/head
parent
2f05aa8984
commit
91083659fa
7 changed files with 219 additions and 0 deletions
@ -0,0 +1,78 @@ |
||||
// Copyright 2022 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_CORE_LIB_PROMISE_CANCEL_CALLBACK_H |
||||
#define GRPC_CORE_LIB_PROMISE_CANCEL_CALLBACK_H |
||||
|
||||
#include <grpc/support/port_platform.h> |
||||
|
||||
#include <utility> |
||||
|
||||
#include "src/core/lib/promise/detail/promise_like.h" |
||||
#include "src/core/lib/promise/poll.h" |
||||
|
||||
namespace grpc_core { |
||||
|
||||
namespace cancel_callback_detail { |
||||
|
||||
template <typename Fn> |
||||
class Handler { |
||||
public: |
||||
explicit Handler(Fn fn) : fn_(std::move(fn)) {} |
||||
Handler(const Handler&) = delete; |
||||
Handler& operator=(const Handler&) = delete; |
||||
~Handler() { |
||||
if (!done_) { |
||||
fn_(); |
||||
} |
||||
} |
||||
Handler(Handler&& other) noexcept |
||||
: fn_(std::move(other.fn_)), done_(other.done_) { |
||||
other.done_ = true; |
||||
} |
||||
Handler& operator=(Handler&& other) noexcept { |
||||
fn_ = std::move(other.fn_); |
||||
done_ = other.done_; |
||||
other.done_ = true; |
||||
} |
||||
|
||||
void Done() { done_ = true; } |
||||
|
||||
private: |
||||
Fn fn_; |
||||
bool done_ = false; |
||||
}; |
||||
|
||||
} // namespace cancel_callback_detail
|
||||
|
||||
// Wrap main_fn so that it calls cancel_fn if the promise is destroyed prior to
|
||||
// completion.
|
||||
// Returns a promise with the same result type as main_fn.
|
||||
template <typename MainFn, typename CancelFn> |
||||
auto OnCancel(MainFn main_fn, CancelFn cancel_fn) { |
||||
return [on_cancel = |
||||
cancel_callback_detail::Handler<CancelFn>(std::move(cancel_fn)), |
||||
main_fn = promise_detail::PromiseLike<MainFn>( |
||||
std::move(main_fn))]() mutable { |
||||
auto r = main_fn(); |
||||
if (!absl::holds_alternative<Pending>(r)) { |
||||
on_cancel.Done(); |
||||
} |
||||
return r; |
||||
}; |
||||
} |
||||
|
||||
} // namespace grpc_core
|
||||
|
||||
#endif // GRPC_CORE_LIB_PROMISE_CANCEL_CALLBACK_H
|
@ -0,0 +1,41 @@ |
||||
// Copyright 2022 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.
|
||||
|
||||
#include "src/core/lib/promise/cancel_callback.h" |
||||
|
||||
#include "gtest/gtest.h" |
||||
|
||||
namespace grpc_core { |
||||
|
||||
TEST(CancelCallback, DoesntCallCancelIfCompleted) { |
||||
auto x = OnCancel([]() { return 42; }, |
||||
[]() { FAIL() << "Should never reach here"; }); |
||||
EXPECT_EQ(x(), Poll<int>(42)); |
||||
} |
||||
|
||||
TEST(CancelCallback, CallsCancelIfNotCompleted) { |
||||
bool called = false; |
||||
{ |
||||
auto x = OnCancel([]() { return 42; }, [&called]() { called = true; }); |
||||
EXPECT_EQ(called, false); |
||||
} |
||||
EXPECT_EQ(called, true); |
||||
} |
||||
|
||||
} // namespace grpc_core
|
||||
|
||||
int main(int argc, char** argv) { |
||||
::testing::InitGoogleTest(&argc, argv); |
||||
return RUN_ALL_TESTS(); |
||||
} |
Loading…
Reference in new issue