Go to the documentation of this file.
19 #ifndef GRPCPP_SUPPORT_CLIENT_CALLBACK_H
20 #define GRPCPP_SUPPORT_CLIENT_CALLBACK_H
25 #include "absl/log/absl_check.h"
50 template <
class InputMessage,
class OutputMessage,
51 class BaseInputMessage = InputMessage,
52 class BaseOutputMessage = OutputMessage>
56 const InputMessage* request, OutputMessage* result,
58 static_assert(std::is_base_of<BaseInputMessage, InputMessage>::value,
59 "Invalid input message specification");
60 static_assert(std::is_base_of<BaseOutputMessage, OutputMessage>::value,
61 "Invalid output message specification");
63 channel, method, context, request, result, on_completion);
66 template <
class InputMessage,
class OutputMessage>
67 class CallbackUnaryCallImpl {
72 const InputMessage* request, OutputMessage* result,
75 ABSL_CHECK_NE(cq,
nullptr);
90 const size_t alloc_sz =
sizeof(OpSetAndTag);
93 auto* ops =
new (&alloced->opset) FullCallOpSet;
94 auto* tag =
new (&alloced->tag)
103 ops->SendInitialMetadata(&context->send_initial_metadata_,
104 context->initial_metadata_flags());
105 ops->RecvInitialMetadata(context);
106 ops->RecvMessage(result);
107 ops->AllowNoMessage();
108 ops->ClientSendClose();
109 ops->ClientRecvStatus(context, tag->status_ptr());
110 ops->set_core_cq_tag(tag);
142 template <
class Request,
class Response>
144 template <
class Response>
146 template <
class Request>
153 template <
class Request,
class Response>
160 virtual void Read(Response* resp) = 0;
161 virtual void AddHold(
int holds) = 0;
166 reactor->BindStream(
this);
170 template <
class Response>
175 virtual void Read(Response* resp) = 0;
176 virtual void AddHold(
int holds) = 0;
181 reactor->BindReader(
this);
185 template <
class Request>
197 virtual void AddHold(
int holds) = 0;
202 reactor->BindWriter(
this);
231 template <
class Request,
class Response>
232 class ClientBidiReactor :
public internal::ClientReactor {
262 stream_->Write(req, options);
309 ABSL_DCHECK_GT(holds, 0);
310 stream_->AddHold(holds);
365 template <
class Response>
366 class ClientReadReactor :
public internal::ClientReactor {
373 ABSL_DCHECK_GT(holds, 0);
374 reader_->AddHold(holds);
390 template <
class Request>
391 class ClientWriteReactor :
public internal::ClientReactor {
396 writer_->Write(req, options);
405 ABSL_DCHECK_GT(holds, 0);
406 writer_->AddHold(holds);
447 reactor->BindCall(
this);
453 template <
class Request,
class Response>
454 class ClientCallbackReaderWriterFactory;
455 template <
class Response>
456 class ClientCallbackReaderFactory;
457 template <
class Request>
458 class ClientCallbackWriterFactory;
460 template <
class Request,
class Response>
461 class ClientCallbackReaderWriterImpl
465 static void operator delete(
void* , std::size_t size) {
474 static void operator delete(
void*,
void*) { ABSL_CHECK(
false); }
476 void StartCall() ABSL_LOCKS_EXCLUDED(start_mu_)
override {
482 if (!start_corked_) {
483 start_ops_.SendInitialMetadata(&context_->send_initial_metadata_,
484 context_->initial_metadata_flags());
492 if (backlog_.read_ops) {
495 if (backlog_.write_ops) {
498 if (backlog_.writes_done_ops) {
504 started_.store(
true, std::memory_order_release);
509 this->MaybeFinish(
false);
512 void Read(Response* msg)
override {
513 read_ops_.RecvMessage(msg);
514 callbacks_outstanding_.fetch_add(1, std::memory_order_relaxed);
515 if (
GPR_UNLIKELY(!started_.load(std::memory_order_acquire))) {
517 if (
GPR_LIKELY(!started_.load(std::memory_order_relaxed))) {
518 backlog_.read_ops =
true;
526 ABSL_LOCKS_EXCLUDED(start_mu_)
override {
527 if (options.is_last_message()) {
528 options.set_buffer_hint();
529 write_ops_.ClientSendClose();
532 ABSL_CHECK(write_ops_.SendMessagePtr(msg, options).ok());
533 callbacks_outstanding_.fetch_add(1, std::memory_order_relaxed);
535 write_ops_.SendInitialMetadata(&context_->send_initial_metadata_,
536 context_->initial_metadata_flags());
537 corked_write_needed_ =
false;
540 if (
GPR_UNLIKELY(!started_.load(std::memory_order_acquire))) {
542 if (
GPR_LIKELY(!started_.load(std::memory_order_relaxed))) {
543 backlog_.write_ops =
true;
550 writes_done_ops_.ClientSendClose();
551 writes_done_tag_.
Set(
554 reactor_->OnWritesDoneDone(ok);
557 &writes_done_ops_,
false);
559 callbacks_outstanding_.fetch_add(1, std::memory_order_relaxed);
561 writes_done_ops_.SendInitialMetadata(&context_->send_initial_metadata_,
562 context_->initial_metadata_flags());
563 corked_write_needed_ =
false;
565 if (
GPR_UNLIKELY(!started_.load(std::memory_order_acquire))) {
567 if (
GPR_LIKELY(!started_.load(std::memory_order_relaxed))) {
568 backlog_.writes_done_ops =
true;
576 callbacks_outstanding_.fetch_add(holds, std::memory_order_relaxed);
589 start_corked_(context_->initial_metadata_corked_),
590 corked_write_needed_(start_corked_) {
591 this->BindReactor(reactor);
597 reactor_->OnReadInitialMetadataDone(
598 ok && !reactor_->InternalTrailersOnly(call_.call()));
602 start_ops_.RecvInitialMetadata(context_);
608 reactor_->OnWriteDone(ok);
617 reactor_->OnReadDone(ok);
626 [
this](
bool ) { MaybeFinish(true); },
629 finish_ops_.ClientRecvStatus(context_, &finish_status_);
639 void MaybeFinish(
bool from_reaction) {
641 1, std::memory_order_acq_rel) == 1)) {
643 auto* reactor = reactor_;
644 auto* call = call_.
call();
645 this->~ClientCallbackReaderWriterImpl();
651 call, [reactor, s = std::move(s)]() { reactor->OnDone(s); });
659 ClientBidiReactor<Request, Response>*
const reactor_;
665 const bool start_corked_;
666 bool corked_write_needed_;
688 struct StartCallBacklog {
689 bool write_ops =
false;
690 bool writes_done_ops =
false;
691 bool read_ops =
false;
693 StartCallBacklog backlog_ ABSL_GUARDED_BY(start_mu_);
696 std::atomic<intptr_t> callbacks_outstanding_{3};
697 std::atomic_bool started_{
false};
701 template <
class Request,
class Response>
702 class ClientCallbackReaderWriterFactory {
709 channel->CreateCall(method, context, channel->CallbackCQ());
719 template <
class Response>
723 static void operator delete(
void* , std::size_t size) {
732 static void operator delete(
void*,
void*) { ABSL_CHECK(
false); }
743 reactor_->OnReadInitialMetadataDone(
744 ok && !reactor_->InternalTrailersOnly(call_.call()));
748 start_ops_.SendInitialMetadata(&context_->send_initial_metadata_,
749 context_->initial_metadata_flags());
750 start_ops_.RecvInitialMetadata(context_);
758 reactor_->OnReadDone(ok);
766 if (backlog_.read_ops) {
769 started_.store(
true, std::memory_order_release);
774 [
this](
bool ) { MaybeFinish(true); },
775 &finish_ops_,
false);
776 finish_ops_.ClientRecvStatus(context_, &finish_status_);
781 void Read(Response* msg)
override {
782 read_ops_.RecvMessage(msg);
783 callbacks_outstanding_.fetch_add(1, std::memory_order_relaxed);
784 if (
GPR_UNLIKELY(!started_.load(std::memory_order_acquire))) {
786 if (
GPR_LIKELY(!started_.load(std::memory_order_relaxed))) {
787 backlog_.read_ops =
true;
795 callbacks_outstanding_.fetch_add(holds, std::memory_order_relaxed);
802 template <
class Request>
806 : context_(context), call_(call), reactor_(reactor) {
807 this->BindReactor(reactor);
809 ABSL_CHECK(start_ops_.SendMessagePtr(request).ok());
810 start_ops_.ClientSendClose();
814 void MaybeFinish(
bool from_reaction) {
816 1, std::memory_order_acq_rel) == 1)) {
818 auto* reactor = reactor_;
819 auto* call = call_.
call();
820 this->~ClientCallbackReaderImpl();
826 call, [reactor, s = std::move(s)]() { reactor->OnDone(s); });
834 ClientReadReactor<Response>*
const reactor_;
851 struct StartCallBacklog {
852 bool read_ops =
false;
854 StartCallBacklog backlog_ ABSL_GUARDED_BY(start_mu_);
857 std::atomic<intptr_t> callbacks_outstanding_{2};
858 std::atomic_bool started_{
false};
862 template <
class Response>
863 class ClientCallbackReaderFactory {
865 template <
class Request>
871 channel->CreateCall(method, context, channel->CallbackCQ());
880 template <
class Request>
884 static void operator delete(
void* , std::size_t size) {
893 static void operator delete(
void*,
void*) { ABSL_CHECK(
false); }
895 void StartCall() ABSL_LOCKS_EXCLUDED(start_mu_)
override {
901 if (!start_corked_) {
902 start_ops_.SendInitialMetadata(&context_->send_initial_metadata_,
903 context_->initial_metadata_flags());
910 if (backlog_.write_ops) {
913 if (backlog_.writes_done_ops) {
919 started_.store(
true, std::memory_order_release);
924 this->MaybeFinish(
false);
928 ABSL_LOCKS_EXCLUDED(start_mu_)
override {
930 options.set_buffer_hint();
931 write_ops_.ClientSendClose();
934 ABSL_CHECK(write_ops_.SendMessagePtr(msg, options).ok());
935 callbacks_outstanding_.fetch_add(1, std::memory_order_relaxed);
938 write_ops_.SendInitialMetadata(&context_->send_initial_metadata_,
939 context_->initial_metadata_flags());
940 corked_write_needed_ =
false;
943 if (
GPR_UNLIKELY(!started_.load(std::memory_order_acquire))) {
945 if (
GPR_LIKELY(!started_.load(std::memory_order_relaxed))) {
946 backlog_.write_ops =
true;
954 writes_done_ops_.ClientSendClose();
955 writes_done_tag_.
Set(
958 reactor_->OnWritesDoneDone(ok);
961 &writes_done_ops_,
false);
963 callbacks_outstanding_.fetch_add(1, std::memory_order_relaxed);
966 writes_done_ops_.SendInitialMetadata(&context_->send_initial_metadata_,
967 context_->initial_metadata_flags());
968 corked_write_needed_ =
false;
971 if (
GPR_UNLIKELY(!started_.load(std::memory_order_acquire))) {
973 if (
GPR_LIKELY(!started_.load(std::memory_order_relaxed))) {
974 backlog_.writes_done_ops =
true;
982 callbacks_outstanding_.fetch_add(holds, std::memory_order_relaxed);
989 template <
class Response>
996 start_corked_(context_->initial_metadata_corked_),
997 corked_write_needed_(start_corked_) {
998 this->BindReactor(reactor);
1004 reactor_->OnReadInitialMetadataDone(
1005 ok && !reactor_->InternalTrailersOnly(call_.call()));
1008 &start_ops_,
false);
1009 start_ops_.RecvInitialMetadata(context_);
1015 reactor_->OnWriteDone(ok);
1018 &write_ops_,
false);
1022 finish_ops_.RecvMessage(response);
1023 finish_ops_.AllowNoMessage();
1026 [
this](
bool ) { MaybeFinish(true); },
1029 finish_ops_.ClientRecvStatus(context_, &finish_status_);
1034 void MaybeFinish(
bool from_reaction) {
1036 1, std::memory_order_acq_rel) == 1)) {
1038 auto* reactor = reactor_;
1039 auto* call = call_.
call();
1040 this->~ClientCallbackWriterImpl();
1046 call, [reactor, s = std::move(s)]() { reactor->OnDone(s); });
1054 ClientWriteReactor<Request>*
const reactor_;
1060 const bool start_corked_;
1061 bool corked_write_needed_;
1081 struct StartCallBacklog {
1082 bool write_ops =
false;
1083 bool writes_done_ops =
false;
1085 StartCallBacklog backlog_ ABSL_GUARDED_BY(start_mu_);
1088 std::atomic<intptr_t> callbacks_outstanding_{3};
1089 std::atomic_bool started_{
false};
1093 template <
class Request>
1094 class ClientCallbackWriterFactory {
1096 template <
class Response>
1102 channel->CreateCall(method, context, channel->CallbackCQ());
1114 static void operator delete(
void* , std::size_t size) {
1123 static void operator delete(
void*,
void*) { ABSL_CHECK(
false); }
1133 reactor_->OnReadInitialMetadataDone(
1134 ok && !reactor_->InternalTrailersOnly(call_.call()));
1137 &start_ops_,
false);
1138 start_ops_.SendInitialMetadata(&context_->send_initial_metadata_,
1139 context_->initial_metadata_flags());
1140 start_ops_.RecvInitialMetadata(context_);
1145 call_.
call(), [
this](
bool ) { MaybeFinish(); }, &finish_ops_,
1147 finish_ops_.ClientRecvStatus(context_, &finish_status_);
1155 template <
class Request,
class Response>
1159 : context_(context), call_(call), reactor_(reactor) {
1162 ABSL_CHECK(start_ops_.SendMessagePtr(request).ok());
1163 start_ops_.ClientSendClose();
1164 finish_ops_.RecvMessage(response);
1165 finish_ops_.AllowNoMessage();
1171 void MaybeFinish() {
1173 1, std::memory_order_acq_rel) == 1)) {
1175 auto* reactor = reactor_;
1176 auto* call = call_.
call();
1185 ClientUnaryReactor*
const reactor_;
1201 std::atomic<intptr_t> callbacks_outstanding_{2};
1206 template <
class Request,
class Response,
class BaseRequest = Request,
1207 class BaseResponse = Response>
1213 channel->CreateCall(method, context, channel->CallbackCQ());
1219 static_cast<const BaseRequest*
>(request),
1220 static_cast<BaseResponse*
>(response), reactor);
1227 #endif // GRPCPP_SUPPORT_CLIENT_CALLBACK_H
Definition: client_callback.h:1111
CallbackWithSuccessTag can be reused multiple times, and will be used in this fashion for streaming o...
Definition: callback_common.h:138
virtual void OnReadInitialMetadataDone(bool)
Definition: client_callback.h:379
virtual void OnReadInitialMetadataDone(bool)
Definition: client_callback.h:411
void StartWritesDone()
Definition: client_callback.h:401
virtual ~ClientCallbackWriter()
Definition: client_callback.h:188
void Read(Response *msg) override
Definition: client_callback.h:512
void AddHold(int holds) override
Definition: client_callback.h:981
void StartCall() ABSL_LOCKS_EXCLUDED(start_mu_) override
Definition: client_callback.h:476
Definition: call_op_set.h:621
void StartWrite(const Request *req)
Initiate a write operation (or post it for later initiation if StartCall has not yet been invoked).
Definition: client_callback.h:253
GRPCAPI void * grpc_call_arena_alloc(grpc_call *call, size_t size)
Allocate memory in the grpc_call arena: this memory is automatically discarded at call completion.
Definition: call_op_set.h:528
void AddHold()
Holds are needed if (and only if) this stream has operations that take place on it after StartCall bu...
Definition: client_callback.h:307
Definition: client_context.h:70
virtual void OnReadDone(bool)
Definition: client_callback.h:380
An Alarm posts the user-provided tag to its associated completion queue or invokes the user-provided ...
Definition: alarm.h:33
Primary implementation of CallOpSetInterface.
Definition: completion_queue.h:98
void Write(const Request *msg, grpc::WriteOptions options) ABSL_LOCKS_EXCLUDED(start_mu_) override
Definition: client_callback.h:525
void RemoveHold() override
Definition: client_callback.h:797
Definition: call_op_set.h:288
CallbackUnaryCallImpl(grpc::ChannelInterface *channel, const grpc::internal::RpcMethod &method, grpc::ClientContext *context, const InputMessage *request, OutputMessage *result, std::function< void(grpc::Status)> on_completion)
Definition: client_callback.h:69
WriteOptions & set_last_message()
last-message bit: indicates this is the last message in a stream client-side: makes Write the equival...
Definition: call_op_set.h:157
ClientUnaryReactor is a reactor-style interface for a unary RPC.
Definition: client_callback.h:433
virtual void Read(Response *resp)=0
static void Create(grpc::ChannelInterface *channel, const grpc::internal::RpcMethod &method, grpc::ClientContext *context, ClientBidiReactor< Request, Response > *reactor)
Definition: client_callback.h:704
void StartWrite(const Request *req, grpc::WriteOptions options)
Definition: client_callback.h:395
void StartCall()
Definition: client_callback.h:393
void OnDone(const grpc::Status &) override
Definition: client_callback.h:410
virtual void OnDone(const grpc::Status &)=0
Called by the library when all operations associated with this RPC have completed and all Holds have ...
void RemoveHold() override
Definition: client_callback.h:578
void OnDone(const grpc::Status &) override
Definition: client_callback.h:378
Straightforward wrapping of the C call object.
Definition: call.h:36
void CallbackUnaryCall(grpc::ChannelInterface *channel, const grpc::internal::RpcMethod &method, grpc::ClientContext *context, const InputMessage *request, OutputMessage *result, std::function< void(grpc::Status)> on_completion)
Perform a callback-based unary call.
Definition: client_callback.h:53
virtual void WritesDone()=0
void RemoveHold() override
Definition: client_callback.h:984
static void Create(grpc::ChannelInterface *channel, const grpc::internal::RpcMethod &method, grpc::ClientContext *context, Response *response, ClientWriteReactor< Request > *reactor)
Definition: client_callback.h:1097
virtual void OnReadInitialMetadataDone(bool)
Notifies the application that a read of initial metadata from the server is done.
Definition: client_callback.h:331
Definition: callback_common.h:72
void BindReactor(ClientBidiReactor< Request, Response > *reactor)
Definition: client_callback.h:165
bool ok() const
Is the status OK?
Definition: status.h:125
void BindReactor(ClientUnaryReactor *reactor)
Definition: client_callback.h:446
GRPCAPI void grpc_call_ref(grpc_call *call)
Ref a call.
void StartRead(Response *resp)
Initiate a read operation (or post it for later initiation if StartCall has not yet been invoked).
Definition: client_callback.h:245
void AddMultipleHolds(int holds)
Definition: client_callback.h:372
void StartCall() ABSL_LOCKS_EXCLUDED(start_mu_) override
Definition: client_callback.h:895
void Write(const Request *msg, grpc::WriteOptions options) ABSL_LOCKS_EXCLUDED(start_mu_) override
Definition: client_callback.h:927
void StartWrite(const Request *req, grpc::WriteOptions options)
Initiate/post a write operation with specified options.
Definition: client_callback.h:261
void OnDone(const grpc::Status &) override
Notifies the application that all operations associated with this RPC have completed and all Holds ha...
Definition: client_callback.h:321
virtual ~ClientReactor()=default
virtual void StartCall()=0
virtual void AddHold(int holds)=0
virtual void OnReadDone(bool)
Notifies the application that a StartRead operation completed.
Definition: client_callback.h:337
Did it work? If it didn't, why?
Definition: status.h:34
virtual void WritesDone()=0
GRPCAPI void grpc_call_unref(grpc_call *call)
Unref a call.
Definition: channel_interface.h:49
void StartCall()
Definition: client_callback.h:368
virtual void OnWriteDone(bool)
Notifies the application that a StartWrite or StartWriteLast operation completed.
Definition: client_callback.h:344
A ClientContext allows the person implementing a service client to:
Definition: client_context.h:195
void StartCall() override
Definition: client_callback.h:734
Definition: channel_interface.h:45
struct grpc_call grpc_call
A Call represents an RPC.
Definition: grpc_types.h:69
Definition: client_context.h:68
virtual void OnReadInitialMetadataDone(bool)
Definition: client_callback.h:437
void BindReactor(ClientWriteReactor< Request > *reactor)
Definition: client_callback.h:201
virtual void RemoveHold()=0
Definition: client_callback.h:154
void StartWritesDone()
Indicate that the RPC will have no more write operations.
Definition: client_callback.h:283
virtual void Read(Response *resp)=0
void StartRead(Response *resp)
Definition: client_callback.h:369
Codegen interface for grpc::Channel.
Definition: channel_interface.h:71
Definition: client_callback.h:116
Definition: client_callback.h:1204
void Read(Response *msg) override
Definition: client_callback.h:781
void StartWriteLast(const Request *req, grpc::WriteOptions options)
Definition: client_callback.h:398
Definition: client_context.h:74
virtual void Write(const Request *req, grpc::WriteOptions options)=0
ClientWriteReactor is the interface for a client-streaming RPC.
Definition: client_callback.h:147
void grpc_call_run_in_event_engine(const grpc_call *call, absl::AnyInvocable< void()> cb)
Definition: client_callback.h:206
void AddMultipleHolds(int holds)
Definition: client_callback.h:308
void RemoveHold()
Definition: client_callback.h:376
static void Create(grpc::ChannelInterface *channel, const grpc::internal::RpcMethod &method, grpc::ClientContext *context, const Request *request, Response *response, ClientUnaryReactor *reactor)
Definition: client_callback.h:1208
void StartWriteLast(const Request *req, grpc::WriteOptions options)
Initiate/post a write operation with specified options and an indication that this is the last write ...
Definition: client_callback.h:274
Per-message write options.
Definition: call_op_set.h:80
virtual void RemoveHold()=0
virtual void OnWritesDoneDone(bool)
Notifies the application that a StartWritesDone operation completed.
Definition: client_callback.h:353
void WritesDone() ABSL_LOCKS_EXCLUDED(start_mu_) override
Definition: client_callback.h:953
virtual ~ClientCallbackReader()
Definition: client_callback.h:173
void Set(grpc_call *call, std::function< void(bool)> f, CompletionQueueTag *ops, bool can_inline)
Definition: callback_common.h:165
void AddHold(int holds) override
Definition: client_callback.h:794
void BindReactor(ClientReadReactor< Response > *reactor)
Definition: client_callback.h:180
Definition: client_callback.h:186
virtual void AddHold(int holds)=0
void RemoveHold()
Definition: client_callback.h:312
virtual ~ClientCallbackReaderWriter()
Definition: client_callback.h:156
virtual void RemoveHold()=0
void Write(const Request *req)
Definition: client_callback.h:190
virtual void StartCall()=0
void AddHold()
Definition: client_callback.h:403
void PerformOps(CallOpSetInterface *ops)
Definition: call.h:66
grpc_call * call() const
Definition: call.h:70
void StartCall()
Definition: client_callback.h:435
virtual void StartCall()=0
Definition: call_op_set.h:771
A thin wrapper around grpc_completion_queue (see src/core/lib/surface/completion_queue....
Definition: completion_queue.h:105
ClientBidiReactor is the interface for a bidirectional streaming RPC.
Definition: client_callback.h:143
Definition: channel_interface.h:47
void WriteLast(const Request *req, grpc::WriteOptions options)
Definition: client_callback.h:192
Definition: client_context.h:72
virtual bool InternalTrailersOnly(const grpc_call *call) const
InternalTrailersOnly is not part of the API and is not meant to be overridden.
virtual void StartCall()=0
void StartCall() override
Definition: client_callback.h:1125
void StartWrite(const Request *req)
Definition: client_callback.h:394
void StartCall()
Activate the RPC and initiate any reads or writes that have been Start'ed before this call.
Definition: client_callback.h:238
virtual void OnWriteDone(bool)
Definition: client_callback.h:412
Definition: call_op_set.h:426
Descriptor of an RPC method.
Definition: rpc_method.h:29
virtual void AddHold(int holds)=0
void AddMultipleHolds(int holds)
Definition: client_callback.h:404
Definition: client_callback.h:171
virtual ~ClientCallbackUnary()
Definition: client_callback.h:208
void set_core_cq_tag(void *core_cq_tag)
set_core_cq_tag is used to provide a different core CQ tag than "this".
Definition: call_op_set.h:947
void AddHold(int holds) override
Definition: client_callback.h:575
void RemoveHold()
Definition: client_callback.h:408
ClientReadReactor is the interface for a server-streaming RPC.
Definition: client_callback.h:145
void WritesDone() ABSL_LOCKS_EXCLUDED(start_mu_) override
Definition: client_callback.h:549
void AddHold()
Definition: client_callback.h:371
void OnDone(const grpc::Status &) override
Called by the library when all operations associated with this RPC have completed and all Holds have ...
Definition: client_callback.h:436
static void Create(grpc::ChannelInterface *channel, const grpc::internal::RpcMethod &method, grpc::ClientContext *context, const Request *request, ClientReadReactor< Response > *reactor)
Definition: client_callback.h:866
virtual void OnWritesDoneDone(bool)
Definition: client_callback.h:413