diff options
author | Craig Tiller <ctiller@google.com> | 2017-03-16 09:42:43 -0700 |
---|---|---|
committer | Craig Tiller <ctiller@google.com> | 2017-03-16 09:42:43 -0700 |
commit | 58450914326278bd7b6fe3cb61cc47b33d89c2c8 (patch) | |
tree | 0c7a5f2f7e52a291b7a6423703cab9456771d2af /include | |
parent | 9f6b9aba888b695c4c154f4fe773ffd06633964a (diff) |
[EXPERIMENTAL] allocate unary response writer against call arena
Diffstat (limited to 'include')
-rw-r--r-- | include/grpc++/impl/codegen/async_unary_call.h | 53 | ||||
-rw-r--r-- | include/grpc/grpc.h | 4 |
2 files changed, 45 insertions, 12 deletions
diff --git a/include/grpc++/impl/codegen/async_unary_call.h b/include/grpc++/impl/codegen/async_unary_call.h index b77a16b699..d11986b6ec 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; @@ -59,19 +62,33 @@ class ClientAsyncResponseReader final : public ClientAsyncResponseReaderInterface<R> { public: 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; + new (&reader->collection_) std::shared_ptr<CallOpSetCollection>( + 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 +116,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,6 +128,15 @@ 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_; }; diff --git a/include/grpc/grpc.h b/include/grpc/grpc.h index 1b33d48c02..d603f89c28 100644 --- a/include/grpc/grpc.h +++ b/include/grpc/grpc.h @@ -198,6 +198,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. |