aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt2
-rw-r--r--Makefile18
-rw-r--r--build.yaml3
-rw-r--r--grpc.def1
-rw-r--r--include/grpc++/impl/codegen/async_unary_call.h61
-rw-r--r--include/grpc++/impl/codegen/call.h49
-rw-r--r--include/grpc/grpc.h4
-rw-r--r--src/compiler/cpp_generator.cc4
-rw-r--r--src/core/lib/surface/call.c4
-rw-r--r--src/ruby/ext/grpc/rb_grpc_imports.generated.c2
-rw-r--r--src/ruby/ext/grpc/rb_grpc_imports.generated.h3
-rw-r--r--tools/run_tests/generated/sources_and_headers.json2
-rw-r--r--vsprojects/vcxproj/test/codegen_test_minimal/codegen_test_minimal.vcxproj8
13 files changed, 125 insertions, 36 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5a442be6c5..ca1d4dbd95 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -9323,6 +9323,8 @@ target_include_directories(codegen_test_minimal
target_link_libraries(codegen_test_minimal
${_gRPC_PROTOBUF_LIBRARIES}
${_gRPC_ALLTARGETS_LIBRARIES}
+ grpc
+ gpr
${_gRPC_GFLAGS_LIBRARIES}
)
diff --git a/Makefile b/Makefile
index a28a27c0da..fa07a545ab 100644
--- a/Makefile
+++ b/Makefile
@@ -13690,28 +13690,28 @@ $(BINDIR)/$(CONFIG)/codegen_test_minimal: protobuf_dep_error
else
-$(BINDIR)/$(CONFIG)/codegen_test_minimal: $(PROTOBUF_DEP) $(CODEGEN_TEST_MINIMAL_OBJS)
+$(BINDIR)/$(CONFIG)/codegen_test_minimal: $(PROTOBUF_DEP) $(CODEGEN_TEST_MINIMAL_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
- $(Q) $(LDXX) $(LDFLAGS) $(CODEGEN_TEST_MINIMAL_OBJS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/codegen_test_minimal
+ $(Q) $(LDXX) $(LDFLAGS) $(CODEGEN_TEST_MINIMAL_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/codegen_test_minimal
endif
endif
-$(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/control.o:
+$(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/control.o: $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a
-$(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/messages.o:
+$(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/messages.o: $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a
-$(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/payloads.o:
+$(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/payloads.o: $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a
-$(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/services.o:
+$(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/services.o: $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a
-$(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/stats.o:
+$(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/stats.o: $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a
-$(OBJDIR)/$(CONFIG)/test/cpp/codegen/codegen_test_minimal.o:
+$(OBJDIR)/$(CONFIG)/test/cpp/codegen/codegen_test_minimal.o: $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a
-$(OBJDIR)/$(CONFIG)/src/cpp/codegen/codegen_init.o:
+$(OBJDIR)/$(CONFIG)/src/cpp/codegen/codegen_init.o: $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a
deps_codegen_test_minimal: $(CODEGEN_TEST_MINIMAL_OBJS:.o=.dep)
diff --git a/build.yaml b/build.yaml
index 0a0b84dfb6..c74faa8fe0 100644
--- a/build.yaml
+++ b/build.yaml
@@ -3456,6 +3456,9 @@ targets:
- src/proto/grpc/testing/services.proto
- src/proto/grpc/testing/stats.proto
- test/cpp/codegen/codegen_test_minimal.cc
+ deps:
+ - grpc
+ - gpr
filegroups:
- grpc++_codegen_base
- grpc++_codegen_base_src
diff --git a/grpc.def b/grpc.def
index 1589316a58..39f06d8cc0 100644
--- a/grpc.def
+++ b/grpc.def
@@ -70,6 +70,7 @@ EXPORTS
grpc_channel_ping
grpc_channel_register_call
grpc_channel_create_registered_call
+ grpc_call_arena_alloc
grpc_call_start_batch
grpc_call_get_peer
grpc_call_set_load_reporting_cost_context
diff --git a/include/grpc++/impl/codegen/async_unary_call.h b/include/grpc++/impl/codegen/async_unary_call.h
index b77a16b699..50bb399df6 100644
--- a/include/grpc++/impl/codegen/async_unary_call.h
+++ b/include/grpc++/impl/codegen/async_unary_call.h
@@ -34,6 +34,7 @@
#ifndef GRPCXX_IMPL_CODEGEN_ASYNC_UNARY_CALL_H
#define GRPCXX_IMPL_CODEGEN_ASYNC_UNARY_CALL_H
+#include <assert.h>
#include <grpc++/impl/codegen/call.h>
#include <grpc++/impl/codegen/channel_interface.h>
#include <grpc++/impl/codegen/client_context.h>
@@ -41,6 +42,8 @@
#include <grpc++/impl/codegen/service_type.h>
#include <grpc++/impl/codegen/status.h>
+extern "C" void* grpc_call_arena_alloc(grpc_call* call, size_t size);
+
namespace grpc {
class CompletionQueue;
@@ -58,20 +61,40 @@ template <class R>
class ClientAsyncResponseReader final
: public ClientAsyncResponseReaderInterface<R> {
public:
+ ~ClientAsyncResponseReader() {
+ if (collection_ != nullptr && collection_->Unref()) {
+ delete collection_;
+ }
+ }
template <class W>
- ClientAsyncResponseReader(ChannelInterface* channel, CompletionQueue* cq,
- const RpcMethod& method, ClientContext* context,
- const W& request)
- : context_(context),
- call_(channel->CreateCall(method, context, cq)),
- collection_(std::make_shared<CallOpSetCollection>()) {
- collection_->init_buf_.SetCollection(collection_);
- collection_->init_buf_.SendInitialMetadata(
+ static ClientAsyncResponseReader* Create(ChannelInterface* channel,
+ CompletionQueue* cq,
+ const RpcMethod& method,
+ ClientContext* context,
+ const W& request) {
+ Call call = channel->CreateCall(method, context, cq);
+ ClientAsyncResponseReader* reader = static_cast<ClientAsyncResponseReader*>(
+ grpc_call_arena_alloc(call.call(), sizeof(*reader)));
+ new (&reader->call_) Call(std::move(call));
+ reader->context_ = context;
+ reader->collection_ =
+ new (grpc_call_arena_alloc(call.call(), sizeof(CallOpSetCollection)))
+ CallOpSetCollection();
+
+ reader->collection_->init_buf_.SetCollection(reader->collection_);
+ reader->collection_->init_buf_.SendInitialMetadata(
context->send_initial_metadata_, context->initial_metadata_flags());
// TODO(ctiller): don't assert
- GPR_CODEGEN_ASSERT(collection_->init_buf_.SendMessage(request).ok());
- collection_->init_buf_.ClientSendClose();
- call_.PerformOps(&collection_->init_buf_);
+ GPR_CODEGEN_ASSERT(
+ reader->collection_->init_buf_.SendMessage(request).ok());
+ reader->collection_->init_buf_.ClientSendClose();
+ reader->call_.PerformOps(&reader->collection_->init_buf_);
+ return reader;
+ }
+
+ // always allocated against a call arena, no memory free required
+ static void operator delete(void* ptr, std::size_t size) {
+ assert(size == sizeof(ClientAsyncResponseReader));
}
void ReadInitialMetadata(void* tag) {
@@ -99,7 +122,10 @@ class ClientAsyncResponseReader final
ClientContext* context_;
Call call_;
- class CallOpSetCollection : public CallOpSetCollectionInterface {
+ // disable operator new
+ static void* operator new(std::size_t size);
+
+ class CallOpSetCollection final : public CallOpSetCollectionInterface {
public:
SneakyCallOpSet<CallOpSendInitialMetadata, CallOpSendMessage,
CallOpClientSendClose>
@@ -108,8 +134,17 @@ class ClientAsyncResponseReader final
CallOpSet<CallOpRecvInitialMetadata, CallOpRecvMessage<R>,
CallOpClientRecvStatus>
finish_buf_;
+
+ static void* operator new(std::size_t size, void* p) { return p; }
+ static void operator delete(void* ptr, std::size_t size) {
+ assert(size == sizeof(CallOpSetCollection));
+ }
+
+ private:
+ // disable operator new
+ static void* operator new(std::size_t size);
};
- std::shared_ptr<CallOpSetCollection> collection_;
+ CallOpSetCollection* collection_;
};
template <class W>
diff --git a/include/grpc++/impl/codegen/call.h b/include/grpc++/impl/codegen/call.h
index a3f2be6bb1..9c8611a116 100644
--- a/include/grpc++/impl/codegen/call.h
+++ b/include/grpc++/impl/codegen/call.h
@@ -34,6 +34,7 @@
#ifndef GRPCXX_IMPL_CODEGEN_CALL_H
#define GRPCXX_IMPL_CODEGEN_CALL_H
+#include <assert.h>
#include <cstring>
#include <functional>
#include <map>
@@ -50,6 +51,7 @@
#include <grpc++/impl/codegen/status_helper.h>
#include <grpc++/impl/codegen/string_ref.h>
+#include <grpc/impl/codegen/atm.h>
#include <grpc/impl/codegen/compression_types.h>
#include <grpc/impl/codegen/grpc_types.h>
@@ -561,14 +563,29 @@ class CallOpClientRecvStatus {
/// An abstract collection of CallOpSet's, to be used whenever
/// CallOpSet objects must be thought of as a group. Each member
-/// of the group should have a shared_ptr back to the collection,
-/// as will the object that instantiates the collection, allowing
-/// for automatic ref-counting. In practice, any actual use should
-/// derive from this base class. This is specifically necessary if
-/// some of the CallOpSet's in the collection are "Sneaky" and don't
-/// report back to the C++ layer CQ operations
-class CallOpSetCollectionInterface
- : public std::enable_shared_from_this<CallOpSetCollectionInterface> {};
+/// of the group should reference the collection, as will the object
+/// that instantiates the collection, allowing for ref-counting.
+/// Any actual use should derive from this base class. This is specifically
+/// necessary if some of the CallOpSet's in the collection are "Sneaky" and
+/// don't report back to the C++ layer CQ operations
+class CallOpSetCollectionInterface {
+ public:
+ CallOpSetCollectionInterface() {
+ gpr_atm_rel_store(&refs_, static_cast<gpr_atm>(1));
+ }
+ // always allocated against a call arena, no memory free required
+ static void operator delete(void* ptr, std::size_t size) {
+ }
+ void Ref() { gpr_atm_no_barrier_fetch_add(&refs_, static_cast<gpr_atm>(1)); }
+ bool Unref() {
+ gpr_atm old =
+ gpr_atm_full_fetch_add(&refs_, static_cast<gpr_atm>(-1));
+ return (old == static_cast<gpr_atm>(1));
+ }
+
+ private:
+ gpr_atm refs_;
+};
/// An abstract collection of call ops, used to generate the
/// grpc_call_op structure to pass down to the lower layers,
@@ -577,18 +594,26 @@ class CallOpSetCollectionInterface
/// API.
class CallOpSetInterface : public CompletionQueueTag {
public:
- CallOpSetInterface() {}
+ CallOpSetInterface() : collection_(nullptr) {}
+ ~CallOpSetInterface() { ResetCollection(); }
/// Fills in grpc_op, starting from ops[*nops] and moving
/// upwards.
virtual void FillOps(grpc_op* ops, size_t* nops) = 0;
/// Mark this as belonging to a collection if needed
- void SetCollection(std::shared_ptr<CallOpSetCollectionInterface> collection) {
+ void SetCollection(CallOpSetCollectionInterface* collection) {
collection_ = collection;
+ collection->Ref();
+ }
+ void ResetCollection() {
+ if (collection_ != nullptr && collection_->Unref()) {
+ delete collection_;
+ }
+ collection_ = nullptr;
}
protected:
- std::shared_ptr<CallOpSetCollectionInterface> collection_;
+ CallOpSetCollectionInterface* collection_;
};
/// Primary implementaiton of CallOpSetInterface.
@@ -626,7 +651,7 @@ class CallOpSet : public CallOpSetInterface,
this->Op5::FinishOp(status);
this->Op6::FinishOp(status);
*tag = return_tag_;
- collection_.reset(); // drop the ref at this point
+ ResetCollection(); // drop the ref at this point
return true;
}
diff --git a/include/grpc/grpc.h b/include/grpc/grpc.h
index e088435d6c..3430cd31e9 100644
--- a/include/grpc/grpc.h
+++ b/include/grpc/grpc.h
@@ -263,6 +263,10 @@ GRPCAPI grpc_call *grpc_channel_create_registered_call(
grpc_completion_queue *completion_queue, void *registered_call_handle,
gpr_timespec deadline, void *reserved);
+/** Allocate memory in the grpc_call arena: this memory is automatically
+ discarded at call completion */
+GRPCAPI void *grpc_call_arena_alloc(grpc_call *call, size_t size);
+
/** Start a batch of operations defined in the array ops; when complete, post a
completion of type 'tag' to the completion queue bound to the call.
The order of ops specified in the batch has no significance.
diff --git a/src/compiler/cpp_generator.cc b/src/compiler/cpp_generator.cc
index 2908b639f3..d223dacc26 100644
--- a/src/compiler/cpp_generator.cc
+++ b/src/compiler/cpp_generator.cc
@@ -1078,8 +1078,8 @@ void PrintSourceClientMethod(Printer *printer, const Method *method,
"const $Request$& request, "
"::grpc::CompletionQueue* cq) {\n");
printer->Print(*vars,
- " return new "
- "::grpc::ClientAsyncResponseReader< $Response$>("
+ " return "
+ "::grpc::ClientAsyncResponseReader< $Response$>::Create("
"channel_.get(), cq, "
"rpcmethod_$Method$_, "
"context, request);\n"
diff --git a/src/core/lib/surface/call.c b/src/core/lib/surface/call.c
index a9317a4694..71c65d86ee 100644
--- a/src/core/lib/surface/call.c
+++ b/src/core/lib/surface/call.c
@@ -268,6 +268,10 @@ static void add_init_error(grpc_error **composite, grpc_error *new) {
*composite = grpc_error_add_child(*composite, new);
}
+void *grpc_call_arena_alloc(grpc_call *call, size_t size) {
+ return gpr_arena_alloc(call->arena, size);
+}
+
grpc_error *grpc_call_create(grpc_exec_ctx *exec_ctx,
const grpc_call_create_args *args,
grpc_call **out_call) {
diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.c b/src/ruby/ext/grpc/rb_grpc_imports.generated.c
index 063f92114c..294ca2c5a4 100644
--- a/src/ruby/ext/grpc/rb_grpc_imports.generated.c
+++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.c
@@ -108,6 +108,7 @@ grpc_channel_create_call_type grpc_channel_create_call_import;
grpc_channel_ping_type grpc_channel_ping_import;
grpc_channel_register_call_type grpc_channel_register_call_import;
grpc_channel_create_registered_call_type grpc_channel_create_registered_call_import;
+grpc_call_arena_alloc_type grpc_call_arena_alloc_import;
grpc_call_start_batch_type grpc_call_start_batch_import;
grpc_call_get_peer_type grpc_call_get_peer_import;
grpc_call_set_load_reporting_cost_context_type grpc_call_set_load_reporting_cost_context_import;
@@ -405,6 +406,7 @@ void grpc_rb_load_imports(HMODULE library) {
grpc_channel_ping_import = (grpc_channel_ping_type) GetProcAddress(library, "grpc_channel_ping");
grpc_channel_register_call_import = (grpc_channel_register_call_type) GetProcAddress(library, "grpc_channel_register_call");
grpc_channel_create_registered_call_import = (grpc_channel_create_registered_call_type) GetProcAddress(library, "grpc_channel_create_registered_call");
+ grpc_call_arena_alloc_import = (grpc_call_arena_alloc_type) GetProcAddress(library, "grpc_call_arena_alloc");
grpc_call_start_batch_import = (grpc_call_start_batch_type) GetProcAddress(library, "grpc_call_start_batch");
grpc_call_get_peer_import = (grpc_call_get_peer_type) GetProcAddress(library, "grpc_call_get_peer");
grpc_call_set_load_reporting_cost_context_import = (grpc_call_set_load_reporting_cost_context_type) GetProcAddress(library, "grpc_call_set_load_reporting_cost_context");
diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.h b/src/ruby/ext/grpc/rb_grpc_imports.generated.h
index f5dcd68a8e..7b40dd2f27 100644
--- a/src/ruby/ext/grpc/rb_grpc_imports.generated.h
+++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.h
@@ -275,6 +275,9 @@ extern grpc_channel_register_call_type grpc_channel_register_call_import;
typedef grpc_call *(*grpc_channel_create_registered_call_type)(grpc_channel *channel, grpc_call *parent_call, uint32_t propagation_mask, grpc_completion_queue *completion_queue, void *registered_call_handle, gpr_timespec deadline, void *reserved);
extern grpc_channel_create_registered_call_type grpc_channel_create_registered_call_import;
#define grpc_channel_create_registered_call grpc_channel_create_registered_call_import
+typedef void *(*grpc_call_arena_alloc_type)(grpc_call *call, size_t size);
+extern grpc_call_arena_alloc_type grpc_call_arena_alloc_import;
+#define grpc_call_arena_alloc grpc_call_arena_alloc_import
typedef grpc_call_error(*grpc_call_start_batch_type)(grpc_call *call, const grpc_op *ops, size_t nops, void *tag, void *reserved);
extern grpc_call_start_batch_type grpc_call_start_batch_import;
#define grpc_call_start_batch grpc_call_start_batch_import
diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json
index 6dfb1d6ed6..2cada0ac09 100644
--- a/tools/run_tests/generated/sources_and_headers.json
+++ b/tools/run_tests/generated/sources_and_headers.json
@@ -2819,6 +2819,8 @@
},
{
"deps": [
+ "gpr",
+ "grpc",
"grpc++_codegen_base",
"grpc++_codegen_base_src"
],
diff --git a/vsprojects/vcxproj/test/codegen_test_minimal/codegen_test_minimal.vcxproj b/vsprojects/vcxproj/test/codegen_test_minimal/codegen_test_minimal.vcxproj
index fd014fdc09..d176a36f20 100644
--- a/vsprojects/vcxproj/test/codegen_test_minimal/codegen_test_minimal.vcxproj
+++ b/vsprojects/vcxproj/test/codegen_test_minimal/codegen_test_minimal.vcxproj
@@ -257,6 +257,14 @@
</ClCompile>
</ItemGroup>
<ItemGroup>
+ <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc\grpc.vcxproj">
+ <Project>{29D16885-7228-4C31-81ED-5F9187C7F2A9}</Project>
+ </ProjectReference>
+ <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr\gpr.vcxproj">
+ <Project>{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}</Project>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />