[metadata] Improve codegen for name lookups (#33237)

The approach of doing a recursive function call to expand the if checks
for known metadata names was tripping up an optimization clang has to
collapse that if/then tree into an optimized tree search over the set of
known strings. By unrolling that loop (with a code generator) we start
to present a pattern that clang *can* recognize, and hopefully get some
more stable and faster code generation as a benefit.

<!--

If you know who should review your pull request, please assign it to
that
person, otherwise the pull request would get assigned randomly.

If your pull request is for a specific language, please add the
appropriate
lang label.

-->

---------

Co-authored-by: ctiller <ctiller@users.noreply.github.com>
pull/33361/head
Craig Tiller 1 year ago committed by GitHub
parent 683261d217
commit 1f85fb21f2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      BUILD
  2. 37
      CMakeLists.txt
  3. 19
      build_autogenerated.yaml
  4. 4
      gRPC-C++.podspec
  5. 4
      gRPC-Core.podspec
  6. 2
      grpc.gemspec
  7. 2
      package.xml
  8. 20
      src/core/BUILD
  9. 4530
      src/core/lib/gprpp/if_list.h
  10. 15
      src/core/lib/gprpp/sorted_pack.h
  11. 32
      src/core/lib/gprpp/type_list.h
  12. 69
      src/core/lib/transport/metadata_batch.h
  13. 12
      test/core/gprpp/BUILD
  14. 37
      test/core/gprpp/if_list_test.cc
  15. 76
      tools/codegen/core/gen_if_list.py
  16. 2
      tools/doxygen/Doxyfile.c++.internal
  17. 2
      tools/doxygen/Doxyfile.core.internal
  18. 24
      tools/run_tests/generated/tests.json

@ -1550,6 +1550,7 @@ grpc_cc_library(
"//src/core:grpc_sockaddr",
"//src/core:http2_errors",
"//src/core:if",
"//src/core:if_list",
"//src/core:init_internally",
"//src/core:iomgr_fwd",
"//src/core:iomgr_port",
@ -1589,6 +1590,7 @@ grpc_cc_library(
"//src/core:transport_fwd",
"//src/core:try_join",
"//src/core:try_seq",
"//src/core:type_list",
"//src/core:useful",
"//src/core:windows_event_engine",
"//src/core:windows_event_engine_listener",

37
CMakeLists.txt generated

@ -1027,6 +1027,7 @@ if(gRPC_BUILD_TESTS)
endif()
add_dependencies(buildtests_cxx hybrid_end2end_test)
add_dependencies(buildtests_cxx idle_filter_state_test)
add_dependencies(buildtests_cxx if_list_test)
add_dependencies(buildtests_cxx if_test)
add_dependencies(buildtests_cxx init_test)
add_dependencies(buildtests_cxx initial_settings_frame_bad_client_test)
@ -13940,6 +13941,42 @@ target_link_libraries(idle_filter_state_test
)
endif()
if(gRPC_BUILD_TESTS)
add_executable(if_list_test
test/core/gprpp/if_list_test.cc
third_party/googletest/googletest/src/gtest-all.cc
third_party/googletest/googlemock/src/gmock-all.cc
)
target_compile_features(if_list_test PUBLIC cxx_std_14)
target_include_directories(if_list_test
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/include
${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
${_gRPC_RE2_INCLUDE_DIR}
${_gRPC_SSL_INCLUDE_DIR}
${_gRPC_UPB_GENERATED_DIR}
${_gRPC_UPB_GRPC_GENERATED_DIR}
${_gRPC_UPB_INCLUDE_DIR}
${_gRPC_XXHASH_INCLUDE_DIR}
${_gRPC_ZLIB_INCLUDE_DIR}
third_party/googletest/googletest/include
third_party/googletest/googletest
third_party/googletest/googlemock/include
third_party/googletest/googlemock
${_gRPC_PROTO_GENS_DIR}
)
target_link_libraries(if_list_test
${_gRPC_BASELIB_LIBRARIES}
${_gRPC_PROTOBUF_LIBRARIES}
${_gRPC_ZLIB_LIBRARIES}
${_gRPC_ALLTARGETS_LIBRARIES}
)
endif()
if(gRPC_BUILD_TESTS)

@ -733,6 +733,7 @@ libs:
- src/core/lib/gprpp/chunked_vector.h
- src/core/lib/gprpp/cpp_impl_of.h
- src/core/lib/gprpp/dual_ref_counted.h
- src/core/lib/gprpp/if_list.h
- src/core/lib/gprpp/load_file.h
- src/core/lib/gprpp/manual_constructor.h
- src/core/lib/gprpp/match.h
@ -749,6 +750,7 @@ libs:
- src/core/lib/gprpp/table.h
- src/core/lib/gprpp/time.h
- src/core/lib/gprpp/time_averaged_stats.h
- src/core/lib/gprpp/type_list.h
- src/core/lib/gprpp/unique_type_name.h
- src/core/lib/gprpp/validation_errors.h
- src/core/lib/gprpp/work_serializer.h
@ -2112,6 +2114,7 @@ libs:
- src/core/lib/gprpp/chunked_vector.h
- src/core/lib/gprpp/cpp_impl_of.h
- src/core/lib/gprpp/dual_ref_counted.h
- src/core/lib/gprpp/if_list.h
- src/core/lib/gprpp/load_file.h
- src/core/lib/gprpp/manual_constructor.h
- src/core/lib/gprpp/match.h
@ -2128,6 +2131,7 @@ libs:
- src/core/lib/gprpp/table.h
- src/core/lib/gprpp/time.h
- src/core/lib/gprpp/time_averaged_stats.h
- src/core/lib/gprpp/type_list.h
- src/core/lib/gprpp/unique_type_name.h
- src/core/lib/gprpp/validation_errors.h
- src/core/lib/gprpp/work_serializer.h
@ -3608,6 +3612,7 @@ libs:
- src/core/lib/gprpp/chunked_vector.h
- src/core/lib/gprpp/cpp_impl_of.h
- src/core/lib/gprpp/dual_ref_counted.h
- src/core/lib/gprpp/if_list.h
- src/core/lib/gprpp/load_file.h
- src/core/lib/gprpp/manual_constructor.h
- src/core/lib/gprpp/match.h
@ -3623,6 +3628,7 @@ libs:
- src/core/lib/gprpp/table.h
- src/core/lib/gprpp/time.h
- src/core/lib/gprpp/time_averaged_stats.h
- src/core/lib/gprpp/type_list.h
- src/core/lib/gprpp/unique_type_name.h
- src/core/lib/gprpp/validation_errors.h
- src/core/lib/gprpp/work_serializer.h
@ -7552,6 +7558,7 @@ targets:
- src/core/lib/gprpp/chunked_vector.h
- src/core/lib/gprpp/cpp_impl_of.h
- src/core/lib/gprpp/dual_ref_counted.h
- src/core/lib/gprpp/if_list.h
- src/core/lib/gprpp/load_file.h
- src/core/lib/gprpp/manual_constructor.h
- src/core/lib/gprpp/match.h
@ -7567,6 +7574,7 @@ targets:
- src/core/lib/gprpp/table.h
- src/core/lib/gprpp/time.h
- src/core/lib/gprpp/time_averaged_stats.h
- src/core/lib/gprpp/type_list.h
- src/core/lib/gprpp/unique_type_name.h
- src/core/lib/gprpp/validation_errors.h
- src/core/lib/gprpp/work_serializer.h
@ -8913,6 +8921,16 @@ targets:
- test/core/client_idle/idle_filter_state_test.cc
deps: []
uses_polling: false
- name: if_list_test
gtest: true
build: test
language: c++
headers:
- src/core/lib/gprpp/if_list.h
src:
- test/core/gprpp/if_list_test.cc
deps: []
uses_polling: false
- name: if_test
gtest: true
build: test
@ -11318,6 +11336,7 @@ targets:
language: c++
headers:
- src/core/lib/gprpp/sorted_pack.h
- src/core/lib/gprpp/type_list.h
src:
- test/core/gprpp/sorted_pack_test.cc
deps: []

4
gRPC-C++.podspec generated

@ -818,6 +818,7 @@ Pod::Spec.new do |s|
'src/core/lib/gprpp/examine_stack.h',
'src/core/lib/gprpp/fork.h',
'src/core/lib/gprpp/host_port.h',
'src/core/lib/gprpp/if_list.h',
'src/core/lib/gprpp/load_file.h',
'src/core/lib/gprpp/manual_constructor.h',
'src/core/lib/gprpp/match.h',
@ -843,6 +844,7 @@ Pod::Spec.new do |s|
'src/core/lib/gprpp/time.h',
'src/core/lib/gprpp/time_averaged_stats.h',
'src/core/lib/gprpp/time_util.h',
'src/core/lib/gprpp/type_list.h',
'src/core/lib/gprpp/unique_type_name.h',
'src/core/lib/gprpp/validation_errors.h',
'src/core/lib/gprpp/work_serializer.h',
@ -1856,6 +1858,7 @@ Pod::Spec.new do |s|
'src/core/lib/gprpp/examine_stack.h',
'src/core/lib/gprpp/fork.h',
'src/core/lib/gprpp/host_port.h',
'src/core/lib/gprpp/if_list.h',
'src/core/lib/gprpp/load_file.h',
'src/core/lib/gprpp/manual_constructor.h',
'src/core/lib/gprpp/match.h',
@ -1881,6 +1884,7 @@ Pod::Spec.new do |s|
'src/core/lib/gprpp/time.h',
'src/core/lib/gprpp/time_averaged_stats.h',
'src/core/lib/gprpp/time_util.h',
'src/core/lib/gprpp/type_list.h',
'src/core/lib/gprpp/unique_type_name.h',
'src/core/lib/gprpp/validation_errors.h',
'src/core/lib/gprpp/work_serializer.h',

4
gRPC-Core.podspec generated

@ -1298,6 +1298,7 @@ Pod::Spec.new do |s|
'src/core/lib/gprpp/fork.h',
'src/core/lib/gprpp/host_port.cc',
'src/core/lib/gprpp/host_port.h',
'src/core/lib/gprpp/if_list.h',
'src/core/lib/gprpp/linux/env.cc',
'src/core/lib/gprpp/load_file.cc',
'src/core/lib/gprpp/load_file.h',
@ -1336,6 +1337,7 @@ Pod::Spec.new do |s|
'src/core/lib/gprpp/time_averaged_stats.h',
'src/core/lib/gprpp/time_util.cc',
'src/core/lib/gprpp/time_util.h',
'src/core/lib/gprpp/type_list.h',
'src/core/lib/gprpp/unique_type_name.h',
'src/core/lib/gprpp/validation_errors.cc',
'src/core/lib/gprpp/validation_errors.h',
@ -2583,6 +2585,7 @@ Pod::Spec.new do |s|
'src/core/lib/gprpp/examine_stack.h',
'src/core/lib/gprpp/fork.h',
'src/core/lib/gprpp/host_port.h',
'src/core/lib/gprpp/if_list.h',
'src/core/lib/gprpp/load_file.h',
'src/core/lib/gprpp/manual_constructor.h',
'src/core/lib/gprpp/match.h',
@ -2608,6 +2611,7 @@ Pod::Spec.new do |s|
'src/core/lib/gprpp/time.h',
'src/core/lib/gprpp/time_averaged_stats.h',
'src/core/lib/gprpp/time_util.h',
'src/core/lib/gprpp/type_list.h',
'src/core/lib/gprpp/unique_type_name.h',
'src/core/lib/gprpp/validation_errors.h',
'src/core/lib/gprpp/work_serializer.h',

2
grpc.gemspec generated

@ -1204,6 +1204,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/gprpp/fork.h )
s.files += %w( src/core/lib/gprpp/host_port.cc )
s.files += %w( src/core/lib/gprpp/host_port.h )
s.files += %w( src/core/lib/gprpp/if_list.h )
s.files += %w( src/core/lib/gprpp/linux/env.cc )
s.files += %w( src/core/lib/gprpp/load_file.cc )
s.files += %w( src/core/lib/gprpp/load_file.h )
@ -1242,6 +1243,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/gprpp/time_averaged_stats.h )
s.files += %w( src/core/lib/gprpp/time_util.cc )
s.files += %w( src/core/lib/gprpp/time_util.h )
s.files += %w( src/core/lib/gprpp/type_list.h )
s.files += %w( src/core/lib/gprpp/unique_type_name.h )
s.files += %w( src/core/lib/gprpp/validation_errors.cc )
s.files += %w( src/core/lib/gprpp/validation_errors.h )

2
package.xml generated

@ -1186,6 +1186,7 @@
<file baseinstalldir="/" name="src/core/lib/gprpp/fork.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/gprpp/host_port.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/gprpp/host_port.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/gprpp/if_list.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/gprpp/linux/env.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/gprpp/load_file.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/gprpp/load_file.h" role="src" />
@ -1224,6 +1225,7 @@
<file baseinstalldir="/" name="src/core/lib/gprpp/time_averaged_stats.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/gprpp/time_util.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/gprpp/time_util.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/gprpp/type_list.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/gprpp/unique_type_name.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/gprpp/validation_errors.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/gprpp/validation_errors.h" role="src" />

@ -2764,6 +2764,26 @@ grpc_cc_library(
"lib/gprpp/sorted_pack.h",
],
language = "c++",
deps = [
"type_list",
"//:gpr_platform",
],
)
grpc_cc_library(
name = "type_list",
hdrs = [
"lib/gprpp/type_list.h",
],
language = "c++",
)
grpc_cc_library(
name = "if_list",
hdrs = [
"lib/gprpp/if_list.h",
],
language = "c++",
deps = ["//:gpr_platform"],
)

File diff suppressed because it is too large Load Diff

@ -19,20 +19,12 @@
#include <type_traits>
#include "src/core/lib/gprpp/type_list.h"
namespace grpc_core {
namespace sorted_pack_detail {
// A list of types
template <typename... A>
struct Typelist {
template <template <typename...> class T>
using Instantiate = T<A...>;
template <typename C>
using PushFront = Typelist<C, A...>;
};
// Find the smallest element of Args, and the rest of the elements
template <template <typename, typename> class Cmp, typename Args>
struct Smallest;
@ -89,8 +81,7 @@ template <template <typename...> class T,
template <typename, typename> class Cmp, typename... Args>
struct WithSortedPack {
using Type = typename sorted_pack_detail::Sorted<
Cmp,
sorted_pack_detail::Typelist<Args...>>::Result::template Instantiate<T>;
Cmp, Typelist<Args...>>::Result::template Instantiate<T>;
};
} // namespace grpc_core

@ -0,0 +1,32 @@
// Copyright 2023 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_SRC_CORE_LIB_GPRPP_TYPE_LIST_H
#define GRPC_SRC_CORE_LIB_GPRPP_TYPE_LIST_H
namespace grpc_core {
// A list of types
template <typename... A>
struct Typelist {
template <template <typename...> class T>
using Instantiate = T<A...>;
template <typename C>
using PushFront = Typelist<C, A...>;
};
} // namespace grpc_core
#endif // GRPC_SRC_CORE_LIB_GPRPP_TYPE_LIST_H

@ -41,8 +41,10 @@
#include "src/core/lib/compression/compression_internal.h"
#include "src/core/lib/gprpp/chunked_vector.h"
#include "src/core/lib/gprpp/if_list.h"
#include "src/core/lib/gprpp/packed_table.h"
#include "src/core/lib/gprpp/time.h"
#include "src/core/lib/gprpp/type_list.h"
#include "src/core/lib/resource_quota/arena.h"
#include "src/core/lib/slice/slice.h"
#include "src/core/lib/transport/custom_metadata.h"
@ -517,44 +519,53 @@ struct IsEncodableTrait<Trait, absl::void_t<decltype(Trait::key())>> {
static const bool value = true;
};
// Helper type - maps a string name to a trait.
template <typename MustBeVoid, typename... Traits>
struct NameLookup;
struct EncodableTraits;
template <typename Trait, typename... Traits>
struct NameLookup<absl::enable_if_t<IsEncodableTrait<Trait>::value, void>,
Trait, Traits...> {
// Call op->Found(Trait()) if op->name == Trait::key() for some Trait in
// Traits. If not found, call op->NotFound().
template <typename Op>
static auto Lookup(absl::string_view key, Op* op)
-> decltype(op->Found(Trait())) {
if (key == Trait::key()) {
return op->Found(Trait());
}
return NameLookup<void, Traits...>::Lookup(key, op);
}
struct EncodableTraits<absl::enable_if_t<IsEncodableTrait<Trait>::value, void>,
Trait, Traits...> {
using List =
typename EncodableTraits<void,
Traits...>::List::template PushFront<Trait>;
};
template <typename Trait, typename... Traits>
struct NameLookup<absl::enable_if_t<!IsEncodableTrait<Trait>::value, void>,
Trait, Traits...> {
template <typename Op>
static auto Lookup(absl::string_view key, Op* op)
-> decltype(NameLookup<void, Traits...>::Lookup(key, op)) {
return NameLookup<void, Traits...>::Lookup(key, op);
}
struct EncodableTraits<absl::enable_if_t<!IsEncodableTrait<Trait>::value, void>,
Trait, Traits...> {
using List = typename EncodableTraits<void, Traits...>::List;
};
template <>
struct NameLookup<void> {
struct EncodableTraits<void> {
using List = Typelist<>;
};
template <typename Trait>
struct EncodableNameLookupKeyComparison {
bool operator()(absl::string_view key) { return key == Trait::key(); }
};
template <typename Trait, typename Op>
struct EncodableNameLookupOnFound {
auto operator()(Op* op) { return op->Found(Trait()); }
};
template <typename... Traits>
struct EncodableNameLookup {
template <typename Op>
static auto Lookup(absl::string_view key, Op* op)
-> decltype(op->NotFound(key)) {
return op->NotFound(key);
static auto Lookup(absl::string_view key, Op* op) {
return IfList(
key, op, [key](Op* op) { return op->NotFound(key); },
EncodableNameLookupKeyComparison<Traits>()...,
EncodableNameLookupOnFound<Traits, Op>()...);
}
};
template <typename... Traits>
using NameLookup = typename EncodableTraits<
void, Traits...>::List::template Instantiate<EncodableNameLookup>;
// Helper to take a slice to a memento to a value.
// By splitting this part out we can scale code size as the number of
// (memento, value) types, rather than as the number of traits.
@ -1277,7 +1288,7 @@ class MetadataMap {
// Remove some metadata by name
void Remove(absl::string_view key) {
metadata_detail::RemoveHelper<Derived> helper(static_cast<Derived*>(this));
metadata_detail::NameLookup<void, Traits...>::Lookup(key, &helper);
metadata_detail::NameLookup<Traits...>::Lookup(key, &helper);
}
void Remove(const char* key) { Remove(absl::string_view(key)); }
@ -1287,7 +1298,7 @@ class MetadataMap {
std::string* buffer) const {
metadata_detail::GetStringValueHelper<Derived> helper(
static_cast<const Derived*>(this), buffer);
return metadata_detail::NameLookup<void, Traits...>::Lookup(name, &helper);
return metadata_detail::NameLookup<Traits...>::Lookup(name, &helper);
}
// Extract a piece of known metadata.
@ -1328,7 +1339,7 @@ class MetadataMap {
MetadataParseErrorFn on_error) {
metadata_detail::ParseHelper<Derived> helper(value.TakeOwned(), on_error,
transport_size);
return metadata_detail::NameLookup<void, Traits...>::Lookup(key, &helper);
return metadata_detail::NameLookup<Traits...>::Lookup(key, &helper);
}
// Set a value from a parsed metadata object.
@ -1341,7 +1352,7 @@ class MetadataMap {
MetadataParseErrorFn on_error) {
metadata_detail::AppendHelper<Derived> helper(static_cast<Derived*>(this),
value.TakeOwned(), on_error);
metadata_detail::NameLookup<void, Traits...>::Lookup(key, &helper);
metadata_detail::NameLookup<Traits...>::Lookup(key, &helper);
}
void Clear();

@ -66,6 +66,18 @@ grpc_cc_test(
],
)
grpc_cc_test(
name = "if_list_test",
srcs = ["if_list_test.cc"],
external_deps = ["gtest"],
language = "C++",
uses_event_engine = False,
uses_polling = False,
deps = [
"//src/core:if_list",
],
)
grpc_cc_test(
name = "no_destruct_test",
srcs = ["no_destruct_test.cc"],

@ -0,0 +1,37 @@
// Copyright 2023 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/gprpp/if_list.h"
#include "gtest/gtest.h"
namespace grpc_core {
TEST(IfListTest, Works) {
EXPECT_EQ(IfList(
0, 42, [](int) { return -1; }, [](int x) { return x == 0; },
[](int x) { return x; }),
42);
EXPECT_EQ(IfList(
1, 42, [](int) { return -1; }, [](int x) { return x == 0; },
[](int x) { return x; }),
-1);
}
} // namespace grpc_core
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

@ -0,0 +1,76 @@
#!/usr/bin/env python3
# Copyright 2023 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.
import sys
# utility: print a big comment block into a set of files
def put_banner(files, banner):
for f in files:
for line in banner:
print('// %s' % line, file=f)
print('', file=f)
with open('src/core/lib/gprpp/if_list.h', 'w') as H:
# copy-paste copyright notice from this file
with open(sys.argv[0]) as my_source:
copyright = []
for line in my_source:
if line[0] != '#':
break
for line in my_source:
if line[0] == '#':
copyright.append(line)
break
for line in my_source:
if line[0] != '#':
break
copyright.append(line)
put_banner([H], [line[2:].rstrip() for line in copyright])
put_banner([H], ["", "Automatically generated by %s" % sys.argv[0], ""])
print("#ifndef GRPC_CORE_LIB_GPRPP_IF_LIST_H", file=H)
print("#define GRPC_CORE_LIB_GPRPP_IF_LIST_H", file=H)
print('', file=H)
print('#include <grpc/support/port_platform.h>', file=H)
print('', file=H)
print("#include <stdlib.h>", file=H)
print('', file=H)
print("namespace grpc_core {", file=H)
for n in range(1, 64):
print('', file=H)
print(
"template <typename CheckArg, typename ActionArg, typename ActionFail, %s, %s> auto IfList(CheckArg input, ActionArg action_arg, ActionFail action_fail, %s, %s) {"
% (
", ".join("typename Check%d" % (i) for i in range(0, n)),
", ".join("typename Action%d" % (i) for i in range(0, n)),
", ".join("Check%d check%d" % (i, i) for i in range(0, n)),
", ".join("Action%d action%d" % (i, i) for i in range(0, n)),
),
file=H)
for i in range(0, n):
print(" if (check%d(input)) return action%d(action_arg);" % (i, i),
file=H)
print(" return action_fail(action_arg);", file=H)
print("}", file=H)
print('', file=H)
print("}", file=H)
print('', file=H)
print("#endif // GRPC_CORE_LIB_GPRPP_IF_LIST_H", file=H)

@ -2200,6 +2200,7 @@ src/core/lib/gprpp/fork.cc \
src/core/lib/gprpp/fork.h \
src/core/lib/gprpp/host_port.cc \
src/core/lib/gprpp/host_port.h \
src/core/lib/gprpp/if_list.h \
src/core/lib/gprpp/linux/env.cc \
src/core/lib/gprpp/load_file.cc \
src/core/lib/gprpp/load_file.h \
@ -2238,6 +2239,7 @@ src/core/lib/gprpp/time_averaged_stats.cc \
src/core/lib/gprpp/time_averaged_stats.h \
src/core/lib/gprpp/time_util.cc \
src/core/lib/gprpp/time_util.h \
src/core/lib/gprpp/type_list.h \
src/core/lib/gprpp/unique_type_name.h \
src/core/lib/gprpp/validation_errors.cc \
src/core/lib/gprpp/validation_errors.h \

@ -1980,6 +1980,7 @@ src/core/lib/gprpp/fork.cc \
src/core/lib/gprpp/fork.h \
src/core/lib/gprpp/host_port.cc \
src/core/lib/gprpp/host_port.h \
src/core/lib/gprpp/if_list.h \
src/core/lib/gprpp/linux/env.cc \
src/core/lib/gprpp/load_file.cc \
src/core/lib/gprpp/load_file.h \
@ -2018,6 +2019,7 @@ src/core/lib/gprpp/time_averaged_stats.cc \
src/core/lib/gprpp/time_averaged_stats.h \
src/core/lib/gprpp/time_util.cc \
src/core/lib/gprpp/time_util.h \
src/core/lib/gprpp/type_list.h \
src/core/lib/gprpp/unique_type_name.h \
src/core/lib/gprpp/validation_errors.cc \
src/core/lib/gprpp/validation_errors.h \

@ -4097,6 +4097,30 @@
],
"uses_polling": false
},
{
"args": [],
"benchmark": false,
"ci_platforms": [
"linux",
"mac",
"posix",
"windows"
],
"cpu_cost": 1.0,
"exclude_configs": [],
"exclude_iomgrs": [],
"flaky": false,
"gtest": true,
"language": "c++",
"name": "if_list_test",
"platforms": [
"linux",
"mac",
"posix",
"windows"
],
"uses_polling": false
},
{
"args": [],
"benchmark": false,

Loading…
Cancel
Save