From fcff618e6f09baf8fb69ed6d4d5c9be94a433511 Mon Sep 17 00:00:00 2001 From: Craig Tiller <craig.tiller@gmail.com> Date: Fri, 5 Jun 2015 10:56:10 -0700 Subject: [PATCH] Clarify some of the call stuff --- include/grpc++/impl/call.h | 68 +++++++++++++++++++++++--------------- 1 file changed, 42 insertions(+), 26 deletions(-) diff --git a/include/grpc++/impl/call.h b/include/grpc++/impl/call.h index 0951bf0320..30260d2a2f 100644 --- a/include/grpc++/impl/call.h +++ b/include/grpc++/impl/call.h @@ -59,6 +59,9 @@ void FillMetadataMap(grpc_metadata_array* arr, grpc_metadata* FillMetadataArray( const std::multimap<grpc::string, grpc::string>& metadata); +/// Default argument for CallOpSet. I is unused by the class, but can be +/// used for generating multiple names for the same thing. +template <int I> class CallNoOp { protected: void AddOp(grpc_op* ops, size_t* nops) {} @@ -344,9 +347,16 @@ class CallOpClientRecvStatus { size_t status_details_capacity_; }; +/// An abstract collection of call ops, used to generate the +/// grpc_call_op structure to pass down to the lower layers, +/// and as it is-a CompletionQueueTag, also massages the final +/// completion into the correct form for consumption in the C++ +/// API. class CallOpSetInterface : public CompletionQueueTag { public: CallOpSetInterface() : max_message_size_(0) {} + /// Fills in grpc_op, starting from ops[*nops] and moving + /// upwards. virtual void FillOps(grpc_op* ops, size_t* nops) = 0; void set_max_message_size(int max_message_size) { @@ -357,36 +367,39 @@ class CallOpSetInterface : public CompletionQueueTag { int max_message_size_; }; -template <class T, int I> -class WrapAndDerive : public T {}; - -template <class Op1 = CallNoOp, class Op2 = CallNoOp, class Op3 = CallNoOp, - class Op4 = CallNoOp, class Op5 = CallNoOp, class Op6 = CallNoOp> +/// Primary implementaiton of CallOpSetInterface. +/// Since we cannot use variadic templates, we declare slots up to +/// the maximum count of ops we'll need in a set. We leverage the +/// empty base class optimization to slim this class (especially +/// when there are many unused slots used). To avoid duplicate base classes, +/// the template parmeter for CallNoOp is varied by argument position. +template <class Op1 = CallNoOp<1>, class Op2 = CallNoOp<2>, class Op3 = CallNoOp<3>, + class Op4 = CallNoOp<4>, class Op5 = CallNoOp<5>, class Op6 = CallNoOp<6>> class CallOpSet : public CallOpSetInterface, - public WrapAndDerive<Op1, 1>, - public WrapAndDerive<Op2, 2>, - public WrapAndDerive<Op3, 3>, - public WrapAndDerive<Op4, 4>, - public WrapAndDerive<Op5, 5>, - public WrapAndDerive<Op6, 6> { + public Op1, + public Op2, + public Op3, + public Op4, + public Op5, + public Op6 { public: CallOpSet() : return_tag_(this) {} void FillOps(grpc_op* ops, size_t* nops) GRPC_OVERRIDE { - this->WrapAndDerive<Op1, 1>::AddOp(ops, nops); - this->WrapAndDerive<Op2, 2>::AddOp(ops, nops); - this->WrapAndDerive<Op3, 3>::AddOp(ops, nops); - this->WrapAndDerive<Op4, 4>::AddOp(ops, nops); - this->WrapAndDerive<Op5, 5>::AddOp(ops, nops); - this->WrapAndDerive<Op6, 6>::AddOp(ops, nops); + this->Op1::AddOp(ops, nops); + this->Op2::AddOp(ops, nops); + this->Op3::AddOp(ops, nops); + this->Op4::AddOp(ops, nops); + this->Op5::AddOp(ops, nops); + this->Op6::AddOp(ops, nops); } bool FinalizeResult(void** tag, bool* status) GRPC_OVERRIDE { - this->WrapAndDerive<Op1, 1>::FinishOp(status, max_message_size_); - this->WrapAndDerive<Op2, 2>::FinishOp(status, max_message_size_); - this->WrapAndDerive<Op3, 3>::FinishOp(status, max_message_size_); - this->WrapAndDerive<Op4, 4>::FinishOp(status, max_message_size_); - this->WrapAndDerive<Op5, 5>::FinishOp(status, max_message_size_); - this->WrapAndDerive<Op6, 6>::FinishOp(status, max_message_size_); + this->Op1::FinishOp(status, max_message_size_); + this->Op2::FinishOp(status, max_message_size_); + this->Op3::FinishOp(status, max_message_size_); + this->Op4::FinishOp(status, max_message_size_); + this->Op5::FinishOp(status, max_message_size_); + this->Op6::FinishOp(status, max_message_size_); *tag = return_tag_; return true; } @@ -397,9 +410,12 @@ class CallOpSet : public CallOpSetInterface, void* return_tag_; }; -// SneakyCallOpBuffer does not post completions to the completion queue -template <class Op1 = CallNoOp, class Op2 = CallNoOp, class Op3 = CallNoOp, - class Op4 = CallNoOp, class Op5 = CallNoOp, class Op6 = CallNoOp> +/// A CallOpSet that does not post completions to the completion queue. +/// +/// Allows hiding some completions that the C core must generate from +/// C++ users. +template <class Op1 = CallNoOp<1>, class Op2 = CallNoOp<2>, class Op3 = CallNoOp<3>, + class Op4 = CallNoOp<4>, class Op5 = CallNoOp<5>, class Op6 = CallNoOp<6>> class SneakyCallOpSet GRPC_FINAL : public CallOpSet<Op1, Op2, Op3, Op4, Op5, Op6> { public: -- GitLab