Go to the documentation of this file.
19 #ifndef GRPCPP_SUPPORT_CLIENT_CALLBACK_H
20 #define GRPCPP_SUPPORT_CLIENT_CALLBACK_H
34 #include "absl/log/absl_check.h"
49 template <
class InputMessage,
class OutputMessage,
50 class BaseInputMessage = InputMessage,
51 class BaseOutputMessage = OutputMessage>
55 const InputMessage* request, OutputMessage* result,
57 static_assert(std::is_base_of<BaseInputMessage, InputMessage>::value,
58 "Invalid input message specification");
59 static_assert(std::is_base_of<BaseOutputMessage, OutputMessage>::value,
60 "Invalid output message specification");
62 channel, method, context, request, result, on_completion);
65 template <
class InputMessage,
class OutputMessage>
66 class CallbackUnaryCallImpl {
71 const InputMessage* request, OutputMessage* result,
74 ABSL_CHECK_NE(cq,
nullptr);
89 const size_t alloc_sz =
sizeof(OpSetAndTag);
92 auto* ops =
new (&alloced->opset) FullCallOpSet;
93 auto* tag =
new (&alloced->tag)
102 ops->SendInitialMetadata(&context->send_initial_metadata_,
103 context->initial_metadata_flags());
104 ops->RecvInitialMetadata(context);
105 ops->RecvMessage(result);
106 ops->AllowNoMessage();
107 ops->ClientSendClose();
108 ops->ClientRecvStatus(context, tag->status_ptr());
109 ops->set_core_cq_tag(tag);
141 template <
class Request,
class Response>
143 template <
class Response>
145 template <
class Request>
152 template <
class Request,
class Response>
159 virtual void Read(Response* resp) = 0;
160 virtual void AddHold(
int holds) = 0;
165 reactor->BindStream(
this);
169 template <
class Response>
174 virtual void Read(Response* resp) = 0;
175 virtual void AddHold(
int holds) = 0;
180 reactor->BindReader(
this);
184 template <
class Request>
196 virtual void AddHold(
int holds) = 0;
201 reactor->BindWriter(
this);
230 template <
class Request,
class Response>
231 class ClientBidiReactor :
public internal::ClientReactor {
261 stream_->Write(req, options);
308 ABSL_DCHECK_GT(holds, 0);
309 stream_->AddHold(holds);
367 template <
class Response>
368 class ClientReadReactor :
public internal::ClientReactor {
375 ABSL_DCHECK_GT(holds, 0);
376 reader_->AddHold(holds);
392 template <
class Request>
393 class ClientWriteReactor :
public internal::ClientReactor {
398 writer_->Write(req, options);
407 ABSL_DCHECK_GT(holds, 0);
408 writer_->AddHold(holds);
449 reactor->BindCall(
this);
455 template <
class Request,
class Response>
456 class ClientCallbackReaderWriterFactory;
457 template <
class Response>
458 class ClientCallbackReaderFactory;
459 template <
class Request>
460 class ClientCallbackWriterFactory;
462 template <
class Request,
class Response>
463 class ClientCallbackReaderWriterImpl
467 static void operator delete(
void* , std::size_t size) {
476 static void operator delete(
void*,
void*) { ABSL_CHECK(
false); }
478 void StartCall() ABSL_LOCKS_EXCLUDED(start_mu_)
override {
484 if (!start_corked_) {
485 start_ops_.SendInitialMetadata(&context_->send_initial_metadata_,
486 context_->initial_metadata_flags());
494 if (backlog_.read_ops) {
497 if (backlog_.write_ops) {
500 if (backlog_.writes_done_ops) {
506 started_.store(
true, std::memory_order_release);
511 this->MaybeFinish(
false);
514 void Read(Response* msg)
override {
515 read_ops_.RecvMessage(msg);
516 callbacks_outstanding_.fetch_add(1, std::memory_order_relaxed);
517 if (
GPR_UNLIKELY(!started_.load(std::memory_order_acquire))) {
519 if (
GPR_LIKELY(!started_.load(std::memory_order_relaxed))) {
520 backlog_.read_ops =
true;
528 ABSL_LOCKS_EXCLUDED(start_mu_)
override {
529 if (options.is_last_message()) {
530 options.set_buffer_hint();
531 write_ops_.ClientSendClose();
534 ABSL_CHECK(write_ops_.SendMessagePtr(msg, options).ok());
535 callbacks_outstanding_.fetch_add(1, std::memory_order_relaxed);
537 write_ops_.SendInitialMetadata(&context_->send_initial_metadata_,
538 context_->initial_metadata_flags());
539 corked_write_needed_ =
false;
542 if (
GPR_UNLIKELY(!started_.load(std::memory_order_acquire))) {
544 if (
GPR_LIKELY(!started_.load(std::memory_order_relaxed))) {
545 backlog_.write_ops =
true;
552 writes_done_ops_.ClientSendClose();
553 writes_done_tag_.
Set(
556 reactor_->OnWritesDoneDone(ok);
559 &writes_done_ops_,
false);
561 callbacks_outstanding_.fetch_add(1, std::memory_order_relaxed);
563 writes_done_ops_.SendInitialMetadata(&context_->send_initial_metadata_,
564 context_->initial_metadata_flags());
565 corked_write_needed_ =
false;
567 if (
GPR_UNLIKELY(!started_.load(std::memory_order_acquire))) {
569 if (
GPR_LIKELY(!started_.load(std::memory_order_relaxed))) {
570 backlog_.writes_done_ops =
true;
578 callbacks_outstanding_.fetch_add(holds, std::memory_order_relaxed);
591 start_corked_(context_->initial_metadata_corked_),
592 corked_write_needed_(start_corked_) {
593 this->BindReactor(reactor);
599 reactor_->OnReadInitialMetadataDone(
600 ok && !reactor_->InternalTrailersOnly(call_.call()));
604 start_ops_.RecvInitialMetadata(context_);
610 reactor_->OnWriteDone(ok);
619 reactor_->OnReadDone(ok);
628 [
this](
bool ) { MaybeFinish(true); },
631 finish_ops_.ClientRecvStatus(context_, &finish_status_);
641 void MaybeFinish(
bool from_reaction) {
643 1, std::memory_order_acq_rel) == 1)) {
645 auto* reactor = reactor_;
646 auto* call = call_.
call();
647 this->~ClientCallbackReaderWriterImpl();
653 call, [reactor, s = std::move(s)]() { reactor->OnDone(s); });
661 ClientBidiReactor<Request, Response>*
const reactor_;
667 const bool start_corked_;
668 bool corked_write_needed_;
690 struct StartCallBacklog {
691 bool write_ops =
false;
692 bool writes_done_ops =
false;
693 bool read_ops =
false;
695 StartCallBacklog backlog_ ABSL_GUARDED_BY(start_mu_);
698 std::atomic<intptr_t> callbacks_outstanding_{3};
699 std::atomic_bool started_{
false};
703 template <
class Request,
class Response>
704 class ClientCallbackReaderWriterFactory {
711 channel->CreateCall(method, context, channel->CallbackCQ());
721 template <
class Response>
725 static void operator delete(
void* , std::size_t size) {
734 static void operator delete(
void*,
void*) { ABSL_CHECK(
false); }
745 reactor_->OnReadInitialMetadataDone(
746 ok && !reactor_->InternalTrailersOnly(call_.call()));
750 start_ops_.SendInitialMetadata(&context_->send_initial_metadata_,
751 context_->initial_metadata_flags());
752 start_ops_.RecvInitialMetadata(context_);
760 reactor_->OnReadDone(ok);
768 if (backlog_.read_ops) {
771 started_.store(
true, std::memory_order_release);
776 [
this](
bool ) { MaybeFinish(true); },
777 &finish_ops_,
false);
778 finish_ops_.ClientRecvStatus(context_, &finish_status_);
783 void Read(Response* msg)
override {
784 read_ops_.RecvMessage(msg);
785 callbacks_outstanding_.fetch_add(1, std::memory_order_relaxed);
786 if (
GPR_UNLIKELY(!started_.load(std::memory_order_acquire))) {
788 if (
GPR_LIKELY(!started_.load(std::memory_order_relaxed))) {
789 backlog_.read_ops =
true;
797 callbacks_outstanding_.fetch_add(holds, std::memory_order_relaxed);
804 template <
class Request>
808 : context_(context), call_(call), reactor_(reactor) {
809 this->BindReactor(reactor);
811 ABSL_CHECK(start_ops_.SendMessagePtr(request).ok());
812 start_ops_.ClientSendClose();
816 void MaybeFinish(
bool from_reaction) {
818 1, std::memory_order_acq_rel) == 1)) {
820 auto* reactor = reactor_;
821 auto* call = call_.
call();
822 this->~ClientCallbackReaderImpl();
828 call, [reactor, s = std::move(s)]() { reactor->OnDone(s); });
836 ClientReadReactor<Response>*
const reactor_;
853 struct StartCallBacklog {
854 bool read_ops =
false;
856 StartCallBacklog backlog_ ABSL_GUARDED_BY(start_mu_);
859 std::atomic<intptr_t> callbacks_outstanding_{2};
860 std::atomic_bool started_{
false};
864 template <
class Response>
865 class ClientCallbackReaderFactory {
867 template <
class Request>
873 channel->CreateCall(method, context, channel->CallbackCQ());
882 template <
class Request>
886 static void operator delete(
void* , std::size_t size) {
895 static void operator delete(
void*,
void*) { ABSL_CHECK(
false); }
897 void StartCall() ABSL_LOCKS_EXCLUDED(start_mu_)
override {
903 if (!start_corked_) {
904 start_ops_.SendInitialMetadata(&context_->send_initial_metadata_,
905 context_->initial_metadata_flags());
912 if (backlog_.write_ops) {
915 if (backlog_.writes_done_ops) {
921 started_.store(
true, std::memory_order_release);
926 this->MaybeFinish(
false);
930 ABSL_LOCKS_EXCLUDED(start_mu_)
override {
932 options.set_buffer_hint();
933 write_ops_.ClientSendClose();
936 ABSL_CHECK(write_ops_.SendMessagePtr(msg, options).ok());
937 callbacks_outstanding_.fetch_add(1, std::memory_order_relaxed);
940 write_ops_.SendInitialMetadata(&context_->send_initial_metadata_,
941 context_->initial_metadata_flags());
942 corked_write_needed_ =
false;
945 if (
GPR_UNLIKELY(!started_.load(std::memory_order_acquire))) {
947 if (
GPR_LIKELY(!started_.load(std::memory_order_relaxed))) {
948 backlog_.write_ops =
true;
956 writes_done_ops_.ClientSendClose();
957 writes_done_tag_.
Set(
960 reactor_->OnWritesDoneDone(ok);
963 &writes_done_ops_,
false);
965 callbacks_outstanding_.fetch_add(1, std::memory_order_relaxed);
968 writes_done_ops_.SendInitialMetadata(&context_->send_initial_metadata_,
969 context_->initial_metadata_flags());
970 corked_write_needed_ =
false;
973 if (
GPR_UNLIKELY(!started_.load(std::memory_order_acquire))) {
975 if (
GPR_LIKELY(!started_.load(std::memory_order_relaxed))) {
976 backlog_.writes_done_ops =
true;
984 callbacks_outstanding_.fetch_add(holds, std::memory_order_relaxed);
991 template <
class Response>
998 start_corked_(context_->initial_metadata_corked_),
999 corked_write_needed_(start_corked_) {
1000 this->BindReactor(reactor);
1006 reactor_->OnReadInitialMetadataDone(
1007 ok && !reactor_->InternalTrailersOnly(call_.call()));
1010 &start_ops_,
false);
1011 start_ops_.RecvInitialMetadata(context_);
1017 reactor_->OnWriteDone(ok);
1020 &write_ops_,
false);
1024 finish_ops_.RecvMessage(response);
1025 finish_ops_.AllowNoMessage();
1028 [
this](
bool ) { MaybeFinish(true); },
1031 finish_ops_.ClientRecvStatus(context_, &finish_status_);
1036 void MaybeFinish(
bool from_reaction) {
1038 1, std::memory_order_acq_rel) == 1)) {
1040 auto* reactor = reactor_;
1041 auto* call = call_.
call();
1042 this->~ClientCallbackWriterImpl();
1048 call, [reactor, s = std::move(s)]() { reactor->OnDone(s); });
1056 ClientWriteReactor<Request>*
const reactor_;
1062 const bool start_corked_;
1063 bool corked_write_needed_;
1083 struct StartCallBacklog {
1084 bool write_ops =
false;
1085 bool writes_done_ops =
false;
1087 StartCallBacklog backlog_ ABSL_GUARDED_BY(start_mu_);
1090 std::atomic<intptr_t> callbacks_outstanding_{3};
1091 std::atomic_bool started_{
false};
1095 template <
class Request>
1096 class ClientCallbackWriterFactory {
1098 template <
class Response>
1104 channel->CreateCall(method, context, channel->CallbackCQ());
1116 static void operator delete(
void* , std::size_t size) {
1125 static void operator delete(
void*,
void*) { ABSL_CHECK(
false); }
1135 reactor_->OnReadInitialMetadataDone(
1136 ok && !reactor_->InternalTrailersOnly(call_.call()));
1139 &start_ops_,
false);
1140 start_ops_.SendInitialMetadata(&context_->send_initial_metadata_,
1141 context_->initial_metadata_flags());
1142 start_ops_.RecvInitialMetadata(context_);
1147 call_.
call(), [
this](
bool ) { MaybeFinish(); }, &finish_ops_,
1149 finish_ops_.ClientRecvStatus(context_, &finish_status_);
1157 template <
class Request,
class Response>
1161 : context_(context), call_(call), reactor_(reactor) {
1164 ABSL_CHECK(start_ops_.SendMessagePtr(request).ok());
1165 start_ops_.ClientSendClose();
1166 finish_ops_.RecvMessage(response);
1167 finish_ops_.AllowNoMessage();
1173 void MaybeFinish() {
1175 1, std::memory_order_acq_rel) == 1)) {
1177 auto* reactor = reactor_;
1178 auto* call = call_.
call();
1187 ClientUnaryReactor*
const reactor_;
1203 std::atomic<intptr_t> callbacks_outstanding_{2};
1208 template <
class Request,
class Response,
class BaseRequest = Request,
1209 class BaseResponse = Response>
1215 channel->CreateCall(method, context, channel->CallbackCQ());
1221 static_cast<const BaseRequest*
>(request),
1222 static_cast<BaseResponse*
>(response), reactor);
1229 #endif // GRPCPP_SUPPORT_CLIENT_CALLBACK_H
Definition: client_callback.h:1113
CallbackWithSuccessTag can be reused multiple times, and will be used in this fashion for streaming o...
Definition: callback_common.h:149
virtual void OnReadInitialMetadataDone(bool)
Definition: client_callback.h:381
virtual void OnReadInitialMetadataDone(bool)
Definition: client_callback.h:413
void StartWritesDone()
Definition: client_callback.h:403
virtual ~ClientCallbackWriter()
Definition: client_callback.h:187
void Read(Response *msg) override
Definition: client_callback.h:514
void AddHold(int holds) override
Definition: client_callback.h:983
void StartCall() ABSL_LOCKS_EXCLUDED(start_mu_) override
Definition: client_callback.h:478
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:252
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:306
Definition: client_context.h:69
virtual void OnReadDone(bool)
Definition: client_callback.h:382
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:97
void Write(const Request *msg, grpc::WriteOptions options) ABSL_LOCKS_EXCLUDED(start_mu_) override
Definition: client_callback.h:527
void RemoveHold() override
Definition: client_callback.h:799
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:68
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:435
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:706
void StartWrite(const Request *req, grpc::WriteOptions options)
Definition: client_callback.h:397
void StartCall()
Definition: client_callback.h:395
void OnDone(const grpc::Status &) override
Definition: client_callback.h:412
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:580
void OnDone(const grpc::Status &) override
Definition: client_callback.h:380
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:52
virtual void WritesDone()=0
void RemoveHold() override
Definition: client_callback.h:986
static void Create(grpc::ChannelInterface *channel, const grpc::internal::RpcMethod &method, grpc::ClientContext *context, Response *response, ClientWriteReactor< Request > *reactor)
Definition: client_callback.h:1099
virtual void OnReadInitialMetadataDone(bool)
Notifies the application that a read of initial metadata from the server is done.
Definition: client_callback.h:333
Definition: callback_common.h:72
void BindReactor(ClientBidiReactor< Request, Response > *reactor)
Definition: client_callback.h:164
bool ok() const
Is the status OK?
Definition: status.h:125
void BindReactor(ClientUnaryReactor *reactor)
Definition: client_callback.h:448
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:244
void AddMultipleHolds(int holds)
Definition: client_callback.h:374
void StartCall() ABSL_LOCKS_EXCLUDED(start_mu_) override
Definition: client_callback.h:897
void Write(const Request *msg, grpc::WriteOptions options) ABSL_LOCKS_EXCLUDED(start_mu_) override
Definition: client_callback.h:929
void StartWrite(const Request *req, grpc::WriteOptions options)
Initiate/post a write operation with specified options.
Definition: client_callback.h:260
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:324
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:339
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:370
virtual void OnWriteDone(bool)
Notifies the application that a StartWrite or StartWriteLast operation completed.
Definition: client_callback.h:346
A ClientContext allows the person implementing a service client to:
Definition: client_context.h:194
void StartCall() override
Definition: client_callback.h:736
Definition: channel_interface.h:45
struct grpc_call grpc_call
A Call represents an RPC.
Definition: grpc_types.h:68
Definition: client_context.h:67
virtual void OnReadInitialMetadataDone(bool)
Definition: client_callback.h:439
void BindReactor(ClientWriteReactor< Request > *reactor)
Definition: client_callback.h:200
virtual void RemoveHold()=0
Definition: client_callback.h:153
void StartWritesDone()
Indicate that the RPC will have no more write operations.
Definition: client_callback.h:282
virtual void Read(Response *resp)=0
void StartRead(Response *resp)
Definition: client_callback.h:371
Codegen interface for grpc::Channel.
Definition: channel_interface.h:71
Definition: client_callback.h:115
Definition: client_callback.h:1206
void Read(Response *msg) override
Definition: client_callback.h:783
void StartWriteLast(const Request *req, grpc::WriteOptions options)
Definition: client_callback.h:400
Definition: client_context.h:73
virtual void Write(const Request *req, grpc::WriteOptions options)=0
ClientWriteReactor is the interface for a client-streaming RPC.
Definition: client_callback.h:146
void grpc_call_run_in_event_engine(const grpc_call *call, absl::AnyInvocable< void()> cb)
Definition: client_callback.h:205
void AddMultipleHolds(int holds)
Definition: client_callback.h:307
void RemoveHold()
Definition: client_callback.h:378
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:1210
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:273
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:355
void WritesDone() ABSL_LOCKS_EXCLUDED(start_mu_) override
Definition: client_callback.h:955
virtual ~ClientCallbackReader()
Definition: client_callback.h:172
void Set(grpc_call *call, std::function< void(bool)> f, CompletionQueueTag *ops, bool can_inline)
Definition: callback_common.h:176
void AddHold(int holds) override
Definition: client_callback.h:796
void BindReactor(ClientReadReactor< Response > *reactor)
Definition: client_callback.h:179
Definition: client_callback.h:185
virtual void AddHold(int holds)=0
void RemoveHold()
Definition: client_callback.h:311
virtual ~ClientCallbackReaderWriter()
Definition: client_callback.h:155
virtual void RemoveHold()=0
void Write(const Request *req)
Definition: client_callback.h:189
virtual void StartCall()=0
void AddHold()
Definition: client_callback.h:405
void PerformOps(CallOpSetInterface *ops)
Definition: call.h:66
grpc_call * call() const
Definition: call.h:70
void StartCall()
Definition: client_callback.h:437
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:104
ClientBidiReactor is the interface for a bidirectional streaming RPC.
Definition: client_callback.h:142
Definition: channel_interface.h:47
void WriteLast(const Request *req, grpc::WriteOptions options)
Definition: client_callback.h:191
Definition: client_context.h:71
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:1127
void StartWrite(const Request *req)
Definition: client_callback.h:396
void StartCall()
Activate the RPC and initiate any reads or writes that have been Start'ed before this call.
Definition: client_callback.h:237
virtual void OnWriteDone(bool)
Definition: client_callback.h:414
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:406
Definition: client_callback.h:170
virtual ~ClientCallbackUnary()
Definition: client_callback.h:207
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:577
void RemoveHold()
Definition: client_callback.h:410
ClientReadReactor is the interface for a server-streaming RPC.
Definition: client_callback.h:144
void WritesDone() ABSL_LOCKS_EXCLUDED(start_mu_) override
Definition: client_callback.h:551
void AddHold()
Definition: client_callback.h:373
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:438
static void Create(grpc::ChannelInterface *channel, const grpc::internal::RpcMethod &method, grpc::ClientContext *context, const Request *request, ClientReadReactor< Response > *reactor)
Definition: client_callback.h:868
virtual void OnWritesDoneDone(bool)
Definition: client_callback.h:415