-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
* Call finalization for promises * comment * split out and test * dont use promise_detail:: directly * fix * Automated change: Fix sanity tests * fix Co-authored-by: ctiller <ctiller@users.noreply.github.com>
- Loading branch information
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
// 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_CHANNEL_CALL_FINALIZATION_H | ||
#define GRPC_CORE_LIB_CHANNEL_CALL_FINALIZATION_H | ||
|
||
#include <grpc/support/port_platform.h> | ||
|
||
#include "src/core/lib/channel/channel_stack.h" | ||
#include "src/core/lib/promise/context.h" | ||
#include "src/core/lib/resource_quota/arena.h" | ||
|
||
namespace grpc_core { | ||
|
||
// Call finalization context. | ||
// Sometimes a filter needs to perform some operation after the last byte of | ||
// data is flushed to the wire. This context is used to perform that | ||
// finalization. | ||
// Filters can register a finalizer by calling Add(). | ||
// The finalizer will be called before the call is destroyed but after | ||
// the top level promise is completed. | ||
class CallFinalization { | ||
public: | ||
// Add a step to the finalization context. | ||
// Takes a callable with a signature compatible with: | ||
// (const grpc_call_final_info&) -> void. | ||
// Finalizers are run in the reverse order they are added. | ||
template <typename F> | ||
void Add(F&& t) { | ||
first_ = | ||
GetContext<Arena>()->New<FuncFinalizer<F>>(std::forward<F>(t), first_); | ||
} | ||
|
||
void Run(const grpc_call_final_info* final_info) { | ||
if (Finalizer* f = absl::exchange(first_, nullptr)) f->Run(final_info); | ||
} | ||
|
||
private: | ||
// Base class for finalizer implementations. | ||
class Finalizer { | ||
public: | ||
// Run the finalizer and call the destructor of this Finalizer. | ||
virtual void Run(const grpc_call_final_info* final_info) = 0; | ||
|
||
protected: | ||
~Finalizer() {} | ||
}; | ||
// Specialization for callable objects. | ||
template <typename F> | ||
class FuncFinalizer final : public Finalizer { | ||
public: | ||
FuncFinalizer(F&& f, Finalizer* next) | ||
: next_(next), f_(std::forward<F>(f)) {} | ||
|
||
void Run(const grpc_call_final_info* final_info) override { | ||
f_(final_info); | ||
Finalizer* next = next_; | ||
this->~FuncFinalizer(); | ||
if (next != nullptr) next->Run(final_info); | ||
} | ||
|
||
private: | ||
Finalizer* next_; | ||
F f_; | ||
}; | ||
// The first finalizer in the chain. | ||
Finalizer* first_ = nullptr; | ||
}; | ||
|
||
template <> | ||
struct ContextType<CallFinalization> {}; | ||
|
||
} // namespace grpc_core | ||
|
||
#endif // GRPC_CORE_LIB_CHANNEL_CALL_FINALIZATION_H |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
// Copyright 2021 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/channel/call_finalization.h" | ||
|
||
#include <gtest/gtest.h> | ||
|
||
#include "src/core/lib/resource_quota/resource_quota.h" | ||
#include "test/core/promise/test_context.h" | ||
|
||
namespace grpc_core { | ||
|
||
static auto* g_memory_allocator = new MemoryAllocator( | ||
ResourceQuota::Default()->memory_quota()->CreateMemoryAllocator("test")); | ||
|
||
TEST(CallFinalizationTest, Works) { | ||
auto arena = MakeScopedArena(1024, g_memory_allocator); | ||
std::string evidence; | ||
TestContext<Arena> context(arena.get()); | ||
CallFinalization finalization; | ||
auto p = std::make_shared<int>(42); | ||
finalization.Add([&evidence, p](const grpc_call_final_info* final_info) { | ||
evidence += absl::StrCat("FIRST", final_info->error_string, *p, "\n"); | ||
}); | ||
finalization.Add([&evidence, p](const grpc_call_final_info* final_info) { | ||
evidence += absl::StrCat("SECOND", final_info->error_string, *p, "\n"); | ||
}); | ||
grpc_call_final_info final_info{}; | ||
final_info.error_string = "123"; | ||
finalization.Run(&final_info); | ||
EXPECT_EQ(evidence, "SECOND12342\nFIRST12342\n"); | ||
} | ||
|
||
} // namespace grpc_core | ||
|
||
int main(int argc, char** argv) { | ||
::testing::InitGoogleTest(&argc, argv); | ||
return RUN_ALL_TESTS(); | ||
} |