|  | @@ -87,6 +87,28 @@ class ClientAsyncResponseReader final
 | 
	
		
			
				|  |  |          ClientAsyncResponseReader(call, context, request);
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +  /// TODO(vjpai): Delete the below constructor
 | 
	
		
			
				|  |  | +  /// PLEASE DO NOT USE THIS CONSTRUCTOR IN NEW CODE
 | 
	
		
			
				|  |  | +  /// This code is only present as a short-term workaround
 | 
	
		
			
				|  |  | +  /// for users that bypassed the code-generator and directly
 | 
	
		
			
				|  |  | +  /// created this struct rather than properly using a stub.
 | 
	
		
			
				|  |  | +  /// This code will not remain a valid public constructor for long.
 | 
	
		
			
				|  |  | +  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<Ops>()) {
 | 
	
		
			
				|  |  | +    collection_->init_buf.SetCollection(collection_);
 | 
	
		
			
				|  |  | +    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);
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |    // always allocated against a call arena, no memory free required
 | 
	
		
			
				|  |  |    static void operator delete(void* ptr, std::size_t size) {
 | 
	
		
			
				|  |  |      assert(size == sizeof(ClientAsyncResponseReader));
 | 
	
	
		
			
				|  | @@ -101,9 +123,18 @@ class ClientAsyncResponseReader final
 | 
	
		
			
				|  |  |    void ReadInitialMetadata(void* tag) {
 | 
	
		
			
				|  |  |      GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    meta_buf_.set_output_tag(tag);
 | 
	
		
			
				|  |  | -    meta_buf_.RecvInitialMetadata(context_);
 | 
	
		
			
				|  |  | -    call_.PerformOps(&meta_buf_);
 | 
	
		
			
				|  |  | +    Ops& o = ops_;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // TODO(vjpai): Remove the collection_ specialization as soon
 | 
	
		
			
				|  |  | +    // as the public constructor is deleted
 | 
	
		
			
				|  |  | +    if (collection_) {
 | 
	
		
			
				|  |  | +      o = *collection_;
 | 
	
		
			
				|  |  | +      collection_->meta_buf.SetCollection(collection_);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    o.meta_buf.set_output_tag(tag);
 | 
	
		
			
				|  |  | +    o.meta_buf.RecvInitialMetadata(context_);
 | 
	
		
			
				|  |  | +    call_.PerformOps(&o.meta_buf);
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    /// See \a ClientAysncResponseReaderInterface::Finish for semantics.
 | 
	
	
		
			
				|  | @@ -112,14 +143,23 @@ class ClientAsyncResponseReader final
 | 
	
		
			
				|  |  |    ///   - the \a ClientContext associated with this call is updated with
 | 
	
		
			
				|  |  |    ///     possible initial and trailing metadata sent from the server.
 | 
	
		
			
				|  |  |    void Finish(R* msg, Status* status, void* tag) {
 | 
	
		
			
				|  |  | -    finish_buf_.set_output_tag(tag);
 | 
	
		
			
				|  |  | +    Ops& o = ops_;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // TODO(vjpai): Remove the collection_ specialization as soon
 | 
	
		
			
				|  |  | +    // as the public constructor is deleted
 | 
	
		
			
				|  |  | +    if (collection_) {
 | 
	
		
			
				|  |  | +      o = *collection_;
 | 
	
		
			
				|  |  | +      collection_->finish_buf.SetCollection(collection_);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    o.finish_buf.set_output_tag(tag);
 | 
	
		
			
				|  |  |      if (!context_->initial_metadata_received_) {
 | 
	
		
			
				|  |  | -      finish_buf_.RecvInitialMetadata(context_);
 | 
	
		
			
				|  |  | +      o.finish_buf.RecvInitialMetadata(context_);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -    finish_buf_.RecvMessage(msg);
 | 
	
		
			
				|  |  | -    finish_buf_.AllowNoMessage();
 | 
	
		
			
				|  |  | -    finish_buf_.ClientRecvStatus(context_, status);
 | 
	
		
			
				|  |  | -    call_.PerformOps(&finish_buf_);
 | 
	
		
			
				|  |  | +    o.finish_buf.RecvMessage(msg);
 | 
	
		
			
				|  |  | +    o.finish_buf.AllowNoMessage();
 | 
	
		
			
				|  |  | +    o.finish_buf.ClientRecvStatus(context_, status);
 | 
	
		
			
				|  |  | +    call_.PerformOps(&o.finish_buf);
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |   private:
 | 
	
	
		
			
				|  | @@ -129,25 +169,33 @@ class ClientAsyncResponseReader final
 | 
	
		
			
				|  |  |    template <class W>
 | 
	
		
			
				|  |  |    ClientAsyncResponseReader(Call call, ClientContext* context, const W& request)
 | 
	
		
			
				|  |  |        : context_(context), call_(call) {
 | 
	
		
			
				|  |  | -    init_buf_.SendInitialMetadata(context->send_initial_metadata_,
 | 
	
		
			
				|  |  | -                                  context->initial_metadata_flags());
 | 
	
		
			
				|  |  | +    ops_.init_buf.SendInitialMetadata(context->send_initial_metadata_,
 | 
	
		
			
				|  |  | +                                      context->initial_metadata_flags());
 | 
	
		
			
				|  |  |      // TODO(ctiller): don't assert
 | 
	
		
			
				|  |  | -    GPR_CODEGEN_ASSERT(init_buf_.SendMessage(request).ok());
 | 
	
		
			
				|  |  | -    init_buf_.ClientSendClose();
 | 
	
		
			
				|  |  | -    call_.PerformOps(&init_buf_);
 | 
	
		
			
				|  |  | +    GPR_CODEGEN_ASSERT(ops_.init_buf.SendMessage(request).ok());
 | 
	
		
			
				|  |  | +    ops_.init_buf.ClientSendClose();
 | 
	
		
			
				|  |  | +    call_.PerformOps(&ops_.init_buf);
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    // disable operator new
 | 
	
		
			
				|  |  |    static void* operator new(std::size_t size);
 | 
	
		
			
				|  |  |    static void* operator new(std::size_t size, void* p) { return p; }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  SneakyCallOpSet<CallOpSendInitialMetadata, CallOpSendMessage,
 | 
	
		
			
				|  |  | -                  CallOpClientSendClose>
 | 
	
		
			
				|  |  | -      init_buf_;
 | 
	
		
			
				|  |  | -  CallOpSet<CallOpRecvInitialMetadata> meta_buf_;
 | 
	
		
			
				|  |  | -  CallOpSet<CallOpRecvInitialMetadata, CallOpRecvMessage<R>,
 | 
	
		
			
				|  |  | -            CallOpClientRecvStatus>
 | 
	
		
			
				|  |  | -      finish_buf_;
 | 
	
		
			
				|  |  | +  // TODO(vjpai): Remove the reference to CallOpSetCollectionInterface
 | 
	
		
			
				|  |  | +  // as soon as the related workaround (public constructor) is deleted
 | 
	
		
			
				|  |  | +  struct Ops : public CallOpSetCollectionInterface {
 | 
	
		
			
				|  |  | +    SneakyCallOpSet<CallOpSendInitialMetadata, CallOpSendMessage,
 | 
	
		
			
				|  |  | +                    CallOpClientSendClose>
 | 
	
		
			
				|  |  | +        init_buf;
 | 
	
		
			
				|  |  | +    CallOpSet<CallOpRecvInitialMetadata> meta_buf;
 | 
	
		
			
				|  |  | +    CallOpSet<CallOpRecvInitialMetadata, CallOpRecvMessage<R>,
 | 
	
		
			
				|  |  | +              CallOpClientRecvStatus>
 | 
	
		
			
				|  |  | +        finish_buf;
 | 
	
		
			
				|  |  | +  } ops_;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  // TODO(vjpai): Remove the collection_ as soon as the related workaround
 | 
	
		
			
				|  |  | +  // (public constructor) is deleted
 | 
	
		
			
				|  |  | +  std::shared_ptr<Ops> collection_;
 | 
	
		
			
				|  |  |  };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  /// Async server-side API for handling unary calls, where the single
 |