|  | @@ -30,6 +30,7 @@
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  namespace grpc {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +namespace internal {
 | 
	
		
			
				|  |  |  /// Common interface for all synchronous client side streaming.
 | 
	
		
			
				|  |  |  class ClientStreamingInterface {
 | 
	
		
			
				|  |  |   public:
 | 
	
	
		
			
				|  | @@ -141,10 +142,12 @@ class WriterInterface {
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +}  // namespace internal
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  /// Client-side interface for streaming reads of message of type \a R.
 | 
	
		
			
				|  |  |  template <class R>
 | 
	
		
			
				|  |  | -class ClientReaderInterface : public ClientStreamingInterface,
 | 
	
		
			
				|  |  | -                              public ReaderInterface<R> {
 | 
	
		
			
				|  |  | +class ClientReaderInterface : public internal::ClientStreamingInterface,
 | 
	
		
			
				|  |  | +                              public internal::ReaderInterface<R> {
 | 
	
		
			
				|  |  |   public:
 | 
	
		
			
				|  |  |    /// Block to wait for initial metadata from server. The received metadata
 | 
	
		
			
				|  |  |    /// can only be accessed after this call returns. Should only be called before
 | 
	
	
		
			
				|  | @@ -153,35 +156,25 @@ class ClientReaderInterface : public ClientStreamingInterface,
 | 
	
		
			
				|  |  |    virtual void WaitForInitialMetadata() = 0;
 | 
	
		
			
				|  |  |  };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +namespace internal {
 | 
	
		
			
				|  |  | +template <class R>
 | 
	
		
			
				|  |  | +class ClientReaderFactory {
 | 
	
		
			
				|  |  | + public:
 | 
	
		
			
				|  |  | +  template <class W>
 | 
	
		
			
				|  |  | +  static ClientReader<R>* Create(ChannelInterface* channel,
 | 
	
		
			
				|  |  | +                                 const ::grpc::internal::RpcMethod& method,
 | 
	
		
			
				|  |  | +                                 ClientContext* context, const W& request) {
 | 
	
		
			
				|  |  | +    return new ClientReader<R>(channel, method, context, request);
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +}  // namespace internal
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  /// Synchronous (blocking) client-side API for doing server-streaming RPCs,
 | 
	
		
			
				|  |  |  /// where the stream of messages coming from the server has messages
 | 
	
		
			
				|  |  |  /// of type \a R.
 | 
	
		
			
				|  |  |  template <class R>
 | 
	
		
			
				|  |  |  class ClientReader final : public ClientReaderInterface<R> {
 | 
	
		
			
				|  |  |   public:
 | 
	
		
			
				|  |  | -  /// Block to create a stream and write the initial metadata and \a request
 | 
	
		
			
				|  |  | -  /// out. Note that \a context will be used to fill in custom initial
 | 
	
		
			
				|  |  | -  /// metadata used to send to the server when starting the call.
 | 
	
		
			
				|  |  | -  template <class W>
 | 
	
		
			
				|  |  | -  ClientReader(ChannelInterface* channel, const RpcMethod& method,
 | 
	
		
			
				|  |  | -               ClientContext* context, const W& request)
 | 
	
		
			
				|  |  | -      : context_(context),
 | 
	
		
			
				|  |  | -        cq_(grpc_completion_queue_attributes{
 | 
	
		
			
				|  |  | -            GRPC_CQ_CURRENT_VERSION, GRPC_CQ_PLUCK,
 | 
	
		
			
				|  |  | -            GRPC_CQ_DEFAULT_POLLING}),  // Pluckable cq
 | 
	
		
			
				|  |  | -        call_(channel->CreateCall(method, context, &cq_)) {
 | 
	
		
			
				|  |  | -    CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage,
 | 
	
		
			
				|  |  | -              CallOpClientSendClose>
 | 
	
		
			
				|  |  | -        ops;
 | 
	
		
			
				|  |  | -    ops.SendInitialMetadata(context->send_initial_metadata_,
 | 
	
		
			
				|  |  | -                            context->initial_metadata_flags());
 | 
	
		
			
				|  |  | -    // TODO(ctiller): don't assert
 | 
	
		
			
				|  |  | -    GPR_CODEGEN_ASSERT(ops.SendMessage(request).ok());
 | 
	
		
			
				|  |  | -    ops.ClientSendClose();
 | 
	
		
			
				|  |  | -    call_.PerformOps(&ops);
 | 
	
		
			
				|  |  | -    cq_.Pluck(&ops);
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |    /// See the \a ClientStreamingInterface.WaitForInitialMetadata method for
 | 
	
		
			
				|  |  |    /// semantics.
 | 
	
		
			
				|  |  |    ///
 | 
	
	
		
			
				|  | @@ -192,7 +185,8 @@ class ClientReader final : public ClientReaderInterface<R> {
 | 
	
		
			
				|  |  |    void WaitForInitialMetadata() override {
 | 
	
		
			
				|  |  |      GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    CallOpSet<CallOpRecvInitialMetadata> ops;
 | 
	
		
			
				|  |  | +    ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata>
 | 
	
		
			
				|  |  | +        ops;
 | 
	
		
			
				|  |  |      ops.RecvInitialMetadata(context_);
 | 
	
		
			
				|  |  |      call_.PerformOps(&ops);
 | 
	
		
			
				|  |  |      cq_.Pluck(&ops);  /// status ignored
 | 
	
	
		
			
				|  | @@ -209,7 +203,9 @@ class ClientReader final : public ClientReaderInterface<R> {
 | 
	
		
			
				|  |  |    ///   already received (if initial metadata is received, it can be then
 | 
	
		
			
				|  |  |    ///   accessed through the \a ClientContext associated with this call).
 | 
	
		
			
				|  |  |    bool Read(R* msg) override {
 | 
	
		
			
				|  |  | -    CallOpSet<CallOpRecvInitialMetadata, CallOpRecvMessage<R>> ops;
 | 
	
		
			
				|  |  | +    ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata,
 | 
	
		
			
				|  |  | +                                ::grpc::internal::CallOpRecvMessage<R>>
 | 
	
		
			
				|  |  | +        ops;
 | 
	
		
			
				|  |  |      if (!context_->initial_metadata_received_) {
 | 
	
		
			
				|  |  |        ops.RecvInitialMetadata(context_);
 | 
	
		
			
				|  |  |      }
 | 
	
	
		
			
				|  | @@ -224,7 +220,7 @@ class ClientReader final : public ClientReaderInterface<R> {
 | 
	
		
			
				|  |  |    ///   The \a ClientContext associated with this call is updated with
 | 
	
		
			
				|  |  |    ///   possible metadata received from the server.
 | 
	
		
			
				|  |  |    Status Finish() override {
 | 
	
		
			
				|  |  | -    CallOpSet<CallOpClientRecvStatus> ops;
 | 
	
		
			
				|  |  | +    ::grpc::internal::CallOpSet<::grpc::internal::CallOpClientRecvStatus> ops;
 | 
	
		
			
				|  |  |      Status status;
 | 
	
		
			
				|  |  |      ops.ClientRecvStatus(context_, &status);
 | 
	
		
			
				|  |  |      call_.PerformOps(&ops);
 | 
	
	
		
			
				|  | @@ -233,15 +229,41 @@ class ClientReader final : public ClientReaderInterface<R> {
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |   private:
 | 
	
		
			
				|  |  | +  friend class internal::ClientReaderFactory<R>;
 | 
	
		
			
				|  |  |    ClientContext* context_;
 | 
	
		
			
				|  |  |    CompletionQueue cq_;
 | 
	
		
			
				|  |  | -  Call call_;
 | 
	
		
			
				|  |  | +  ::grpc::internal::Call call_;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  /// Block to create a stream and write the initial metadata and \a request
 | 
	
		
			
				|  |  | +  /// out. Note that \a context will be used to fill in custom initial
 | 
	
		
			
				|  |  | +  /// metadata used to send to the server when starting the call.
 | 
	
		
			
				|  |  | +  template <class W>
 | 
	
		
			
				|  |  | +  ClientReader(::grpc::ChannelInterface* channel,
 | 
	
		
			
				|  |  | +               const ::grpc::internal::RpcMethod& method,
 | 
	
		
			
				|  |  | +               ClientContext* context, const W& request)
 | 
	
		
			
				|  |  | +      : context_(context),
 | 
	
		
			
				|  |  | +        cq_(grpc_completion_queue_attributes{
 | 
	
		
			
				|  |  | +            GRPC_CQ_CURRENT_VERSION, GRPC_CQ_PLUCK,
 | 
	
		
			
				|  |  | +            GRPC_CQ_DEFAULT_POLLING}),  // Pluckable cq
 | 
	
		
			
				|  |  | +        call_(channel->CreateCall(method, context, &cq_)) {
 | 
	
		
			
				|  |  | +    ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata,
 | 
	
		
			
				|  |  | +                                ::grpc::internal::CallOpSendMessage,
 | 
	
		
			
				|  |  | +                                ::grpc::internal::CallOpClientSendClose>
 | 
	
		
			
				|  |  | +        ops;
 | 
	
		
			
				|  |  | +    ops.SendInitialMetadata(context->send_initial_metadata_,
 | 
	
		
			
				|  |  | +                            context->initial_metadata_flags());
 | 
	
		
			
				|  |  | +    // TODO(ctiller): don't assert
 | 
	
		
			
				|  |  | +    GPR_CODEGEN_ASSERT(ops.SendMessage(request).ok());
 | 
	
		
			
				|  |  | +    ops.ClientSendClose();
 | 
	
		
			
				|  |  | +    call_.PerformOps(&ops);
 | 
	
		
			
				|  |  | +    cq_.Pluck(&ops);
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  |  };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  /// Client-side interface for streaming writes of message type \a W.
 | 
	
		
			
				|  |  |  template <class W>
 | 
	
		
			
				|  |  | -class ClientWriterInterface : public ClientStreamingInterface,
 | 
	
		
			
				|  |  | -                              public WriterInterface<W> {
 | 
	
		
			
				|  |  | +class ClientWriterInterface : public internal::ClientStreamingInterface,
 | 
	
		
			
				|  |  | +                              public internal::WriterInterface<W> {
 | 
	
		
			
				|  |  |   public:
 | 
	
		
			
				|  |  |    /// Half close writing from the client. (signal that the stream of messages
 | 
	
		
			
				|  |  |    /// coming from the client is complete).
 | 
	
	
		
			
				|  | @@ -252,37 +274,25 @@ class ClientWriterInterface : public ClientStreamingInterface,
 | 
	
		
			
				|  |  |    virtual bool WritesDone() = 0;
 | 
	
		
			
				|  |  |  };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +namespace internal {
 | 
	
		
			
				|  |  | +template <class W>
 | 
	
		
			
				|  |  | +class ClientWriterFactory {
 | 
	
		
			
				|  |  | + public:
 | 
	
		
			
				|  |  | +  template <class R>
 | 
	
		
			
				|  |  | +  static ClientWriter<W>* Create(::grpc::ChannelInterface* channel,
 | 
	
		
			
				|  |  | +                                 const ::grpc::internal::RpcMethod& method,
 | 
	
		
			
				|  |  | +                                 ClientContext* context, R* response) {
 | 
	
		
			
				|  |  | +    return new ClientWriter<W>(channel, method, context, response);
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +}  // namespace internal
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  /// Synchronous (blocking) client-side API for doing client-streaming RPCs,
 | 
	
		
			
				|  |  |  /// where the outgoing message stream coming from the client has messages of
 | 
	
		
			
				|  |  |  /// type \a W.
 | 
	
		
			
				|  |  |  template <class W>
 | 
	
		
			
				|  |  |  class ClientWriter : public ClientWriterInterface<W> {
 | 
	
		
			
				|  |  |   public:
 | 
	
		
			
				|  |  | -  /// Block to create a stream (i.e. send request headers and other initial
 | 
	
		
			
				|  |  | -  /// metadata to the server). Note that \a context will be used to fill
 | 
	
		
			
				|  |  | -  /// in custom initial metadata. \a response will be filled in with the
 | 
	
		
			
				|  |  | -  /// single expected response message from the server upon a successful
 | 
	
		
			
				|  |  | -  /// call to the \a Finish method of this instance.
 | 
	
		
			
				|  |  | -  template <class R>
 | 
	
		
			
				|  |  | -  ClientWriter(ChannelInterface* channel, const RpcMethod& method,
 | 
	
		
			
				|  |  | -               ClientContext* context, R* response)
 | 
	
		
			
				|  |  | -      : context_(context),
 | 
	
		
			
				|  |  | -        cq_(grpc_completion_queue_attributes{
 | 
	
		
			
				|  |  | -            GRPC_CQ_CURRENT_VERSION, GRPC_CQ_PLUCK,
 | 
	
		
			
				|  |  | -            GRPC_CQ_DEFAULT_POLLING}),  // Pluckable cq
 | 
	
		
			
				|  |  | -        call_(channel->CreateCall(method, context, &cq_)) {
 | 
	
		
			
				|  |  | -    finish_ops_.RecvMessage(response);
 | 
	
		
			
				|  |  | -    finish_ops_.AllowNoMessage();
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    if (!context_->initial_metadata_corked_) {
 | 
	
		
			
				|  |  | -      CallOpSet<CallOpSendInitialMetadata> ops;
 | 
	
		
			
				|  |  | -      ops.SendInitialMetadata(context->send_initial_metadata_,
 | 
	
		
			
				|  |  | -                              context->initial_metadata_flags());
 | 
	
		
			
				|  |  | -      call_.PerformOps(&ops);
 | 
	
		
			
				|  |  | -      cq_.Pluck(&ops);
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |    /// See the \a ClientStreamingInterface.WaitForInitialMetadata method for
 | 
	
		
			
				|  |  |    /// semantics.
 | 
	
		
			
				|  |  |    ///
 | 
	
	
		
			
				|  | @@ -292,7 +302,8 @@ class ClientWriter : public ClientWriterInterface<W> {
 | 
	
		
			
				|  |  |    void WaitForInitialMetadata() {
 | 
	
		
			
				|  |  |      GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    CallOpSet<CallOpRecvInitialMetadata> ops;
 | 
	
		
			
				|  |  | +    ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata>
 | 
	
		
			
				|  |  | +        ops;
 | 
	
		
			
				|  |  |      ops.RecvInitialMetadata(context_);
 | 
	
		
			
				|  |  |      call_.PerformOps(&ops);
 | 
	
		
			
				|  |  |      cq_.Pluck(&ops);  // status ignored
 | 
	
	
		
			
				|  | @@ -304,10 +315,11 @@ class ClientWriter : public ClientWriterInterface<W> {
 | 
	
		
			
				|  |  |    /// Side effect:
 | 
	
		
			
				|  |  |    ///   Also sends initial metadata if not already sent (using the
 | 
	
		
			
				|  |  |    ///   \a ClientContext associated with this call).
 | 
	
		
			
				|  |  | -  using WriterInterface<W>::Write;
 | 
	
		
			
				|  |  | +  using ::grpc::internal::WriterInterface<W>::Write;
 | 
	
		
			
				|  |  |    bool Write(const W& msg, WriteOptions options) override {
 | 
	
		
			
				|  |  | -    CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage,
 | 
	
		
			
				|  |  | -              CallOpClientSendClose>
 | 
	
		
			
				|  |  | +    ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata,
 | 
	
		
			
				|  |  | +                                ::grpc::internal::CallOpSendMessage,
 | 
	
		
			
				|  |  | +                                ::grpc::internal::CallOpClientSendClose>
 | 
	
		
			
				|  |  |          ops;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      if (options.is_last_message()) {
 | 
	
	
		
			
				|  | @@ -328,7 +340,7 @@ class ClientWriter : public ClientWriterInterface<W> {
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    bool WritesDone() override {
 | 
	
		
			
				|  |  | -    CallOpSet<CallOpClientSendClose> ops;
 | 
	
		
			
				|  |  | +    ::grpc::internal::CallOpSet<::grpc::internal::CallOpClientSendClose> ops;
 | 
	
		
			
				|  |  |      ops.ClientSendClose();
 | 
	
		
			
				|  |  |      call_.PerformOps(&ops);
 | 
	
		
			
				|  |  |      return cq_.Pluck(&ops);
 | 
	
	
		
			
				|  | @@ -352,21 +364,51 @@ class ClientWriter : public ClientWriterInterface<W> {
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |   private:
 | 
	
		
			
				|  |  | +  friend class internal::ClientWriterFactory<W>;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  /// Block to create a stream (i.e. send request headers and other initial
 | 
	
		
			
				|  |  | +  /// metadata to the server). Note that \a context will be used to fill
 | 
	
		
			
				|  |  | +  /// in custom initial metadata. \a response will be filled in with the
 | 
	
		
			
				|  |  | +  /// single expected response message from the server upon a successful
 | 
	
		
			
				|  |  | +  /// call to the \a Finish method of this instance.
 | 
	
		
			
				|  |  | +  template <class R>
 | 
	
		
			
				|  |  | +  ClientWriter(ChannelInterface* channel,
 | 
	
		
			
				|  |  | +               const ::grpc::internal::RpcMethod& method,
 | 
	
		
			
				|  |  | +               ClientContext* context, R* response)
 | 
	
		
			
				|  |  | +      : context_(context),
 | 
	
		
			
				|  |  | +        cq_(grpc_completion_queue_attributes{
 | 
	
		
			
				|  |  | +            GRPC_CQ_CURRENT_VERSION, GRPC_CQ_PLUCK,
 | 
	
		
			
				|  |  | +            GRPC_CQ_DEFAULT_POLLING}),  // Pluckable cq
 | 
	
		
			
				|  |  | +        call_(channel->CreateCall(method, context, &cq_)) {
 | 
	
		
			
				|  |  | +    finish_ops_.RecvMessage(response);
 | 
	
		
			
				|  |  | +    finish_ops_.AllowNoMessage();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    if (!context_->initial_metadata_corked_) {
 | 
	
		
			
				|  |  | +      ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata>
 | 
	
		
			
				|  |  | +          ops;
 | 
	
		
			
				|  |  | +      ops.SendInitialMetadata(context->send_initial_metadata_,
 | 
	
		
			
				|  |  | +                              context->initial_metadata_flags());
 | 
	
		
			
				|  |  | +      call_.PerformOps(&ops);
 | 
	
		
			
				|  |  | +      cq_.Pluck(&ops);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |    ClientContext* context_;
 | 
	
		
			
				|  |  | -  CallOpSet<CallOpRecvInitialMetadata, CallOpGenericRecvMessage,
 | 
	
		
			
				|  |  | -            CallOpClientRecvStatus>
 | 
	
		
			
				|  |  | +  ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata,
 | 
	
		
			
				|  |  | +                              ::grpc::internal::CallOpGenericRecvMessage,
 | 
	
		
			
				|  |  | +                              ::grpc::internal::CallOpClientRecvStatus>
 | 
	
		
			
				|  |  |        finish_ops_;
 | 
	
		
			
				|  |  |    CompletionQueue cq_;
 | 
	
		
			
				|  |  | -  Call call_;
 | 
	
		
			
				|  |  | +  ::grpc::internal::Call call_;
 | 
	
		
			
				|  |  |  };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  /// Client-side interface for bi-directional streaming with
 | 
	
		
			
				|  |  |  /// client-to-server stream messages of type \a W and
 | 
	
		
			
				|  |  |  /// server-to-client stream messages of type \a R.
 | 
	
		
			
				|  |  |  template <class W, class R>
 | 
	
		
			
				|  |  | -class ClientReaderWriterInterface : public ClientStreamingInterface,
 | 
	
		
			
				|  |  | -                                    public WriterInterface<W>,
 | 
	
		
			
				|  |  | -                                    public ReaderInterface<R> {
 | 
	
		
			
				|  |  | +class ClientReaderWriterInterface : public internal::ClientStreamingInterface,
 | 
	
		
			
				|  |  | +                                    public internal::WriterInterface<W>,
 | 
	
		
			
				|  |  | +                                    public internal::ReaderInterface<R> {
 | 
	
		
			
				|  |  |   public:
 | 
	
		
			
				|  |  |    /// Block to wait for initial metadata from server. The received metadata
 | 
	
		
			
				|  |  |    /// can only be accessed after this call returns. Should only be called before
 | 
	
	
		
			
				|  | @@ -375,7 +417,7 @@ class ClientReaderWriterInterface : public ClientStreamingInterface,
 | 
	
		
			
				|  |  |    virtual void WaitForInitialMetadata() = 0;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    /// Half close writing from the client. (signal that the stream of messages
 | 
	
		
			
				|  |  | -  /// coming from the client is complete).
 | 
	
		
			
				|  |  | +  /// coming from the clinet is complete).
 | 
	
		
			
				|  |  |    /// Blocks until currently-pending writes are completed.
 | 
	
		
			
				|  |  |    /// Thread-safe with respect to \a ReaderInterface::Read
 | 
	
		
			
				|  |  |    ///
 | 
	
	
		
			
				|  | @@ -383,6 +425,18 @@ class ClientReaderWriterInterface : public ClientStreamingInterface,
 | 
	
		
			
				|  |  |    virtual bool WritesDone() = 0;
 | 
	
		
			
				|  |  |  };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +namespace internal {
 | 
	
		
			
				|  |  | +template <class W, class R>
 | 
	
		
			
				|  |  | +class ClientReaderWriterFactory {
 | 
	
		
			
				|  |  | + public:
 | 
	
		
			
				|  |  | +  static ClientReaderWriter<W, R>* Create(
 | 
	
		
			
				|  |  | +      ::grpc::ChannelInterface* channel,
 | 
	
		
			
				|  |  | +      const ::grpc::internal::RpcMethod& method, ClientContext* context) {
 | 
	
		
			
				|  |  | +    return new ClientReaderWriter<W, R>(channel, method, context);
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +}  // namespace internal
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  /// Synchronous (blocking) client-side API for bi-directional streaming RPCs,
 | 
	
		
			
				|  |  |  /// where the outgoing message stream coming from the client has messages of
 | 
	
		
			
				|  |  |  /// type \a W, and the incoming messages stream coming from the server has
 | 
	
	
		
			
				|  | @@ -390,25 +444,6 @@ class ClientReaderWriterInterface : public ClientStreamingInterface,
 | 
	
		
			
				|  |  |  template <class W, class R>
 | 
	
		
			
				|  |  |  class ClientReaderWriter final : public ClientReaderWriterInterface<W, R> {
 | 
	
		
			
				|  |  |   public:
 | 
	
		
			
				|  |  | -  /// Block to create a stream and write the initial metadata and \a request
 | 
	
		
			
				|  |  | -  /// out. Note that \a context will be used to fill in custom initial metadata
 | 
	
		
			
				|  |  | -  /// used to send to the server when starting the call.
 | 
	
		
			
				|  |  | -  ClientReaderWriter(ChannelInterface* channel, const RpcMethod& method,
 | 
	
		
			
				|  |  | -                     ClientContext* context)
 | 
	
		
			
				|  |  | -      : context_(context),
 | 
	
		
			
				|  |  | -        cq_(grpc_completion_queue_attributes{
 | 
	
		
			
				|  |  | -            GRPC_CQ_CURRENT_VERSION, GRPC_CQ_PLUCK,
 | 
	
		
			
				|  |  | -            GRPC_CQ_DEFAULT_POLLING}),  // Pluckable cq
 | 
	
		
			
				|  |  | -        call_(channel->CreateCall(method, context, &cq_)) {
 | 
	
		
			
				|  |  | -    if (!context_->initial_metadata_corked_) {
 | 
	
		
			
				|  |  | -      CallOpSet<CallOpSendInitialMetadata> ops;
 | 
	
		
			
				|  |  | -      ops.SendInitialMetadata(context->send_initial_metadata_,
 | 
	
		
			
				|  |  | -                              context->initial_metadata_flags());
 | 
	
		
			
				|  |  | -      call_.PerformOps(&ops);
 | 
	
		
			
				|  |  | -      cq_.Pluck(&ops);
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |    /// Block waiting to read initial metadata from the server.
 | 
	
		
			
				|  |  |    /// This call is optional, but if it is used, it cannot be used concurrently
 | 
	
		
			
				|  |  |    /// with or after the \a Finish method.
 | 
	
	
		
			
				|  | @@ -418,7 +453,8 @@ class ClientReaderWriter final : public ClientReaderWriterInterface<W, R> {
 | 
	
		
			
				|  |  |    void WaitForInitialMetadata() override {
 | 
	
		
			
				|  |  |      GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    CallOpSet<CallOpRecvInitialMetadata> ops;
 | 
	
		
			
				|  |  | +    ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata>
 | 
	
		
			
				|  |  | +        ops;
 | 
	
		
			
				|  |  |      ops.RecvInitialMetadata(context_);
 | 
	
		
			
				|  |  |      call_.PerformOps(&ops);
 | 
	
		
			
				|  |  |      cq_.Pluck(&ops);  // status ignored
 | 
	
	
		
			
				|  | @@ -434,7 +470,9 @@ class ClientReaderWriter final : public ClientReaderWriterInterface<W, R> {
 | 
	
		
			
				|  |  |    ///   Also receives initial metadata if not already received (updates the \a
 | 
	
		
			
				|  |  |    ///   ClientContext associated with this call in that case).
 | 
	
		
			
				|  |  |    bool Read(R* msg) override {
 | 
	
		
			
				|  |  | -    CallOpSet<CallOpRecvInitialMetadata, CallOpRecvMessage<R>> ops;
 | 
	
		
			
				|  |  | +    ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata,
 | 
	
		
			
				|  |  | +                                ::grpc::internal::CallOpRecvMessage<R>>
 | 
	
		
			
				|  |  | +        ops;
 | 
	
		
			
				|  |  |      if (!context_->initial_metadata_received_) {
 | 
	
		
			
				|  |  |        ops.RecvInitialMetadata(context_);
 | 
	
		
			
				|  |  |      }
 | 
	
	
		
			
				|  | @@ -448,10 +486,11 @@ class ClientReaderWriter final : public ClientReaderWriterInterface<W, R> {
 | 
	
		
			
				|  |  |    /// Side effect:
 | 
	
		
			
				|  |  |    ///   Also sends initial metadata if not already sent (using the
 | 
	
		
			
				|  |  |    ///   \a ClientContext associated with this call to fill in values).
 | 
	
		
			
				|  |  | -  using WriterInterface<W>::Write;
 | 
	
		
			
				|  |  | +  using ::grpc::internal::WriterInterface<W>::Write;
 | 
	
		
			
				|  |  |    bool Write(const W& msg, WriteOptions options) override {
 | 
	
		
			
				|  |  | -    CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage,
 | 
	
		
			
				|  |  | -              CallOpClientSendClose>
 | 
	
		
			
				|  |  | +    ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata,
 | 
	
		
			
				|  |  | +                                ::grpc::internal::CallOpSendMessage,
 | 
	
		
			
				|  |  | +                                ::grpc::internal::CallOpClientSendClose>
 | 
	
		
			
				|  |  |          ops;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      if (options.is_last_message()) {
 | 
	
	
		
			
				|  | @@ -472,7 +511,7 @@ class ClientReaderWriter final : public ClientReaderWriterInterface<W, R> {
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    bool WritesDone() override {
 | 
	
		
			
				|  |  | -    CallOpSet<CallOpClientSendClose> ops;
 | 
	
		
			
				|  |  | +    ::grpc::internal::CallOpSet<::grpc::internal::CallOpClientSendClose> ops;
 | 
	
		
			
				|  |  |      ops.ClientSendClose();
 | 
	
		
			
				|  |  |      call_.PerformOps(&ops);
 | 
	
		
			
				|  |  |      return cq_.Pluck(&ops);
 | 
	
	
		
			
				|  | @@ -484,7 +523,9 @@ class ClientReaderWriter final : public ClientReaderWriterInterface<W, R> {
 | 
	
		
			
				|  |  |    ///   - the \a ClientContext associated with this call is updated with
 | 
	
		
			
				|  |  |    ///     possible trailing metadata sent from the server.
 | 
	
		
			
				|  |  |    Status Finish() override {
 | 
	
		
			
				|  |  | -    CallOpSet<CallOpRecvInitialMetadata, CallOpClientRecvStatus> ops;
 | 
	
		
			
				|  |  | +    ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata,
 | 
	
		
			
				|  |  | +                                ::grpc::internal::CallOpClientRecvStatus>
 | 
	
		
			
				|  |  | +        ops;
 | 
	
		
			
				|  |  |      if (!context_->initial_metadata_received_) {
 | 
	
		
			
				|  |  |        ops.RecvInitialMetadata(context_);
 | 
	
		
			
				|  |  |      }
 | 
	
	
		
			
				|  | @@ -496,15 +537,38 @@ class ClientReaderWriter final : public ClientReaderWriterInterface<W, R> {
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |   private:
 | 
	
		
			
				|  |  | +  friend class internal::ClientReaderWriterFactory<W, R>;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |    ClientContext* context_;
 | 
	
		
			
				|  |  |    CompletionQueue cq_;
 | 
	
		
			
				|  |  | -  Call call_;
 | 
	
		
			
				|  |  | +  ::grpc::internal::Call call_;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  /// Block to create a stream and write the initial metadata and \a request
 | 
	
		
			
				|  |  | +  /// out. Note that \a context will be used to fill in custom initial metadata
 | 
	
		
			
				|  |  | +  /// used to send to the server when starting the call.
 | 
	
		
			
				|  |  | +  ClientReaderWriter(::grpc::ChannelInterface* channel,
 | 
	
		
			
				|  |  | +                     const ::grpc::internal::RpcMethod& method,
 | 
	
		
			
				|  |  | +                     ClientContext* context)
 | 
	
		
			
				|  |  | +      : context_(context),
 | 
	
		
			
				|  |  | +        cq_(grpc_completion_queue_attributes{
 | 
	
		
			
				|  |  | +            GRPC_CQ_CURRENT_VERSION, GRPC_CQ_PLUCK,
 | 
	
		
			
				|  |  | +            GRPC_CQ_DEFAULT_POLLING}),  // Pluckable cq
 | 
	
		
			
				|  |  | +        call_(channel->CreateCall(method, context, &cq_)) {
 | 
	
		
			
				|  |  | +    if (!context_->initial_metadata_corked_) {
 | 
	
		
			
				|  |  | +      ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata>
 | 
	
		
			
				|  |  | +          ops;
 | 
	
		
			
				|  |  | +      ops.SendInitialMetadata(context->send_initial_metadata_,
 | 
	
		
			
				|  |  | +                              context->initial_metadata_flags());
 | 
	
		
			
				|  |  | +      call_.PerformOps(&ops);
 | 
	
		
			
				|  |  | +      cq_.Pluck(&ops);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  |  };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  /// Server-side interface for streaming reads of message of type \a R.
 | 
	
		
			
				|  |  |  template <class R>
 | 
	
		
			
				|  |  | -class ServerReaderInterface : public ServerStreamingInterface,
 | 
	
		
			
				|  |  | -                              public ReaderInterface<R> {};
 | 
	
		
			
				|  |  | +class ServerReaderInterface : public internal::ServerStreamingInterface,
 | 
	
		
			
				|  |  | +                              public internal::ReaderInterface<R> {};
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  /// Synchronous (blocking) server-side API for doing client-streaming RPCs,
 | 
	
		
			
				|  |  |  /// where the incoming message stream coming from the client has messages of
 | 
	
	
		
			
				|  | @@ -512,15 +576,13 @@ class ServerReaderInterface : public ServerStreamingInterface,
 | 
	
		
			
				|  |  |  template <class R>
 | 
	
		
			
				|  |  |  class ServerReader final : public ServerReaderInterface<R> {
 | 
	
		
			
				|  |  |   public:
 | 
	
		
			
				|  |  | -  ServerReader(Call* call, ServerContext* ctx) : call_(call), ctx_(ctx) {}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |    /// See the \a ServerStreamingInterface.SendInitialMetadata method
 | 
	
		
			
				|  |  |    /// for semantics. Note that initial metadata will be affected by the
 | 
	
		
			
				|  |  |    /// \a ServerContext associated with this call.
 | 
	
		
			
				|  |  |    void SendInitialMetadata() override {
 | 
	
		
			
				|  |  |      GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    CallOpSet<CallOpSendInitialMetadata> ops;
 | 
	
		
			
				|  |  | +    internal::CallOpSet<internal::CallOpSendInitialMetadata> ops;
 | 
	
		
			
				|  |  |      ops.SendInitialMetadata(ctx_->initial_metadata_,
 | 
	
		
			
				|  |  |                              ctx_->initial_metadata_flags());
 | 
	
		
			
				|  |  |      if (ctx_->compression_level_set()) {
 | 
	
	
		
			
				|  | @@ -537,21 +599,27 @@ class ServerReader final : public ServerReaderInterface<R> {
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    bool Read(R* msg) override {
 | 
	
		
			
				|  |  | -    CallOpSet<CallOpRecvMessage<R>> ops;
 | 
	
		
			
				|  |  | +    internal::CallOpSet<internal::CallOpRecvMessage<R>> ops;
 | 
	
		
			
				|  |  |      ops.RecvMessage(msg);
 | 
	
		
			
				|  |  |      call_->PerformOps(&ops);
 | 
	
		
			
				|  |  |      return call_->cq()->Pluck(&ops) && ops.got_message;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |   private:
 | 
	
		
			
				|  |  | -  Call* const call_;
 | 
	
		
			
				|  |  | +  internal::Call* const call_;
 | 
	
		
			
				|  |  |    ServerContext* const ctx_;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  template <class ServiceType, class RequestType, class ResponseType>
 | 
	
		
			
				|  |  | +  friend class internal::ClientStreamingHandler;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  ServerReader(internal::Call* call, ServerContext* ctx)
 | 
	
		
			
				|  |  | +      : call_(call), ctx_(ctx) {}
 | 
	
		
			
				|  |  |  };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  /// Server-side interface for streaming writes of message of type \a W.
 | 
	
		
			
				|  |  |  template <class W>
 | 
	
		
			
				|  |  | -class ServerWriterInterface : public ServerStreamingInterface,
 | 
	
		
			
				|  |  | -                              public WriterInterface<W> {};
 | 
	
		
			
				|  |  | +class ServerWriterInterface : public internal::ServerStreamingInterface,
 | 
	
		
			
				|  |  | +                              public internal::WriterInterface<W> {};
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  /// Synchronous (blocking) server-side API for doing for doing a
 | 
	
		
			
				|  |  |  /// server-streaming RPCs, where the outgoing message stream coming from the
 | 
	
	
		
			
				|  | @@ -559,8 +627,6 @@ class ServerWriterInterface : public ServerStreamingInterface,
 | 
	
		
			
				|  |  |  template <class W>
 | 
	
		
			
				|  |  |  class ServerWriter final : public ServerWriterInterface<W> {
 | 
	
		
			
				|  |  |   public:
 | 
	
		
			
				|  |  | -  ServerWriter(Call* call, ServerContext* ctx) : call_(call), ctx_(ctx) {}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |    /// See the \a ServerStreamingInterface.SendInitialMetadata method
 | 
	
		
			
				|  |  |    /// for semantics.
 | 
	
		
			
				|  |  |    /// Note that initial metadata will be affected by the
 | 
	
	
		
			
				|  | @@ -568,7 +634,7 @@ class ServerWriter final : public ServerWriterInterface<W> {
 | 
	
		
			
				|  |  |    void SendInitialMetadata() override {
 | 
	
		
			
				|  |  |      GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    CallOpSet<CallOpSendInitialMetadata> ops;
 | 
	
		
			
				|  |  | +    internal::CallOpSet<internal::CallOpSendInitialMetadata> ops;
 | 
	
		
			
				|  |  |      ops.SendInitialMetadata(ctx_->initial_metadata_,
 | 
	
		
			
				|  |  |                              ctx_->initial_metadata_flags());
 | 
	
		
			
				|  |  |      if (ctx_->compression_level_set()) {
 | 
	
	
		
			
				|  | @@ -584,11 +650,12 @@ class ServerWriter final : public ServerWriterInterface<W> {
 | 
	
		
			
				|  |  |    /// Side effect:
 | 
	
		
			
				|  |  |    ///   Also sends initial metadata if not already sent (using the
 | 
	
		
			
				|  |  |    ///   \a ClientContext associated with this call to fill in values).
 | 
	
		
			
				|  |  | -  using WriterInterface<W>::Write;
 | 
	
		
			
				|  |  | +  using internal::WriterInterface<W>::Write;
 | 
	
		
			
				|  |  |    bool Write(const W& msg, WriteOptions options) override {
 | 
	
		
			
				|  |  |      if (options.is_last_message()) {
 | 
	
		
			
				|  |  |        options.set_buffer_hint();
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      if (!ctx_->pending_ops_.SendMessage(msg, options).ok()) {
 | 
	
		
			
				|  |  |        return false;
 | 
	
		
			
				|  |  |      }
 | 
	
	
		
			
				|  | @@ -613,15 +680,21 @@ class ServerWriter final : public ServerWriterInterface<W> {
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |   private:
 | 
	
		
			
				|  |  | -  Call* const call_;
 | 
	
		
			
				|  |  | +  internal::Call* const call_;
 | 
	
		
			
				|  |  |    ServerContext* const ctx_;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  template <class ServiceType, class RequestType, class ResponseType>
 | 
	
		
			
				|  |  | +  friend class internal::ServerStreamingHandler;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  ServerWriter(internal::Call* call, ServerContext* ctx)
 | 
	
		
			
				|  |  | +      : call_(call), ctx_(ctx) {}
 | 
	
		
			
				|  |  |  };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  /// Server-side interface for bi-directional streaming.
 | 
	
		
			
				|  |  |  template <class W, class R>
 | 
	
		
			
				|  |  | -class ServerReaderWriterInterface : public ServerStreamingInterface,
 | 
	
		
			
				|  |  | -                                    public WriterInterface<W>,
 | 
	
		
			
				|  |  | -                                    public ReaderInterface<R> {};
 | 
	
		
			
				|  |  | +class ServerReaderWriterInterface : public internal::ServerStreamingInterface,
 | 
	
		
			
				|  |  | +                                    public internal::WriterInterface<W>,
 | 
	
		
			
				|  |  | +                                    public internal::ReaderInterface<R> {};
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  /// Actual implementation of bi-directional streaming
 | 
	
		
			
				|  |  |  namespace internal {
 | 
	
	
		
			
				|  | @@ -688,6 +761,7 @@ class ServerReaderWriterBody final {
 | 
	
		
			
				|  |  |    Call* const call_;
 | 
	
		
			
				|  |  |    ServerContext* const ctx_;
 | 
	
		
			
				|  |  |  };
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  }  // namespace internal
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  /// Synchronous (blocking) server-side API for a bidirectional
 | 
	
	
		
			
				|  | @@ -697,8 +771,6 @@ class ServerReaderWriterBody final {
 | 
	
		
			
				|  |  |  template <class W, class R>
 | 
	
		
			
				|  |  |  class ServerReaderWriter final : public ServerReaderWriterInterface<W, R> {
 | 
	
		
			
				|  |  |   public:
 | 
	
		
			
				|  |  | -  ServerReaderWriter(Call* call, ServerContext* ctx) : body_(call, ctx) {}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |    /// See the \a ServerStreamingInterface.SendInitialMetadata method
 | 
	
		
			
				|  |  |    /// for semantics. Note that initial metadata will be affected by the
 | 
	
		
			
				|  |  |    /// \a ServerContext associated with this call.
 | 
	
	
		
			
				|  | @@ -715,13 +787,18 @@ class ServerReaderWriter final : public ServerReaderWriterInterface<W, R> {
 | 
	
		
			
				|  |  |    /// Side effect:
 | 
	
		
			
				|  |  |    ///   Also sends initial metadata if not already sent (using the \a
 | 
	
		
			
				|  |  |    ///   ServerContext associated with this call).
 | 
	
		
			
				|  |  | -  using WriterInterface<W>::Write;
 | 
	
		
			
				|  |  | +  using internal::WriterInterface<W>::Write;
 | 
	
		
			
				|  |  |    bool Write(const W& msg, WriteOptions options) override {
 | 
	
		
			
				|  |  |      return body_.Write(msg, options);
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |   private:
 | 
	
		
			
				|  |  |    internal::ServerReaderWriterBody<W, R> body_;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  friend class internal::TemplatedBidiStreamingHandler<ServerReaderWriter<W, R>,
 | 
	
		
			
				|  |  | +                                                       false>;
 | 
	
		
			
				|  |  | +  ServerReaderWriter(internal::Call* call, ServerContext* ctx)
 | 
	
		
			
				|  |  | +      : body_(call, ctx) {}
 | 
	
		
			
				|  |  |  };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  /// A class to represent a flow-controlled unary call. This is something
 | 
	
	
		
			
				|  | @@ -736,9 +813,6 @@ template <class RequestType, class ResponseType>
 | 
	
		
			
				|  |  |  class ServerUnaryStreamer final
 | 
	
		
			
				|  |  |      : public ServerReaderWriterInterface<ResponseType, RequestType> {
 | 
	
		
			
				|  |  |   public:
 | 
	
		
			
				|  |  | -  ServerUnaryStreamer(Call* call, ServerContext* ctx)
 | 
	
		
			
				|  |  | -      : body_(call, ctx), read_done_(false), write_done_(false) {}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |    /// Block to send initial metadata to client.
 | 
	
		
			
				|  |  |    /// Implicit input parameter:
 | 
	
		
			
				|  |  |    ///    - the \a ServerContext associated with this call will be used for
 | 
	
	
		
			
				|  | @@ -775,7 +849,7 @@ class ServerUnaryStreamer final
 | 
	
		
			
				|  |  |    /// \param options The WriteOptions affecting the write operation.
 | 
	
		
			
				|  |  |    ///
 | 
	
		
			
				|  |  |    /// \return \a true on success, \a false when the stream has been closed.
 | 
	
		
			
				|  |  | -  using WriterInterface<ResponseType>::Write;
 | 
	
		
			
				|  |  | +  using internal::WriterInterface<ResponseType>::Write;
 | 
	
		
			
				|  |  |    bool Write(const ResponseType& response, WriteOptions options) override {
 | 
	
		
			
				|  |  |      if (write_done_ || !read_done_) {
 | 
	
		
			
				|  |  |        return false;
 | 
	
	
		
			
				|  | @@ -788,6 +862,11 @@ class ServerUnaryStreamer final
 | 
	
		
			
				|  |  |    internal::ServerReaderWriterBody<ResponseType, RequestType> body_;
 | 
	
		
			
				|  |  |    bool read_done_;
 | 
	
		
			
				|  |  |    bool write_done_;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  friend class internal::TemplatedBidiStreamingHandler<
 | 
	
		
			
				|  |  | +      ServerUnaryStreamer<RequestType, ResponseType>, true>;
 | 
	
		
			
				|  |  | +  ServerUnaryStreamer(internal::Call* call, ServerContext* ctx)
 | 
	
		
			
				|  |  | +      : body_(call, ctx), read_done_(false), write_done_(false) {}
 | 
	
		
			
				|  |  |  };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  /// A class to represent a flow-controlled server-side streaming call.
 | 
	
	
		
			
				|  | @@ -799,9 +878,6 @@ template <class RequestType, class ResponseType>
 | 
	
		
			
				|  |  |  class ServerSplitStreamer final
 | 
	
		
			
				|  |  |      : public ServerReaderWriterInterface<ResponseType, RequestType> {
 | 
	
		
			
				|  |  |   public:
 | 
	
		
			
				|  |  | -  ServerSplitStreamer(Call* call, ServerContext* ctx)
 | 
	
		
			
				|  |  | -      : body_(call, ctx), read_done_(false) {}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |    /// Block to send initial metadata to client.
 | 
	
		
			
				|  |  |    /// Implicit input parameter:
 | 
	
		
			
				|  |  |    ///    - the \a ServerContext associated with this call will be used for
 | 
	
	
		
			
				|  | @@ -838,7 +914,7 @@ class ServerSplitStreamer final
 | 
	
		
			
				|  |  |    /// \param options The WriteOptions affecting the write operation.
 | 
	
		
			
				|  |  |    ///
 | 
	
		
			
				|  |  |    /// \return \a true on success, \a false when the stream has been closed.
 | 
	
		
			
				|  |  | -  using WriterInterface<ResponseType>::Write;
 | 
	
		
			
				|  |  | +  using internal::WriterInterface<ResponseType>::Write;
 | 
	
		
			
				|  |  |    bool Write(const ResponseType& response, WriteOptions options) override {
 | 
	
		
			
				|  |  |      return read_done_ && body_.Write(response, options);
 | 
	
		
			
				|  |  |    }
 | 
	
	
		
			
				|  | @@ -846,6 +922,11 @@ class ServerSplitStreamer final
 | 
	
		
			
				|  |  |   private:
 | 
	
		
			
				|  |  |    internal::ServerReaderWriterBody<ResponseType, RequestType> body_;
 | 
	
		
			
				|  |  |    bool read_done_;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  friend class internal::TemplatedBidiStreamingHandler<
 | 
	
		
			
				|  |  | +      ServerSplitStreamer<RequestType, ResponseType>, false>;
 | 
	
		
			
				|  |  | +  ServerSplitStreamer(internal::Call* call, ServerContext* ctx)
 | 
	
		
			
				|  |  | +      : body_(call, ctx), read_done_(false) {}
 | 
	
		
			
				|  |  |  };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  }  // namespace grpc
 |