Skip to content

Commit

Permalink
x
Browse files Browse the repository at this point in the history
  • Loading branch information
ctiller committed Jan 18, 2024
1 parent b85ebb9 commit 467e7d5
Show file tree
Hide file tree
Showing 3 changed files with 168 additions and 127 deletions.
17 changes: 15 additions & 2 deletions src/core/lib/transport/call_filters.cc
Original file line number Diff line number Diff line change
Expand Up @@ -171,21 +171,34 @@ CallFilters::CallFilters(RefCountedPtr<Stack> stack)
: stack_(std::move(stack)),
call_data_(gpr_malloc_aligned(stack_->data_.call_data_size,
stack_->data_.call_data_alignment)) {
for (const auto& constructor : stack_->data_.filter_constructor) {
constructor.call_init(Offset(call_data_, constructor.call_offset),
constructor.channel_data);
}
client_initial_metadata_state_.Start();
client_to_server_message_state_.Start();
server_initial_metadata_state_.Start();
server_to_client_message_state_.Start();
}

CallFilters::~CallFilters() {
if (call_data_ != nullptr) gpr_free_aligned(call_data_);
if (call_data_ != nullptr) {
for (const auto& destructor : stack_->data_.filter_destructor) {
destructor.call_destroy(Offset(call_data_, destructor.call_offset));
}
gpr_free_aligned(call_data_);
}
}

void CallFilters::SetStack(RefCountedPtr<Stack> stack) {
if (call_data_ != nullptr) gpr_free_aligned(call_data_);
GPR_ASSERT(call_data_ == nullptr);
stack_ = std::move(stack);
call_data_ = gpr_malloc_aligned(stack_->data_.call_data_size,
stack_->data_.call_data_alignment);
for (const auto& constructor : stack_->data_.filter_constructor) {
constructor.call_init(Offset(call_data_, constructor.call_offset),
constructor.channel_data);
}
client_initial_metadata_state_.Start();
client_to_server_message_state_.Start();
server_initial_metadata_state_.Start();
Expand Down
67 changes: 54 additions & 13 deletions src/core/lib/transport/call_filters.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

#include <cstdint>
#include <memory>
#include <type_traits>

#include "src/core/lib/gprpp/ref_counted.h"
#include "src/core/lib/gprpp/ref_counted_ptr.h"
Expand Down Expand Up @@ -109,17 +110,24 @@ struct NoInterceptor {};

namespace filters_detail {

// One call filter metadata
// Contains enough information to allocate and initialize/destruct the
// One call filter constructor
// Contains enough information to allocate and initialize the
// call data for one filter.
struct Filter {
struct FilterConstructor {
// Pointer to corresponding channel data for this filter
void* channel_data;
// Offset of the call data for this filter within the call data memory
// allocation
size_t call_offset;
// Initialize the call data for this filter
void (*call_init)(void* call_data, void* channel_data);
};

// One call filter destructor
struct FilterDestructor {
// Offset of the call data for this filter within the call data memory
// allocation
size_t call_offset;
// Destroy the call data for this filter
void (*call_destroy)(void* call_data);
};
Expand Down Expand Up @@ -568,7 +576,8 @@ struct StackData {
size_t call_data_size = 0;
// A complete list of filters for this call, so that we can construct the
// call data for each filter.
std::vector<Filter> filters;
std::vector<FilterConstructor> filter_constructor;
std::vector<FilterDestructor> filter_destructor;
// For each kind of operation, a layout of the operations for this call.
// (there's some duplicate data here, and that's ok: we want to avoid
// pointer chasing as much as possible when executing a call)
Expand All @@ -592,45 +601,77 @@ struct StackData {
// story.
template <typename FilterType>
absl::enable_if_t<!std::is_empty<typename FilterType::Call>::value, size_t>
AddFilter(FilterType* channel_data) {
AddFilterConstructor(FilterType* channel_data) {
const size_t alignment = alignof(typename FilterType::Call);
call_data_alignment = std::max(call_data_alignment, alignment);
if (call_data_size % alignment != 0) {
call_data_size += alignment - call_data_size % alignment;
}
const size_t call_offset = call_data_size;
call_data_size += sizeof(typename FilterType::Call);
filters.push_back(Filter{
filter_constructor.push_back(FilterConstructor{
channel_data,
call_offset,
[](void* call_data, void* channel_data) {
CallConstructor<FilterType>::Construct(
call_data, static_cast<FilterType*>(channel_data));
},
[](void* call_data) {
static_cast<typename FilterType::Call*>(call_data)->~Call();
},
});
return call_offset;
}

template <typename FilterType>
absl::enable_if_t<std::is_empty<typename FilterType::Call>::value, size_t>
AddFilter(FilterType* channel_data) {
absl::enable_if_t<
std::is_empty<typename FilterType::Call>::value &&
!std::is_trivially_constructible<typename FilterType::Call>::value,
size_t>
AddFilterConstructor(FilterType* channel_data) {
const size_t alignment = alignof(typename FilterType::Call);
call_data_alignment = std::max(call_data_alignment, alignment);
filters.push_back(Filter{
filter_constructor.push_back(FilterConstructor{
channel_data,
0,
[](void* call_data, void* channel_data) {
CallConstructor<FilterType>::Construct(
call_data, static_cast<FilterType*>(channel_data));
},
});
return 0;
}

template <typename FilterType>
absl::enable_if_t<
std::is_empty<typename FilterType::Call>::value &&
std::is_trivially_constructible<typename FilterType::Call>::value,
size_t>
AddFilterConstructor(FilterType* channel_data) {
const size_t alignment = alignof(typename FilterType::Call);
call_data_alignment = std::max(call_data_alignment, alignment);
return 0;
}

template <typename FilterType>
absl::enable_if_t<
!std::is_trivially_destructible<typename FilterType::Call>::value>
AddFilterDestructor(size_t call_offset) {
filter_destructor.push_back(FilterDestructor{
call_offset,
[](void* call_data) {
static_cast<typename FilterType::Call*>(call_data)->~Call();
},
});
return 0;
}

template <typename FilterType>
absl::enable_if_t<
std::is_trivially_destructible<typename FilterType::Call>::value>
AddFilterDestructor(size_t call_offset) {}

template <typename FilterType>
size_t AddFilter(FilterType* filter) {
const size_t call_offset = AddFilterConstructor(filter);
AddFilterDestructor<FilterType>(call_offset);
return call_offset;
}

// Per operation adders - one for each interception point.
Expand Down
Loading

0 comments on commit 467e7d5

Please sign in to comment.