1 // Copyright 2022 gRPC authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #ifndef GRPC_SRC_CORE_LIB_PROMISE_CANCEL_CALLBACK_H 16 #define GRPC_SRC_CORE_LIB_PROMISE_CANCEL_CALLBACK_H 17 18 #include <grpc/support/port_platform.h> 19 20 #include "src/core/lib/promise/detail/promise_like.h" 21 22 namespace grpc_core { 23 24 namespace cancel_callback_detail { 25 26 template <typename Fn> 27 class Handler { 28 public: Handler(Fn fn)29 explicit Handler(Fn fn) : fn_(std::move(fn)) {} 30 Handler(const Handler&) = delete; 31 Handler& operator=(const Handler&) = delete; ~Handler()32 ~Handler() { 33 if (!done_) { 34 fn_(); 35 } 36 } Handler(Handler && other)37 Handler(Handler&& other) noexcept 38 : fn_(std::move(other.fn_)), done_(other.done_) { 39 other.done_ = true; 40 } 41 Handler& operator=(Handler&& other) noexcept { 42 fn_ = std::move(other.fn_); 43 done_ = other.done_; 44 other.done_ = true; 45 } 46 Done()47 void Done() { done_ = true; } 48 49 private: 50 Fn fn_; 51 bool done_ = false; 52 }; 53 54 } // namespace cancel_callback_detail 55 56 // Wrap main_fn so that it calls cancel_fn if the promise is destroyed prior to 57 // completion. 58 // Returns a promise with the same result type as main_fn. 59 template <typename MainFn, typename CancelFn> OnCancel(MainFn main_fn,CancelFn cancel_fn)60auto OnCancel(MainFn main_fn, CancelFn cancel_fn) { 61 return [on_cancel = 62 cancel_callback_detail::Handler<CancelFn>(std::move(cancel_fn)), 63 main_fn = promise_detail::PromiseLike<MainFn>( 64 std::move(main_fn))]() mutable { 65 auto r = main_fn(); 66 if (r.ready()) { 67 on_cancel.Done(); 68 } 69 return r; 70 }; 71 } 72 73 } // namespace grpc_core 74 75 #endif // GRPC_SRC_CORE_LIB_PROMISE_CANCEL_CALLBACK_H 76