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 <utility> 21 22 #include "src/core/lib/promise/detail/promise_like.h" 23 24 namespace grpc_core { 25 26 namespace cancel_callback_detail { 27 28 template <typename Fn> 29 class Handler { 30 public: Handler(Fn fn)31 explicit Handler(Fn fn) : fn_(std::move(fn)) {} 32 Handler(const Handler&) = delete; 33 Handler& operator=(const Handler&) = delete; ~Handler()34 ~Handler() { 35 if (!done_) { 36 fn_(); 37 } 38 } Handler(Handler && other)39 Handler(Handler&& other) noexcept 40 : fn_(std::move(other.fn_)), done_(other.done_) { 41 other.done_ = true; 42 } 43 Handler& operator=(Handler&& other) noexcept { 44 fn_ = std::move(other.fn_); 45 done_ = other.done_; 46 other.done_ = true; 47 } 48 Done()49 void Done() { done_ = true; } 50 51 private: 52 Fn fn_; 53 bool done_ = false; 54 }; 55 56 } // namespace cancel_callback_detail 57 58 // Wrap main_fn so that it calls cancel_fn if the promise is destroyed prior to 59 // completion. 60 // Returns a promise with the same result type as main_fn. 61 template <typename MainFn, typename CancelFn> OnCancel(MainFn main_fn,CancelFn cancel_fn)62auto OnCancel(MainFn main_fn, CancelFn cancel_fn) { 63 return [on_cancel = 64 cancel_callback_detail::Handler<CancelFn>(std::move(cancel_fn)), 65 main_fn = promise_detail::PromiseLike<MainFn>( 66 std::move(main_fn))]() mutable { 67 auto r = main_fn(); 68 if (r.ready()) { 69 on_cancel.Done(); 70 } 71 return r; 72 }; 73 } 74 75 } // namespace grpc_core 76 77 #endif // GRPC_SRC_CORE_LIB_PROMISE_CANCEL_CALLBACK_H 78