Merge pull request #13288 from ncteisen/inheritance-in-core

Support Manually Constructed Virtual Functions in C Core
pull/13483/head
Noah Eisen 7 years ago committed by GitHub
commit 9c26f6866a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      BUILD
  2. 29
      CMakeLists.txt
  3. 47
      Makefile
  4. 12
      build.yaml
  5. 2
      gRPC-Core.podspec
  6. 1
      grpc.gemspec
  7. 1
      package.xml
  8. 1
      src/core/ext/transport/chttp2/transport/flow_control.h
  9. 29
      src/core/lib/support/abstract.h
  10. 135
      src/core/lib/support/manual_constructor.h
  11. 12
      templates/Makefile.template
  12. 10
      test/core/support/BUILD
  13. 99
      test/core/support/manual_constructor_test.cc
  14. 1
      tools/doxygen/Doxyfile.c++.internal
  15. 1
      tools/doxygen/Doxyfile.core.internal
  16. 17
      tools/run_tests/generated/sources_and_headers.json
  17. 24
      tools/run_tests/generated/tests.json

@ -480,6 +480,7 @@ grpc_cc_library(
],
hdrs = [
"src/core/lib/profiling/timers.h",
"src/core/lib/support/abstract.h",
"src/core/lib/support/arena.h",
"src/core/lib/support/atomic.h",
"src/core/lib/support/atomic_with_atm.h",

@ -430,6 +430,7 @@ add_dependencies(buildtests_c gpr_env_test)
add_dependencies(buildtests_c gpr_histogram_test)
add_dependencies(buildtests_c gpr_host_port_test)
add_dependencies(buildtests_c gpr_log_test)
add_dependencies(buildtests_c gpr_manual_constructor_test)
add_dependencies(buildtests_c gpr_mpscq_test)
add_dependencies(buildtests_c gpr_spinlock_test)
add_dependencies(buildtests_c gpr_stack_lockfree_test)
@ -6390,6 +6391,34 @@ target_link_libraries(gpr_log_test
endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)
add_executable(gpr_manual_constructor_test
test/core/support/manual_constructor_test.cc
)
target_include_directories(gpr_manual_constructor_test
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
PRIVATE ${BORINGSSL_ROOT_DIR}/include
PRIVATE ${PROTOBUF_ROOT_DIR}/src
PRIVATE ${BENCHMARK_ROOT_DIR}/include
PRIVATE ${ZLIB_ROOT_DIR}
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
PRIVATE ${CARES_INCLUDE_DIR}
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
)
target_link_libraries(gpr_manual_constructor_test
${_gRPC_ALLTARGETS_LIBRARIES}
gpr_test_util
gpr
)
endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)
add_executable(gpr_mpscq_test
test/core/support/mpscq_test.cc
)

