Go to the documentation of this file.
19 #ifndef GRPCPP_SUPPORT_CLIENT_CALLBACK_H
20 #define GRPCPP_SUPPORT_CLIENT_CALLBACK_H
47 template <
class InputMessage,
class OutputMessage,
48 class BaseInputMessage = InputMessage,
49 class BaseOutputMessage = OutputMessage>
53 const InputMessage* request, OutputMessage* result,
55 static_assert(std::is_base_of<BaseInputMessage, InputMessage>::value,
56 "Invalid input message specification");
57 static_assert(std::is_base_of<BaseOutputMessage, OutputMessage>::value,
58 "Invalid output message specification");
60 channel, method, context, request, result, on_completion);
63 template <
class InputMessage,
class OutputMessage>
64 class CallbackUnaryCallImpl {
69 const InputMessage* request, OutputMessage* result,
87 const size_t alloc_sz =
sizeof(OpSetAndTag);
90 auto* ops =
new (&alloced->opset) FullCallOpSet;
91 auto* tag =
new (&alloced->tag)
100 ops->SendInitialMetadata(&context->send_initial_metadata_,
101 context->initial_metadata_flags());
102 ops->RecvInitialMetadata(context);
103 ops->RecvMessage(result);
104 ops->AllowNoMessage();
105 ops->ClientSendClose();
106 ops->ClientRecvStatus(context, tag->status_ptr());
107 ops->set_core_cq_tag(tag);
148 template <
class Request,
class Response>
150 template <
class Response>
152 template <
class Request>
159 template <
class Request,
class Response>
166 virtual void Read(Response* resp) = 0;
167 virtual void AddHold(
int holds) = 0;
172 reactor->BindStream(
this);
176 template <
class Response>
181 virtual void Read(Response* resp) = 0;
182 virtual void AddHold(
int holds) = 0;
187 reactor->BindReader(
this);
191 template <
class Request>
203 virtual void AddHold(
int holds) = 0;
208 reactor->BindWriter(
this);
237 template <
class Request,
class Response>
238 class ClientBidiReactor :
public internal::ClientReactor {
268 stream_->Write(req, options);
316 stream_->AddHold(holds);
371 template <
class Response>
372 class ClientReadReactor :
public internal::ClientReactor {
380 reader_->AddHold(holds);
396 template <
class Request>
397 class ClientWriteReactor :
public internal::ClientReactor {
402 writer_->Write(req, options);
412 writer_->AddHold(holds);
453 reactor->BindCall(
this);
459 template <
class Request,
class Response>
460 class ClientCallbackReaderWriterFactory;
461 template <
class Response>
462 class ClientCallbackReaderFactory;
463 template <
class Request>
464 class ClientCallbackWriterFactory;
466 template <
class Request,
class Response>
467 class ClientCallbackReaderWriterImpl
471 static void operator delete(
void* , std::size_t size) {
480 static void operator delete(
void*,
void*) {
GPR_ASSERT(
false); }
482 void StartCall() ABSL_LOCKS_EXCLUDED(start_mu_)
override {
488 if (!start_corked_) {
489 start_ops_.SendInitialMetadata(&context_->send_initial_metadata_,
490 context_->initial_metadata_flags());
498 if (backlog_.read_ops) {
501 if (backlog_.write_ops) {
504 if (backlog_.writes_done_ops) {
510 started_.store(
true, std::memory_order_release);
515 this->MaybeFinish(
false);
518 void Read(Response* msg)
override {
519 read_ops_.RecvMessage(msg);
520 callbacks_outstanding_.fetch_add(1, std::memory_order_relaxed);
521 if (
GPR_UNLIKELY(!started_.load(std::memory_order_acquire))) {
523 if (
GPR_LIKELY(!started_.load(std::memory_order_relaxed))) {
524 backlog_.read_ops =
true;
532 ABSL_LOCKS_EXCLUDED(start_mu_)
override {
533 if (options.is_last_message()) {
534 options.set_buffer_hint();
535 write_ops_.ClientSendClose();
538 GPR_ASSERT(write_ops_.SendMessagePtr(msg, options).ok());
539 callbacks_outstanding_.fetch_add(1, std::memory_order_relaxed);
541 write_ops_.SendInitialMetadata(&context_->send_initial_metadata_,
542 context_->initial_metadata_flags());
543 corked_write_needed_ =
false;
546 if (
GPR_UNLIKELY(!started_.load(std::memory_order_acquire))) {
548 if (
GPR_LIKELY(!started_.load(std::memory_order_relaxed))) {
549 backlog_.write_ops =
true;
556 writes_done_ops_.ClientSendClose();
557 writes_done_tag_.
Set(
560 reactor_->OnWritesDoneDone(ok);
563 &writes_done_ops_,
false);
565 callbacks_outstanding_.fetch_add(1, std::memory_order_relaxed);
567 writes_done_ops_.SendInitialMetadata(&context_->send_initial_metadata_,
568 context_->initial_metadata_flags());
569 corked_write_needed_ =
false;
571 if (
GPR_UNLIKELY(!started_.load(std::memory_order_acquire))) {
573 if (
GPR_LIKELY(!started_.load(std::memory_order_relaxed))) {
574 backlog_.writes_done_ops =
true;
582 callbacks_outstanding_.fetch_add(holds, std::memory_order_relaxed);
595 start_corked_(context_->initial_metadata_corked_),
596 corked_write_needed_(start_corked_) {
597 this->BindReactor(reactor);
603 reactor_->OnReadInitialMetadataDone(
604 ok && !reactor_->InternalTrailersOnly(call_.call()));
608 start_ops_.RecvInitialMetadata(context_);
614 reactor_->OnWriteDone(ok);
623 reactor_->OnReadDone(ok);
632 [
this](
bool ) { MaybeFinish(true); },
635 finish_ops_.ClientRecvStatus(context_, &finish_status_);
645 void MaybeFinish(
bool from_reaction) {
647 1, std::memory_order_acq_rel) == 1)) {
649 auto* reactor = reactor_;
650 auto* call = call_.
call();
651 this->~ClientCallbackReaderWriterImpl();
656 reactor->InternalScheduleOnDone(std::move(s));
663 ClientBidiReactor<Request, Response>*
const reactor_;
669 const bool start_corked_;
670 bool corked_write_needed_;
692 struct StartCallBacklog {
693 bool write_ops =
false;
694 bool writes_done_ops =
false;
695 bool read_ops =
false;
697 StartCallBacklog backlog_ ABSL_GUARDED_BY(start_mu_);
700 std::atomic<intptr_t> callbacks_outstanding_{3};
701 std::atomic_bool started_{
false};
705 template <
class Request,
class Response>
706 class ClientCallbackReaderWriterFactory {
713 channel->CreateCall(method, context, channel->CallbackCQ());
723 template <
class Response>
727 static void operator delete(
void* , std::size_t size) {
736 static void operator delete(
void*,
void*) {
GPR_ASSERT(
false); }
747 reactor_->OnReadInitialMetadataDone(
748 ok && !reactor_->InternalTrailersOnly(call_.call()));
752 start_ops_.SendInitialMetadata(&context_->send_initial_metadata_,
753 context_->initial_metadata_flags());
754 start_ops_.RecvInitialMetadata(context_);
762 reactor_->OnReadDone(ok);
770 if (backlog_.read_ops) {
773 started_.store(
true, std::memory_order_release);
778 [
this](
bool ) { MaybeFinish(true); },
779 &finish_ops_,
false);
780 finish_ops_.ClientRecvStatus(context_, &finish_status_);
785 void Read(Response* msg)
override {
786 read_ops_.RecvMessage(msg);
787 callbacks_outstanding_.fetch_add(1, std::memory_order_relaxed);
788 if (
GPR_UNLIKELY(!started_.load(std::memory_order_acquire))) {
790 if (
GPR_LIKELY(!started_.load(std::memory_order_relaxed))) {
791 backlog_.read_ops =
true;
799 callbacks_outstanding_.fetch_add(holds, std::memory_order_relaxed);
806 template <
class Request>
810 : context_(context), call_(call), reactor_(reactor) {
811 this->BindReactor(reactor);
813 GPR_ASSERT(start_ops_.SendMessagePtr(request).ok());
814 start_ops_.ClientSendClose();
818 void MaybeFinish(
bool from_reaction) {
820 1, std::memory_order_acq_rel) == 1)) {
822 auto* reactor = reactor_;
823 auto* call = call_.
call();
824 this->~ClientCallbackReaderImpl();
829 reactor->InternalScheduleOnDone(std::move(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*) {
GPR_ASSERT(
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 GPR_ASSERT(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();
1047 reactor->InternalScheduleOnDone(std::move(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) {
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 GPR_ASSERT(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:136
virtual void OnReadInitialMetadataDone(bool)
Definition: client_callback.h:385
virtual void OnReadInitialMetadataDone(bool)
Definition: client_callback.h:417
void StartWritesDone()
Definition: client_callback.h:407
virtual ~ClientCallbackWriter()
Definition: client_callback.h:194
void Read(Response *msg) override
Definition: client_callback.h:518
void AddHold(int holds) override
Definition: client_callback.h:983
void StartCall() ABSL_LOCKS_EXCLUDED(start_mu_) override
Definition: client_callback.h:482
Definition: call_op_set.h:619
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:259
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:526
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:313
Definition: client_context.h:68
virtual void OnReadDone(bool)
Definition: client_callback.h:386
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:96
#define GPR_DEBUG_ASSERT(x)
Definition: log.h:103
void Write(const Request *msg, grpc::WriteOptions options) ABSL_LOCKS_EXCLUDED(start_mu_) override
Definition: client_callback.h:531
void RemoveHold() override
Definition: client_callback.h:801
Definition: call_op_set.h:286
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:66
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:155
ClientUnaryReactor is a reactor-style interface for a unary RPC.
Definition: client_callback.h:439
virtual void InternalScheduleOnDone(grpc::Status s)
InternalScheduleOnDone is not part of the API and is not meant to be overridden.
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:708
void StartWrite(const Request *req, grpc::WriteOptions options)
Definition: client_callback.h:401
void StartCall()
Definition: client_callback.h:399
void OnDone(const grpc::Status &) override
Definition: client_callback.h:416
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:584
void OnDone(const grpc::Status &) override
Definition: client_callback.h:384
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:50
#define GPR_ASSERT(x)
abort() the process if x is zero, having written a line to the log.
Definition: log.h:95
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:1097
virtual void OnReadInitialMetadataDone(bool)
Notifies the application that a read of initial metadata from the server is done.
Definition: client_callback.h:337
Definition: callback_common.h:70
void BindReactor(ClientBidiReactor< Request, Response > *reactor)
Definition: client_callback.h:171
bool ok() const
Is the status OK?
Definition: status.h:126
void BindReactor(ClientUnaryReactor *reactor)
Definition: client_callback.h:452
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:251
void AddMultipleHolds(int holds)
Definition: client_callback.h:378
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:267
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:327
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:343
Did it work? If it didn't, why?
Definition: status.h:35
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:374
virtual void OnWriteDone(bool)
Notifies the application that a StartWrite or StartWriteLast operation completed.
Definition: client_callback.h:350
A ClientContext allows the person implementing a service client to:
Definition: client_context.h:193
void StartCall() override
Definition: client_callback.h:738
Definition: channel_interface.h:45
struct grpc_call grpc_call
A Call represents an RPC.
Definition: grpc_types.h:70
Definition: client_context.h:66
virtual void OnReadInitialMetadataDone(bool)
Definition: client_callback.h:443
void BindReactor(ClientWriteReactor< Request > *reactor)
Definition: client_callback.h:207
virtual void RemoveHold()=0
Definition: client_callback.h:160
void StartWritesDone()
Indicate that the RPC will have no more write operations.
Definition: client_callback.h:289
virtual void Read(Response *resp)=0
void StartRead(Response *resp)
Definition: client_callback.h:375
Codegen interface for grpc::Channel.
Definition: channel_interface.h:71
Definition: client_callback.h:113
Definition: client_callback.h:1204
void Read(Response *msg) override
Definition: client_callback.h:785
void StartWriteLast(const Request *req, grpc::WriteOptions options)
Definition: client_callback.h:404
Definition: client_context.h:72
virtual void Write(const Request *req, grpc::WriteOptions options)=0
ClientWriteReactor is the interface for a client-streaming RPC.
Definition: client_callback.h:153
Definition: client_callback.h:212
void AddMultipleHolds(int holds)
Definition: client_callback.h:314
void RemoveHold()
Definition: client_callback.h:382
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:280
Per-message write options.
Definition: call_op_set.h:78
virtual void RemoveHold()=0
virtual void OnWritesDoneDone(bool)
Notifies the application that a StartWritesDone operation completed.
Definition: client_callback.h:359
void WritesDone() ABSL_LOCKS_EXCLUDED(start_mu_) override
Definition: client_callback.h:955
virtual ~ClientCallbackReader()
Definition: client_callback.h:179
void Set(grpc_call *call, std::function< void(bool)> f, CompletionQueueTag *ops, bool can_inline)
Definition: callback_common.h:163
void AddHold(int holds) override
Definition: client_callback.h:798
void BindReactor(ClientReadReactor< Response > *reactor)
Definition: client_callback.h:186
Definition: client_callback.h:192
virtual void AddHold(int holds)=0
void RemoveHold()
Definition: client_callback.h:318
virtual ~ClientCallbackReaderWriter()
Definition: client_callback.h:162
virtual void RemoveHold()=0
void Write(const Request *req)
Definition: client_callback.h:196
virtual void StartCall()=0
void AddHold()
Definition: client_callback.h:409
void PerformOps(CallOpSetInterface *ops)
Definition: call.h:66
grpc_call * call() const
Definition: call.h:70
void StartCall()
Definition: client_callback.h:441
virtual void StartCall()=0
Definition: call_op_set.h:769
A thin wrapper around grpc_completion_queue (see src/core/lib/surface/completion_queue....
Definition: completion_queue.h:103
ClientBidiReactor is the interface for a bidirectional streaming RPC.
Definition: client_callback.h:149
Definition: channel_interface.h:47
void WriteLast(const Request *req, grpc::WriteOptions options)
Definition: client_callback.h:198
Definition: client_context.h:70
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:400
void StartCall()
Activate the RPC and initiate any reads or writes that have been Start'ed before this call.
Definition: client_callback.h:244
virtual void OnWriteDone(bool)
Definition: client_callback.h:418
Definition: call_op_set.h:424
Descriptor of an RPC method.
Definition: rpc_method.h:29
virtual void AddHold(int holds)=0
void AddMultipleHolds(int holds)
Definition: client_callback.h:410
Definition: client_callback.h:177
virtual ~ClientCallbackUnary()
Definition: client_callback.h:214
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:943
void AddHold(int holds) override
Definition: client_callback.h:581
void RemoveHold()
Definition: client_callback.h:414
ClientReadReactor is the interface for a server-streaming RPC.
Definition: client_callback.h:151
void WritesDone() ABSL_LOCKS_EXCLUDED(start_mu_) override
Definition: client_callback.h:555
void AddHold()
Definition: client_callback.h:377
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:442
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:419