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_CHANNEL_CALL_FINALIZATION_H 16 #define GRPC_SRC_CORE_LIB_CHANNEL_CALL_FINALIZATION_H 17 18 #include <grpc/support/port_platform.h> 19 20 #include <utility> 21 22 #include "src/core/lib/channel/channel_stack.h" 23 #include "src/core/lib/promise/context.h" 24 #include "src/core/lib/resource_quota/arena.h" 25 26 namespace grpc_core { 27 28 // Call finalization context. 29 // Sometimes a filter needs to perform some operation after the last byte of 30 // data is flushed to the wire. This context is used to perform that 31 // finalization. 32 // Filters can register a finalizer by calling Add(). 33 // The finalizer will be called before the call is destroyed but after 34 // the top level promise is completed. 35 class CallFinalization { 36 public: 37 // Add a step to the finalization context. 38 // Takes a callable with a signature compatible with: 39 // (const grpc_call_final_info*) -> void. 40 // Finalizers are run in the reverse order they are added. 41 template <typename F> Add(F && t)42 void Add(F&& t) { 43 first_ = 44 GetContext<Arena>()->New<FuncFinalizer<F>>(std::forward<F>(t), first_); 45 } 46 Run(const grpc_call_final_info * final_info)47 void Run(const grpc_call_final_info* final_info) { 48 if (Finalizer* f = std::exchange(first_, nullptr)) f->Run(final_info); 49 } 50 51 private: 52 // Base class for finalizer implementations. 53 class Finalizer { 54 public: 55 // Run the finalizer and call the destructor of this Finalizer. 56 virtual void Run(const grpc_call_final_info* final_info) = 0; 57 58 protected: ~Finalizer()59 ~Finalizer() {} 60 }; 61 // Specialization for callable objects. 62 template <typename F> 63 class FuncFinalizer final : public Finalizer { 64 public: FuncFinalizer(F && f,Finalizer * next)65 FuncFinalizer(F&& f, Finalizer* next) 66 : next_(next), f_(std::forward<F>(f)) {} 67 Run(const grpc_call_final_info * final_info)68 void Run(const grpc_call_final_info* final_info) override { 69 f_(final_info); 70 Finalizer* next = next_; 71 this->~FuncFinalizer(); 72 if (next != nullptr) next->Run(final_info); 73 } 74 75 private: 76 Finalizer* next_; 77 F f_; 78 }; 79 // The first finalizer in the chain. 80 Finalizer* first_ = nullptr; 81 }; 82 83 template <> 84 struct ContextType<CallFinalization> {}; 85 86 } // namespace grpc_core 87 88 #endif // GRPC_SRC_CORE_LIB_CHANNEL_CALL_FINALIZATION_H 89