@ -328,6 +328,7 @@ ifeq ($(SYSTEM),Darwin)
CXXFLAGS += -stdlib=libc++
endif
CPPFLAGS += -g -Wall -Wextra -Werror -Wno-long-long -Wno-unused-parameter -DOSATOMIC_USE_INLINED=1 -Ithird_party/abseil-cpp
COREFLAGS += -fno-rtti -fno-exceptions
LDFLAGS += -g
CPPFLAGS += $(CPPFLAGS_$(CONFIG))
@ -990,6 +991,7 @@ gpr_env_test: $(BINDIR)/$(CONFIG)/gpr_env_test
gpr_histogram_test: $(BINDIR)/$(CONFIG)/gpr_histogram_test
gpr_host_port_test: $(BINDIR)/$(CONFIG)/gpr_host_port_test
gpr_log_test: $(BINDIR)/$(CONFIG)/gpr_log_test
gpr_manual_constructor_test: $(BINDIR)/$(CONFIG)/gpr_manual_constructor_test
gpr_mpscq_test: $(BINDIR)/$(CONFIG)/gpr_mpscq_test
gpr_spinlock_test: $(BINDIR)/$(CONFIG)/gpr_spinlock_test
gpr_stack_lockfree_test: $(BINDIR)/$(CONFIG)/gpr_stack_lockfree_test
@ -1384,6 +1386,7 @@ buildtests_c: privatelibs_c \
$(BINDIR)/$(CONFIG)/gpr_histogram_test \
$(BINDIR)/$(CONFIG)/gpr_host_port_test \
$(BINDIR)/$(CONFIG)/gpr_log_test \
$(BINDIR)/$(CONFIG)/gpr_manual_constructor_test \
$(BINDIR)/$(CONFIG)/gpr_mpscq_test \
$(BINDIR)/$(CONFIG)/gpr_spinlock_test \
$(BINDIR)/$(CONFIG)/gpr_stack_lockfree_test \
@ -1831,6 +1834,8 @@ test_c: buildtests_c
$(Q) $(BINDIR)/$(CONFIG)/gpr_host_port_test || ( echo test gpr_host_port_test failed ; exit 1 )
$(E) "[RUN] Testing gpr_log_test"
$(Q) $(BINDIR)/$(CONFIG)/gpr_log_test || ( echo test gpr_log_test failed ; exit 1 )
$(E) "[RUN] Testing gpr_manual_constructor_test"
$(Q) $(BINDIR)/$(CONFIG)/gpr_manual_constructor_test || ( echo test gpr_manual_constructor_test failed ; exit 1 )
$(E) "[RUN] Testing gpr_mpscq_test"
$(Q) $(BINDIR)/$(CONFIG)/gpr_mpscq_test || ( echo test gpr_mpscq_test failed ; exit 1 )
$(E) "[RUN] Testing gpr_spinlock_test"
@ -2579,6 +2584,16 @@ $(OBJDIR)/$(CONFIG)/src/compiler/%.o : src/compiler/%.cc
$(Q) mkdir -p `dirname $@`
$(Q) $(HOST_CXX) $(HOST_CXXFLAGS) $(HOST_CPPFLAGS) -MMD -MF $(addsuffix .dep, $(basename $@)) -c -o $@ $<
$(OBJDIR)/$(CONFIG)/src/core/%.o : src/core/%.cc
$(E) "[CXX] Compiling $<"
$(Q) mkdir -p `dirname $@`
$(Q) $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(COREFLAGS) -MMD -MF $(addsuffix .dep, $(basename $@)) -c -o $@ $<
$(OBJDIR)/$(CONFIG)/test/core/%.o : test/core/%.cc
$(E) "[CXX] Compiling $<"
$(Q) mkdir -p `dirname $@`
$(Q) $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(COREFLAGS) -MMD -MF $(addsuffix .dep, $(basename $@)) -c -o $@ $<
$(OBJDIR)/$(CONFIG)/%.o : %.cc
$(E) "[CXX] Compiling $<"
$(Q) mkdir -p `dirname $@`
@ -10147,6 +10162,38 @@ endif
endif
GPR_MANUAL_CONSTRUCTOR_TEST_SRC = \
test/core/support/manual_constructor_test.cc \
GPR_MANUAL_CONSTRUCTOR_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GPR_MANUAL_CONSTRUCTOR_TEST_SRC))))
ifeq ($(NO_SECURE),true)
# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/gpr_manual_constructor_test: openssl_dep_error
else
$(BINDIR)/$(CONFIG)/gpr_manual_constructor_test: $(GPR_MANUAL_CONSTRUCTOR_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
$(Q) $(LD) $(LDFLAGS) $(GPR_MANUAL_CONSTRUCTOR_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/gpr_manual_constructor_test
endif
$(OBJDIR)/$(CONFIG)/test/core/support/manual_constructor_test.o: $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
deps_gpr_manual_constructor_test: $(GPR_MANUAL_CONSTRUCTOR_TEST_OBJS:.o=.dep)
ifneq ($(NO_SECURE),true)
ifneq ($(NO_DEPS),true)
-include $(GPR_MANUAL_CONSTRUCTOR_TEST_OBJS:.o=.dep)
endif
endif
GPR_MPSCQ_TEST_SRC = \
test/core/support/mpscq_test.cc \

@ -104,6 +104,7 @@ filegroups:
- include/grpc/support/useful.h
headers:
- src/core/lib/profiling/timers.h
- src/core/lib/support/abstract.h
- src/core/lib/support/arena.h
- src/core/lib/support/atomic.h
- src/core/lib/support/atomic_with_atm.h
@ -2215,6 +2216,16 @@ targets:
- gpr_test_util
- gpr
uses_polling: false
- name: gpr_manual_constructor_test
cpu_cost: 3
build: test
language: c
src:
- test/core/support/manual_constructor_test.cc
deps:
- gpr_test_util
- gpr
uses_polling: false
- name: gpr_mpscq_test
cpu_cost: 30
build: test
@ -4965,6 +4976,7 @@ defaults:
CPPFLAGS: -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM
-D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX
global:
COREFLAGS: -fno-rtti -fno-exceptions
CPPFLAGS: -g -Wall -Wextra -Werror -Wno-long-long -Wno-unused-parameter -DOSATOMIC_USE_INLINED=1
-Ithird_party/abseil-cpp
LDFLAGS: -g

@ -187,6 +187,7 @@ Pod::Spec.new do |s|
# To save you from scrolling, this is the last part of the podspec.
ss.source_files = 'src/core/lib/profiling/timers.h',
'src/core/lib/support/abstract.h',
'src/core/lib/support/arena.h',
'src/core/lib/support/atomic.h',
'src/core/lib/support/atomic_with_atm.h',
@ -706,6 +707,7 @@ Pod::Spec.new do |s|
'src/core/plugin_registry/grpc_plugin_registry.cc'
ss.private_header_files = 'src/core/lib/profiling/timers.h',
'src/core/lib/support/abstract.h',
'src/core/lib/support/arena.h',
'src/core/lib/support/atomic.h',
'src/core/lib/support/atomic_with_atm.h',

@ -84,6 +84,7 @@ Gem::Specification.new do |s|
s.files += %w( include/grpc/impl/codegen/sync_posix.h )
s.files += %w( include/grpc/impl/codegen/sync_windows.h )
s.files += %w( src/core/lib/profiling/timers.h )
s.files += %w( src/core/lib/support/abstract.h )
s.files += %w( src/core/lib/support/arena.h )
s.files += %w( src/core/lib/support/atomic.h )
s.files += %w( src/core/lib/support/atomic_with_atm.h )

@ -96,6 +96,7 @@
<file baseinstalldir="/" name="include/grpc/impl/codegen/sync_posix.h" role="src" />
<file baseinstalldir="/" name="include/grpc/impl/codegen/sync_windows.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/profiling/timers.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/support/abstract.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/support/arena.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/support/atomic.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/support/atomic_with_atm.h" role="src" />

@ -19,6 +19,7 @@
#ifndef GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_FLOW_CONTROL_H
#define GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_FLOW_CONTROL_H
#include <grpc/support/port_platform.h>
#include <stdint.h>
#include <grpc/support/useful.h>

@ -0,0 +1,29 @@
/*
*
* Copyright 2017 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_SUPPORT_ABSTRACT_H
#define GRPC_CORE_LIB_SUPPORT_ABSTRACT_H
// This is needed to support abstract base classes in the c core. Since gRPC
// doesn't have a c++ runtime, it will hit a linker error on delete unless
// we define a virtual operator delete. See this blog for more info:
// https://eli.thegreenplace.net/2015/c-deleting-destructors-and-virtual-operator-delete/
#define GRPC_ABSTRACT_BASE_CLASS \
static void operator delete(void* p) { abort(); }
#endif /* GRPC_CORE_LIB_SUPPORT_ABSTRACT_H */

@ -22,12 +22,147 @@
// manually construct a region of memory with some type
#include <stddef.h>
#include <stdlib.h>
#include <new>
#include <type_traits>
#include <utility>
#include <grpc/support/log.h>
namespace grpc_core {
// this contains templated helpers needed to implement the ManualConstructors
// in this file.
namespace manual_ctor_impl {
// is_one_of returns true it a class, Member, is present in a variadic list of
// classes, List.
template <class Member, class... List>
class is_one_of;
template <class Member, class... List>
class is_one_of<Member, Member, List...> {
public:
static constexpr const bool value = true;
};
template <class Member, class A, class... List>
class is_one_of<Member, A, List...> {
public:
static constexpr const bool value = is_one_of<Member, List...>::value;
};
template <class Member>
class is_one_of<Member> {
public:
static constexpr const bool value = false;
};
// max_size_of returns sizeof(Type) for the largest type in the variadic list
// of classes, Types.
template <class... Types>
class max_size_of;
template <class A>
class max_size_of<A> {
public:
static constexpr const size_t value = sizeof(A);
};
template <class A, class... B>
class max_size_of<A, B...> {
public:
static constexpr const size_t value = sizeof(A) > max_size_of<B...>::value
? sizeof(A)
: max_size_of<B...>::value;
};
// max_size_of returns alignof(Type) for the largest type in the variadic list
// of classes, Types.
template <class... Types>
class max_align_of;
template <class A>
class max_align_of<A> {
public:
static constexpr const size_t value = alignof(A);
};
template <class A, class... B>
class max_align_of<A, B...> {
public:
static constexpr const size_t value = alignof(A) > max_align_of<B...>::value
? alignof(A)
: max_align_of<B...>::value;
};
} // namespace manual_ctor_impl
template <class BaseType, class... DerivedTypes>
class PolymorphicManualConstructor {
public:
// No constructor or destructor because one of the most useful uses of
// this class is as part of a union, and members of a union could not have
// constructors or destructors till C++11. And, anyway, the whole point of
// this class is to bypass constructor and destructor.
BaseType* get() { return reinterpret_cast<BaseType*>(&space_); }
const BaseType* get() const {
return reinterpret_cast<const BaseType*>(&space_);
}
BaseType* operator->() { return get(); }
const BaseType* operator->() const { return get(); }
BaseType& operator*() { return *get(); }
const BaseType& operator*() const { return *get(); }
template <class DerivedType>
void Init() {
FinishInit(new (&space_) DerivedType);
}
// Init() constructs the Type instance using the given arguments
// (which are forwarded to Type's constructor).
//
// Note that Init() with no arguments performs default-initialization,
// not zero-initialization (i.e it behaves the same as "new Type;", not
// "new Type();"), so it will leave non-class types uninitialized.
template <class DerivedType, typename... Ts>
void Init(Ts&&... args) {
FinishInit(new (&space_) DerivedType(std::forward<Ts>(args)...));
}
// Init() that is equivalent to copy and move construction.
// Enables usage like this:
// ManualConstructor<std::vector<int>> v;
// v.Init({1, 2, 3});
template <class DerivedType>
void Init(const DerivedType& x) {
FinishInit(new (&space_) DerivedType(x));
}
template <class DerivedType>
void Init(DerivedType&& x) {
FinishInit(new (&space_) DerivedType(std::move(x)));
}
void Destroy() { get()->~BaseType(); }
private:
template <class DerivedType>
void FinishInit(DerivedType* p) {
static_assert(
manual_ctor_impl::is_one_of<DerivedType, DerivedTypes...>::value,
"DerivedType must be one of the predeclared DerivedTypes");
GPR_ASSERT(reinterpret_cast<BaseType*>(static_cast<DerivedType*>(p)) == p);
}
typename std::aligned_storage<
grpc_core::manual_ctor_impl::max_size_of<DerivedTypes...>::value,
grpc_core::manual_ctor_impl::max_align_of<DerivedTypes...>::value>::type
space_;
};
template <typename Type>
class ManualConstructor {
public:

@ -215,7 +215,7 @@
ifeq ($(SYSTEM),Darwin)
CXXFLAGS += -stdlib=libc++
endif
% for arg in ['CFLAGS', 'CXXFLAGS', 'CPPFLAGS', 'LDFLAGS', 'DEFINES']:
% for arg in ['CFLAGS', 'CXXFLAGS', 'CPPFLAGS', 'COREFLAGS', 'LDFLAGS', 'DEFINES']:
% if defaults.get('global', []).get(arg, None) is not None:
${arg} += ${defaults.get('global').get(arg)}
% endif
@ -1268,6 +1268,16 @@
$(Q) mkdir -p `dirname $@`
$(Q) $(HOST_CXX) $(HOST_CXXFLAGS) $(HOST_CPPFLAGS) -MMD -MF $(addsuffix .dep, $(basename $@)) -c -o $@ $<
$(OBJDIR)/$(CONFIG)/src/core/%.o : src/core/%.cc
$(E) "[CXX] Compiling $<"
$(Q) mkdir -p `dirname $@`
$(Q) $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(COREFLAGS) -MMD -MF $(addsuffix .dep, $(basename $@)) -c -o $@ $<
$(OBJDIR)/$(CONFIG)/test/core/%.o : test/core/%.cc
$(E) "[CXX] Compiling $<"
$(Q) mkdir -p `dirname $@`
$(Q) $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(COREFLAGS) -MMD -MF $(addsuffix .dep, $(basename $@)) -c -o $@ $<
$(OBJDIR)/$(CONFIG)/%.o : %.cc
$(E) "[CXX] Compiling $<"
$(Q) mkdir -p `dirname $@`

@ -138,6 +138,16 @@ grpc_cc_test(
],
)
grpc_cc_test(
name = "manual_constructor_test",
srcs = ["manual_constructor_test.cc"],
language = "C++",
deps = [
"//:gpr",
"//test/core/util:gpr_test_util",
],
)
grpc_cc_test(
name = "spinlock_test",
srcs = ["spinlock_test.cc"],

@ -0,0 +1,99 @@
/*
*
* Copyright 2017 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.
*
*/
/* Test of gpr synchronization support. */
#include "src/core/lib/support/manual_constructor.h"
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/sync.h>
#include <grpc/support/thd.h>
#include <stdio.h>
#include <stdlib.h>
#include <cstring>
#include "src/core/lib/support/abstract.h"
#include "test/core/util/test_config.h"
class A {
public:
A() {}
virtual ~A() {}
virtual const char* foo() { return "A_foo"; }
virtual const char* bar() { return "A_bar"; }
GRPC_ABSTRACT_BASE_CLASS
};
class B : public A {
public:
B() {}
~B() {}
const char* foo() override { return "B_foo"; }
char get_junk() { return junk[0]; }
private:
char junk[1000];
};
class C : public B {
public:
C() {}
~C() {}
virtual const char* bar() { return "C_bar"; }
char get_more_junk() { return more_junk[0]; }
private:
char more_junk[1000];
};
class D : public A {
public:
virtual const char* bar() { return "D_bar"; }
};
static void basic_test() {
grpc_core::PolymorphicManualConstructor<A, B> poly;
poly.Init<B>();
GPR_ASSERT(!strcmp(poly->foo(), "B_foo"));
GPR_ASSERT(!strcmp(poly->bar(), "A_bar"));
}
static void complex_test() {
grpc_core::PolymorphicManualConstructor<A, B, C, D> polyB;
polyB.Init<B>();
GPR_ASSERT(!strcmp(polyB->foo(), "B_foo"));
GPR_ASSERT(!strcmp(polyB->bar(), "A_bar"));
grpc_core::PolymorphicManualConstructor<A, B, C, D> polyC;
polyC.Init<C>();
GPR_ASSERT(!strcmp(polyC->foo(), "B_foo"));
GPR_ASSERT(!strcmp(polyC->bar(), "C_bar"));
grpc_core::PolymorphicManualConstructor<A, B, C, D> polyD;
polyD.Init<D>();
GPR_ASSERT(!strcmp(polyD->foo(), "A_foo"));
GPR_ASSERT(!strcmp(polyD->bar(), "D_bar"));
}
/* ------------------------------------------------- */
int main(int argc, char* argv[]) {
grpc_test_init(argc, argv);
basic_test();
complex_test();
return 0;
}

@ -1026,6 +1026,7 @@ src/core/lib/slice/percent_encoding.h \
src/core/lib/slice/slice_hash_table.h \
src/core/lib/slice/slice_internal.h \
src/core/lib/slice/slice_string_helpers.h \
src/core/lib/support/abstract.h \
src/core/lib/support/arena.h \
src/core/lib/support/atomic.h \
src/core/lib/support/atomic_with_atm.h \

@ -1267,6 +1267,7 @@ src/core/lib/slice/slice_intern.cc \
src/core/lib/slice/slice_internal.h \
src/core/lib/slice/slice_string_helpers.cc \
src/core/lib/slice/slice_string_helpers.h \
src/core/lib/support/abstract.h \
src/core/lib/support/alloc.cc \
src/core/lib/support/arena.cc \
src/core/lib/support/arena.h \

@ -748,6 +748,21 @@
"third_party": false,
"type": "target"
},
{
"deps": [
"gpr",
"gpr_test_util"
],
"headers": [],
"is_filegroup": false,
"language": "c",
"name": "gpr_manual_constructor_test",
"src": [
"test/core/support/manual_constructor_test.cc"
],
"third_party": false,
"type": "target"
},
{
"deps": [
"gpr",
@ -7814,6 +7829,7 @@
"include/grpc/support/tls_pthread.h",
"include/grpc/support/useful.h",
"src/core/lib/profiling/timers.h",
"src/core/lib/support/abstract.h",
"src/core/lib/support/arena.h",
"src/core/lib/support/atomic.h",
"src/core/lib/support/atomic_with_atm.h",
@ -7862,6 +7878,7 @@
"include/grpc/support/tls_pthread.h",
"include/grpc/support/useful.h",
"src/core/lib/profiling/timers.h",
"src/core/lib/support/abstract.h",
"src/core/lib/support/arena.h",
"src/core/lib/support/atomic.h",
"src/core/lib/support/atomic_with_atm.h",

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

Loading…
Cancel
Save