GRPC C++  1.70.1
client_callback.h
Go to the documentation of this file.
1 //
2 //
3 // Copyright 2018 gRPC authors.
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17 //
18 
19 #ifndef GRPCPP_SUPPORT_CLIENT_CALLBACK_H
20 #define GRPCPP_SUPPORT_CLIENT_CALLBACK_H
21 
22 #include <grpc/grpc.h>
23 #include <grpc/impl/call.h>
24 #include <grpcpp/impl/call.h>
26 #include <grpcpp/impl/sync.h>
28 #include <grpcpp/support/config.h>
29 #include <grpcpp/support/status.h>
30 
31 #include <atomic>
32 #include <functional>
33 
34 #include "absl/log/absl_check.h"
35 
36 namespace grpc {
37 class Channel;
38 class ClientContext;
39 
40 namespace internal {
41 class RpcMethod;
42 
49 template <class InputMessage, class OutputMessage,
50  class BaseInputMessage = InputMessage,
51  class BaseOutputMessage = OutputMessage>
53  const grpc::internal::RpcMethod& method,
54  grpc::ClientContext* context,
55  const InputMessage* request, OutputMessage* result,
56  std::function<void(grpc::Status)> on_completion) {
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);
63 }
64 
65 template <class InputMessage, class OutputMessage>
66 class CallbackUnaryCallImpl {
67  public:
69  const grpc::internal::RpcMethod& method,
70  grpc::ClientContext* context,
71  const InputMessage* request, OutputMessage* result,
72  std::function<void(grpc::Status)> on_completion) {
73  grpc::CompletionQueue* cq = channel->CallbackCQ();
74  ABSL_CHECK_NE(cq, nullptr);
75  grpc::internal::Call call(channel->CreateCall(method, context, cq));
76 
77  using FullCallOpSet = grpc::internal::CallOpSet<
84 
85  struct OpSetAndTag {
86  FullCallOpSet opset;
88  };
89  const size_t alloc_sz = sizeof(OpSetAndTag);
90  auto* const alloced =
91  static_cast<OpSetAndTag*>(grpc_call_arena_alloc(call.call(), alloc_sz));
92  auto* ops = new (&alloced->opset) FullCallOpSet;
93  auto* tag = new (&alloced->tag)
94  grpc::internal::CallbackWithStatusTag(call.call(), on_completion, ops);
95 
96  // TODO(vjpai): Unify code with sync API as much as possible
97  grpc::Status s = ops->SendMessagePtr(request);
98  if (!s.ok()) {
99  tag->force_run(s);
100  return;
101  }
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);
110  call.PerformOps(ops);
111  }
112 };
113 
114 // Base class for public API classes.
116  public:
117  virtual ~ClientReactor() = default;
118 
126  virtual void OnDone(const grpc::Status& /*s*/) = 0;
127 
135  virtual bool InternalTrailersOnly(const grpc_call* call) const;
136 };
137 
138 } // namespace internal
139 
140 // Forward declarations
141 template <class Request, class Response>
143 template <class Response>
145 template <class Request>
147 class ClientUnaryReactor;
148 
149 // NOTE: The streaming objects are not actually implemented in the public API.
150 // These interfaces are provided for mocking only. Typical applications
151 // will interact exclusively with the reactors that they define.
152 template <class Request, class Response>
154  public:
156  virtual void StartCall() = 0;
157  virtual void Write(const Request* req, grpc::WriteOptions options) = 0;
158  virtual void WritesDone() = 0;
159  virtual void Read(Response* resp) = 0;
160  virtual void AddHold(int holds) = 0;
161  virtual void RemoveHold() = 0;
162 
163  protected:
165  reactor->BindStream(this);
166  }
167 };
168 
169 template <class Response>
171  public:
173  virtual void StartCall() = 0;
174  virtual void Read(Response* resp) = 0;
175  virtual void AddHold(int holds) = 0;
176  virtual void RemoveHold() = 0;
177 
178  protected:
180  reactor->BindReader(this);
181  }
182 };
183 
184 template <class Request>
186  public:
188  virtual void StartCall() = 0;
189  void Write(const Request* req) { Write(req, grpc::WriteOptions()); }
190  virtual void Write(const Request* req, grpc::WriteOptions options) = 0;
191  void WriteLast(const Request* req, grpc::WriteOptions options) {
192  Write(req, options.set_last_message());
193  }
194  virtual void WritesDone() = 0;
195 
196  virtual void AddHold(int holds) = 0;
197  virtual void RemoveHold() = 0;
198 
199  protected:
201  reactor->BindWriter(this);
202  }
203 };
204 
206  public:
207  virtual ~ClientCallbackUnary() {}
208  virtual void StartCall() = 0;
209 
210  protected:
211  void BindReactor(ClientUnaryReactor* reactor);
212 };
213 
214 // The following classes are the reactor interfaces that are to be implemented
215 // by the user. They are passed in to the library as an argument to a call on a
216 // stub (either a codegen-ed call or a generic call). The streaming RPC is
217 // activated by calling StartCall, possibly after initiating StartRead,
218 // StartWrite, or AddHold operations on the streaming object. Note that none of
219 // the classes are pure; all reactions have a default empty reaction so that the
220 // user class only needs to override those reactions that it cares about.
221 // The reactor must be passed to the stub invocation before any of the below
222 // operations can be called and its reactions will be invoked by the library in
223 // response to the completion of various operations. Reactions must not include
224 // blocking operations (such as blocking I/O, starting synchronous RPCs, or
225 // waiting on condition variables). Reactions may be invoked concurrently,
226 // except that OnDone is called after all others (assuming proper API usage).
227 // The reactor may not be deleted until OnDone is called.
228 
230 template <class Request, class Response>
231 class ClientBidiReactor : public internal::ClientReactor {
232  public:
237  void StartCall() { stream_->StartCall(); }
238 
244  void StartRead(Response* resp) { stream_->Read(resp); }
245 
252  void StartWrite(const Request* req) { StartWrite(req, grpc::WriteOptions()); }
253 
260  void StartWrite(const Request* req, grpc::WriteOptions options) {
261  stream_->Write(req, options);
262  }
263 
273  void StartWriteLast(const Request* req, grpc::WriteOptions options) {
274  StartWrite(req, options.set_last_message());
275  }
276 
282  void StartWritesDone() { stream_->WritesDone(); }
283 
306  void AddHold() { AddMultipleHolds(1); }
307  void AddMultipleHolds(int holds) {
308  ABSL_DCHECK_GT(holds, 0);
309  stream_->AddHold(holds);
310  }
311  void RemoveHold() { stream_->RemoveHold(); }
312 
324  void OnDone(const grpc::Status& /*s*/) override {}
325 
333  virtual void OnReadInitialMetadataDone(bool /*ok*/) {}
334 
339  virtual void OnReadDone(bool /*ok*/) {}
340 
346  virtual void OnWriteDone(bool /*ok*/) {}
347 
355  virtual void OnWritesDoneDone(bool /*ok*/) {}
356 
357  private:
358  friend class ClientCallbackReaderWriter<Request, Response>;
359  void BindStream(ClientCallbackReaderWriter<Request, Response>* stream) {
360  stream_ = stream;
361  }
363 };
364 
367 template <class Response>
368 class ClientReadReactor : public internal::ClientReactor {
369  public:
370  void StartCall() { reader_->StartCall(); }
371  void StartRead(Response* resp) { reader_->Read(resp); }
372 
373  void AddHold() { AddMultipleHolds(1); }
374  void AddMultipleHolds(int holds) {
375  ABSL_DCHECK_GT(holds, 0);
376  reader_->AddHold(holds);
377  }
378  void RemoveHold() { reader_->RemoveHold(); }
379 
380  void OnDone(const grpc::Status& /*s*/) override {}
381  virtual void OnReadInitialMetadataDone(bool /*ok*/) {}
382  virtual void OnReadDone(bool /*ok*/) {}
383 
384  private:
385  friend class ClientCallbackReader<Response>;
386  void BindReader(ClientCallbackReader<Response>* reader) { reader_ = reader; }
388 };
389 
392 template <class Request>
393 class ClientWriteReactor : public internal::ClientReactor {
394  public:
395  void StartCall() { writer_->StartCall(); }
396  void StartWrite(const Request* req) { StartWrite(req, grpc::WriteOptions()); }
397  void StartWrite(const Request* req, grpc::WriteOptions options) {
398  writer_->Write(req, options);
399  }
400  void StartWriteLast(const Request* req, grpc::WriteOptions options) {
401  StartWrite(req, options.set_last_message());
402  }
403  void StartWritesDone() { writer_->WritesDone(); }
404 
405  void AddHold() { AddMultipleHolds(1); }
406  void AddMultipleHolds(int holds) {
407  ABSL_DCHECK_GT(holds, 0);
408  writer_->AddHold(holds);
409  }
410  void RemoveHold() { writer_->RemoveHold(); }
411 
412  void OnDone(const grpc::Status& /*s*/) override {}
413  virtual void OnReadInitialMetadataDone(bool /*ok*/) {}
414  virtual void OnWriteDone(bool /*ok*/) {}
415  virtual void OnWritesDoneDone(bool /*ok*/) {}
416 
417  private:
418  friend class ClientCallbackWriter<Request>;
419  void BindWriter(ClientCallbackWriter<Request>* writer) { writer_ = writer; }
420 
422 };
423 
436  public:
437  void StartCall() { call_->StartCall(); }
438  void OnDone(const grpc::Status& /*s*/) override {}
439  virtual void OnReadInitialMetadataDone(bool /*ok*/) {}
440 
441  private:
442  friend class ClientCallbackUnary;
443  void BindCall(ClientCallbackUnary* call) { call_ = call; }
444  ClientCallbackUnary* call_;
445 };
446 
447 // Define function out-of-line from class to avoid forward declaration issue
449  reactor->BindCall(this);
450 }
451 
452 namespace internal {
453 
454 // Forward declare factory classes for friendship
455 template <class Request, class Response>
456 class ClientCallbackReaderWriterFactory;
457 template <class Response>
458 class ClientCallbackReaderFactory;
459 template <class Request>
460 class ClientCallbackWriterFactory;
461 
462 template <class Request, class Response>
463 class ClientCallbackReaderWriterImpl
464  : public ClientCallbackReaderWriter<Request, Response> {
465  public:
466  // always allocated against a call arena, no memory free required
467  static void operator delete(void* /*ptr*/, std::size_t size) {
468  ABSL_CHECK_EQ(size, sizeof(ClientCallbackReaderWriterImpl));
469  }
470 
471  // This operator should never be called as the memory should be freed as part
472  // of the arena destruction. It only exists to provide a matching operator
473  // delete to the operator new so that some compilers will not complain (see
474  // https://github.com/grpc/grpc/issues/11301) Note at the time of adding this
475  // there are no tests catching the compiler warning.
476  static void operator delete(void*, void*) { ABSL_CHECK(false); }
477 
478  void StartCall() ABSL_LOCKS_EXCLUDED(start_mu_) override {
479  // This call initiates two batches, plus any backlog, each with a callback
480  // 1. Send initial metadata (unless corked) + recv initial metadata
481  // 2. Any read backlog
482  // 3. Any write backlog
483  // 4. Recv trailing metadata (unless corked)
484  if (!start_corked_) {
485  start_ops_.SendInitialMetadata(&context_->send_initial_metadata_,
486  context_->initial_metadata_flags());
487  }
488 
489  call_.PerformOps(&start_ops_);
490 
491  {
492  grpc::internal::MutexLock lock(&start_mu_);
493 
494  if (backlog_.read_ops) {
495  call_.PerformOps(&read_ops_);
496  }
497  if (backlog_.write_ops) {
498  call_.PerformOps(&write_ops_);
499  }
500  if (backlog_.writes_done_ops) {
501  call_.PerformOps(&writes_done_ops_);
502  }
503  call_.PerformOps(&finish_ops_);
504  // The last thing in this critical section is to set started_ so that it
505  // can be used lock-free as well.
506  started_.store(true, std::memory_order_release);
507  }
508  // MaybeFinish outside the lock to make sure that destruction of this object
509  // doesn't take place while holding the lock (which would cause the lock to
510  // be released after destruction)
511  this->MaybeFinish(/*from_reaction=*/false);
512  }
513 
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))) {
518  grpc::internal::MutexLock lock(&start_mu_);
519  if (GPR_LIKELY(!started_.load(std::memory_order_relaxed))) {
520  backlog_.read_ops = true;
521  return;
522  }
523  }
524  call_.PerformOps(&read_ops_);
525  }
526 
527  void Write(const Request* msg, grpc::WriteOptions options)
528  ABSL_LOCKS_EXCLUDED(start_mu_) override {
529  if (options.is_last_message()) {
530  options.set_buffer_hint();
531  write_ops_.ClientSendClose();
532  }
533  // TODO(vjpai): don't assert
534  ABSL_CHECK(write_ops_.SendMessagePtr(msg, options).ok());
535  callbacks_outstanding_.fetch_add(1, std::memory_order_relaxed);
536  if (GPR_UNLIKELY(corked_write_needed_)) {
537  write_ops_.SendInitialMetadata(&context_->send_initial_metadata_,
538  context_->initial_metadata_flags());
539  corked_write_needed_ = false;
540  }
541 
542  if (GPR_UNLIKELY(!started_.load(std::memory_order_acquire))) {
543  grpc::internal::MutexLock lock(&start_mu_);
544  if (GPR_LIKELY(!started_.load(std::memory_order_relaxed))) {
545  backlog_.write_ops = true;
546  return;
547  }
548  }
549  call_.PerformOps(&write_ops_);
550  }
551  void WritesDone() ABSL_LOCKS_EXCLUDED(start_mu_) override {
552  writes_done_ops_.ClientSendClose();
553  writes_done_tag_.Set(
554  call_.call(),
555  [this](bool ok) {
556  reactor_->OnWritesDoneDone(ok);
557  MaybeFinish(/*from_reaction=*/true);
558  },
559  &writes_done_ops_, /*can_inline=*/false);
560  writes_done_ops_.set_core_cq_tag(&writes_done_tag_);
561  callbacks_outstanding_.fetch_add(1, std::memory_order_relaxed);
562  if (GPR_UNLIKELY(corked_write_needed_)) {
563  writes_done_ops_.SendInitialMetadata(&context_->send_initial_metadata_,
564  context_->initial_metadata_flags());
565  corked_write_needed_ = false;
566  }
567  if (GPR_UNLIKELY(!started_.load(std::memory_order_acquire))) {
568  grpc::internal::MutexLock lock(&start_mu_);
569  if (GPR_LIKELY(!started_.load(std::memory_order_relaxed))) {
570  backlog_.writes_done_ops = true;
571  return;
572  }
573  }
574  call_.PerformOps(&writes_done_ops_);
575  }
576 
577  void AddHold(int holds) override {
578  callbacks_outstanding_.fetch_add(holds, std::memory_order_relaxed);
579  }
580  void RemoveHold() override { MaybeFinish(/*from_reaction=*/false); }
581 
582  private:
583  friend class ClientCallbackReaderWriterFactory<Request, Response>;
584 
586  grpc::ClientContext* context,
588  : context_(context),
589  call_(call),
590  reactor_(reactor),
591  start_corked_(context_->initial_metadata_corked_),
592  corked_write_needed_(start_corked_) {
593  this->BindReactor(reactor);
594 
595  // Set up the unchanging parts of the start, read, and write tags and ops.
596  start_tag_.Set(
597  call_.call(),
598  [this](bool ok) {
599  reactor_->OnReadInitialMetadataDone(
600  ok && !reactor_->InternalTrailersOnly(call_.call()));
601  MaybeFinish(/*from_reaction=*/true);
602  },
603  &start_ops_, /*can_inline=*/false);
604  start_ops_.RecvInitialMetadata(context_);
605  start_ops_.set_core_cq_tag(&start_tag_);
606 
607  write_tag_.Set(
608  call_.call(),
609  [this](bool ok) {
610  reactor_->OnWriteDone(ok);
611  MaybeFinish(/*from_reaction=*/true);
612  },
613  &write_ops_, /*can_inline=*/false);
614  write_ops_.set_core_cq_tag(&write_tag_);
615 
616  read_tag_.Set(
617  call_.call(),
618  [this](bool ok) {
619  reactor_->OnReadDone(ok);
620  MaybeFinish(/*from_reaction=*/true);
621  },
622  &read_ops_, /*can_inline=*/false);
623  read_ops_.set_core_cq_tag(&read_tag_);
624 
625  // Also set up the Finish tag and op set.
626  finish_tag_.Set(
627  call_.call(),
628  [this](bool /*ok*/) { MaybeFinish(/*from_reaction=*/true); },
629  &finish_ops_,
630  /*can_inline=*/false);
631  finish_ops_.ClientRecvStatus(context_, &finish_status_);
632  finish_ops_.set_core_cq_tag(&finish_tag_);
633  }
634 
635  // MaybeFinish can be called from reactions or from user-initiated operations
636  // like StartCall or RemoveHold. If this is the last operation or hold on this
637  // object, it will invoke the OnDone reaction. If MaybeFinish was called from
638  // a reaction, it can call OnDone directly. If not, it would need to schedule
639  // OnDone onto an executor thread to avoid the possibility of deadlocking with
640  // any locks in the user code that invoked it.
641  void MaybeFinish(bool from_reaction) {
642  if (GPR_UNLIKELY(callbacks_outstanding_.fetch_sub(
643  1, std::memory_order_acq_rel) == 1)) {
644  grpc::Status s = std::move(finish_status_);
645  auto* reactor = reactor_;
646  auto* call = call_.call();
647  this->~ClientCallbackReaderWriterImpl();
648  if (GPR_LIKELY(from_reaction)) {
649  grpc_call_unref(call);
650  reactor->OnDone(s);
651  } else {
653  call, [reactor, s = std::move(s)]() { reactor->OnDone(s); });
654  grpc_call_unref(call);
655  }
656  }
657  }
658 
659  grpc::ClientContext* const context_;
660  grpc::internal::Call call_;
661  ClientBidiReactor<Request, Response>* const reactor_;
662 
665  start_ops_;
667  const bool start_corked_;
668  bool corked_write_needed_; // no lock needed since only accessed in
669  // Write/WritesDone which cannot be concurrent
670 
673  grpc::Status finish_status_;
674 
678  write_ops_;
680 
683  writes_done_ops_;
685 
687  read_ops_;
689 
690  struct StartCallBacklog {
691  bool write_ops = false;
692  bool writes_done_ops = false;
693  bool read_ops = false;
694  };
695  StartCallBacklog backlog_ ABSL_GUARDED_BY(start_mu_);
696 
697  // Minimum of 3 callbacks to pre-register for start ops, StartCall, and finish
698  std::atomic<intptr_t> callbacks_outstanding_{3};
699  std::atomic_bool started_{false};
700  grpc::internal::Mutex start_mu_;
701 };
702 
703 template <class Request, class Response>
704 class ClientCallbackReaderWriterFactory {
705  public:
706  static void Create(grpc::ChannelInterface* channel,
707  const grpc::internal::RpcMethod& method,
708  grpc::ClientContext* context,
710  grpc::internal::Call call =
711  channel->CreateCall(method, context, channel->CallbackCQ());
712 
713  grpc_call_ref(call.call());
717  reactor);
718  }
719 };
720 
721 template <class Response>
722 class ClientCallbackReaderImpl : public ClientCallbackReader<Response> {
723  public:
724  // always allocated against a call arena, no memory free required
725  static void operator delete(void* /*ptr*/, std::size_t size) {
726  ABSL_CHECK_EQ(size, sizeof(ClientCallbackReaderImpl));
727  }
728 
729  // This operator should never be called as the memory should be freed as part
730  // of the arena destruction. It only exists to provide a matching operator
731  // delete to the operator new so that some compilers will not complain (see
732  // https://github.com/grpc/grpc/issues/11301) Note at the time of adding this
733  // there are no tests catching the compiler warning.
734  static void operator delete(void*, void*) { ABSL_CHECK(false); }
735 
736  void StartCall() override {
737  // This call initiates two batches, plus any backlog, each with a callback
738  // 1. Send initial metadata (unless corked) + recv initial metadata
739  // 2. Any backlog
740  // 3. Recv trailing metadata
741 
742  start_tag_.Set(
743  call_.call(),
744  [this](bool ok) {
745  reactor_->OnReadInitialMetadataDone(
746  ok && !reactor_->InternalTrailersOnly(call_.call()));
747  MaybeFinish(/*from_reaction=*/true);
748  },
749  &start_ops_, /*can_inline=*/false);
750  start_ops_.SendInitialMetadata(&context_->send_initial_metadata_,
751  context_->initial_metadata_flags());
752  start_ops_.RecvInitialMetadata(context_);
753  start_ops_.set_core_cq_tag(&start_tag_);
754  call_.PerformOps(&start_ops_);
755 
756  // Also set up the read tag so it doesn't have to be set up each time
757  read_tag_.Set(
758  call_.call(),
759  [this](bool ok) {
760  reactor_->OnReadDone(ok);
761  MaybeFinish(/*from_reaction=*/true);
762  },
763  &read_ops_, /*can_inline=*/false);
764  read_ops_.set_core_cq_tag(&read_tag_);
765 
766  {
767  grpc::internal::MutexLock lock(&start_mu_);
768  if (backlog_.read_ops) {
769  call_.PerformOps(&read_ops_);
770  }
771  started_.store(true, std::memory_order_release);
772  }
773 
774  finish_tag_.Set(
775  call_.call(),
776  [this](bool /*ok*/) { MaybeFinish(/*from_reaction=*/true); },
777  &finish_ops_, /*can_inline=*/false);
778  finish_ops_.ClientRecvStatus(context_, &finish_status_);
779  finish_ops_.set_core_cq_tag(&finish_tag_);
780  call_.PerformOps(&finish_ops_);
781  }
782 
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))) {
787  grpc::internal::MutexLock lock(&start_mu_);
788  if (GPR_LIKELY(!started_.load(std::memory_order_relaxed))) {
789  backlog_.read_ops = true;
790  return;
791  }
792  }
793  call_.PerformOps(&read_ops_);
794  }
795 
796  void AddHold(int holds) override {
797  callbacks_outstanding_.fetch_add(holds, std::memory_order_relaxed);
798  }
799  void RemoveHold() override { MaybeFinish(/*from_reaction=*/false); }
800 
801  private:
802  friend class ClientCallbackReaderFactory<Response>;
803 
804  template <class Request>
806  grpc::ClientContext* context, Request* request,
808  : context_(context), call_(call), reactor_(reactor) {
809  this->BindReactor(reactor);
810  // TODO(vjpai): don't assert
811  ABSL_CHECK(start_ops_.SendMessagePtr(request).ok());
812  start_ops_.ClientSendClose();
813  }
814 
815  // MaybeFinish behaves as in ClientCallbackReaderWriterImpl.
816  void MaybeFinish(bool from_reaction) {
817  if (GPR_UNLIKELY(callbacks_outstanding_.fetch_sub(
818  1, std::memory_order_acq_rel) == 1)) {
819  grpc::Status s = std::move(finish_status_);
820  auto* reactor = reactor_;
821  auto* call = call_.call();
822  this->~ClientCallbackReaderImpl();
823  if (GPR_LIKELY(from_reaction)) {
824  grpc_call_unref(call);
825  reactor->OnDone(s);
826  } else {
828  call, [reactor, s = std::move(s)]() { reactor->OnDone(s); });
829  grpc_call_unref(call);
830  }
831  }
832  }
833 
834  grpc::ClientContext* const context_;
835  grpc::internal::Call call_;
836  ClientReadReactor<Response>* const reactor_;
837 
842  start_ops_;
844 
847  grpc::Status finish_status_;
848 
850  read_ops_;
852 
853  struct StartCallBacklog {
854  bool read_ops = false;
855  };
856  StartCallBacklog backlog_ ABSL_GUARDED_BY(start_mu_);
857 
858  // Minimum of 2 callbacks to pre-register for start and finish
859  std::atomic<intptr_t> callbacks_outstanding_{2};
860  std::atomic_bool started_{false};
861  grpc::internal::Mutex start_mu_;
862 };
863 
864 template <class Response>
865 class ClientCallbackReaderFactory {
866  public:
867  template <class Request>
868  static void Create(grpc::ChannelInterface* channel,
869  const grpc::internal::RpcMethod& method,
870  grpc::ClientContext* context, const Request* request,
871  ClientReadReactor<Response>* reactor) {
872  grpc::internal::Call call =
873  channel->CreateCall(method, context, channel->CallbackCQ());
874 
875  grpc_call_ref(call.call());
876  new (grpc_call_arena_alloc(call.call(),
878  ClientCallbackReaderImpl<Response>(call, context, request, reactor);
879  }
880 };
881 
882 template <class Request>
883 class ClientCallbackWriterImpl : public ClientCallbackWriter<Request> {
884  public:
885  // always allocated against a call arena, no memory free required
886  static void operator delete(void* /*ptr*/, std::size_t size) {
887  ABSL_CHECK_EQ(size, sizeof(ClientCallbackWriterImpl));
888  }
889 
890  // This operator should never be called as the memory should be freed as part
891  // of the arena destruction. It only exists to provide a matching operator
892  // delete to the operator new so that some compilers will not complain (see
893  // https://github.com/grpc/grpc/issues/11301) Note at the time of adding this
894  // there are no tests catching the compiler warning.
895  static void operator delete(void*, void*) { ABSL_CHECK(false); }
896 
897  void StartCall() ABSL_LOCKS_EXCLUDED(start_mu_) override {
898  // This call initiates two batches, plus any backlog, each with a callback
899  // 1. Send initial metadata (unless corked) + recv initial metadata
900  // 2. Any backlog
901  // 3. Recv trailing metadata
902 
903  if (!start_corked_) {
904  start_ops_.SendInitialMetadata(&context_->send_initial_metadata_,
905  context_->initial_metadata_flags());
906  }
907  call_.PerformOps(&start_ops_);
908 
909  {
910  grpc::internal::MutexLock lock(&start_mu_);
911 
912  if (backlog_.write_ops) {
913  call_.PerformOps(&write_ops_);
914  }
915  if (backlog_.writes_done_ops) {
916  call_.PerformOps(&writes_done_ops_);
917  }
918  call_.PerformOps(&finish_ops_);
919  // The last thing in this critical section is to set started_ so that it
920  // can be used lock-free as well.
921  started_.store(true, std::memory_order_release);
922  }
923  // MaybeFinish outside the lock to make sure that destruction of this object
924  // doesn't take place while holding the lock (which would cause the lock to
925  // be released after destruction)
926  this->MaybeFinish(/*from_reaction=*/false);
927  }
928 
929  void Write(const Request* msg, grpc::WriteOptions options)
930  ABSL_LOCKS_EXCLUDED(start_mu_) override {
931  if (GPR_UNLIKELY(options.is_last_message())) {
932  options.set_buffer_hint();
933  write_ops_.ClientSendClose();
934  }
935  // TODO(vjpai): don't assert
936  ABSL_CHECK(write_ops_.SendMessagePtr(msg, options).ok());
937  callbacks_outstanding_.fetch_add(1, std::memory_order_relaxed);
938 
939  if (GPR_UNLIKELY(corked_write_needed_)) {
940  write_ops_.SendInitialMetadata(&context_->send_initial_metadata_,
941  context_->initial_metadata_flags());
942  corked_write_needed_ = false;
943  }
944 
945  if (GPR_UNLIKELY(!started_.load(std::memory_order_acquire))) {
946  grpc::internal::MutexLock lock(&start_mu_);
947  if (GPR_LIKELY(!started_.load(std::memory_order_relaxed))) {
948  backlog_.write_ops = true;
949  return;
950  }
951  }
952  call_.PerformOps(&write_ops_);
953  }
954 
955  void WritesDone() ABSL_LOCKS_EXCLUDED(start_mu_) override {
956  writes_done_ops_.ClientSendClose();
957  writes_done_tag_.Set(
958  call_.call(),
959  [this](bool ok) {
960  reactor_->OnWritesDoneDone(ok);
961  MaybeFinish(/*from_reaction=*/true);
962  },
963  &writes_done_ops_, /*can_inline=*/false);
964  writes_done_ops_.set_core_cq_tag(&writes_done_tag_);
965  callbacks_outstanding_.fetch_add(1, std::memory_order_relaxed);
966 
967  if (GPR_UNLIKELY(corked_write_needed_)) {
968  writes_done_ops_.SendInitialMetadata(&context_->send_initial_metadata_,
969  context_->initial_metadata_flags());
970  corked_write_needed_ = false;
971  }
972 
973  if (GPR_UNLIKELY(!started_.load(std::memory_order_acquire))) {
974  grpc::internal::MutexLock lock(&start_mu_);
975  if (GPR_LIKELY(!started_.load(std::memory_order_relaxed))) {
976  backlog_.writes_done_ops = true;
977  return;
978  }
979  }
980  call_.PerformOps(&writes_done_ops_);
981  }
982 
983  void AddHold(int holds) override {
984  callbacks_outstanding_.fetch_add(holds, std::memory_order_relaxed);
985  }
986  void RemoveHold() override { MaybeFinish(/*from_reaction=*/false); }
987 
988  private:
989  friend class ClientCallbackWriterFactory<Request>;
990 
991  template <class Response>
993  grpc::ClientContext* context, Response* response,
995  : context_(context),
996  call_(call),
997  reactor_(reactor),
998  start_corked_(context_->initial_metadata_corked_),
999  corked_write_needed_(start_corked_) {
1000  this->BindReactor(reactor);
1001 
1002  // Set up the unchanging parts of the start and write tags and ops.
1003  start_tag_.Set(
1004  call_.call(),
1005  [this](bool ok) {
1006  reactor_->OnReadInitialMetadataDone(
1007  ok && !reactor_->InternalTrailersOnly(call_.call()));
1008  MaybeFinish(/*from_reaction=*/true);
1009  },
1010  &start_ops_, /*can_inline=*/false);
1011  start_ops_.RecvInitialMetadata(context_);
1012  start_ops_.set_core_cq_tag(&start_tag_);
1013 
1014  write_tag_.Set(
1015  call_.call(),
1016  [this](bool ok) {
1017  reactor_->OnWriteDone(ok);
1018  MaybeFinish(/*from_reaction=*/true);
1019  },
1020  &write_ops_, /*can_inline=*/false);
1021  write_ops_.set_core_cq_tag(&write_tag_);
1022 
1023  // Also set up the Finish tag and op set.
1024  finish_ops_.RecvMessage(response);
1025  finish_ops_.AllowNoMessage();
1026  finish_tag_.Set(
1027  call_.call(),
1028  [this](bool /*ok*/) { MaybeFinish(/*from_reaction=*/true); },
1029  &finish_ops_,
1030  /*can_inline=*/false);
1031  finish_ops_.ClientRecvStatus(context_, &finish_status_);
1032  finish_ops_.set_core_cq_tag(&finish_tag_);
1033  }
1034 
1035  // MaybeFinish behaves as in ClientCallbackReaderWriterImpl.
1036  void MaybeFinish(bool from_reaction) {
1037  if (GPR_UNLIKELY(callbacks_outstanding_.fetch_sub(
1038  1, std::memory_order_acq_rel) == 1)) {
1039  grpc::Status s = std::move(finish_status_);
1040  auto* reactor = reactor_;
1041  auto* call = call_.call();
1042  this->~ClientCallbackWriterImpl();
1043  if (GPR_LIKELY(from_reaction)) {
1044  grpc_call_unref(call);
1045  reactor->OnDone(s);
1046  } else {
1048  call, [reactor, s = std::move(s)]() { reactor->OnDone(s); });
1049  grpc_call_unref(call);
1050  }
1051  }
1052  }
1053 
1054  grpc::ClientContext* const context_;
1055  grpc::internal::Call call_;
1056  ClientWriteReactor<Request>* const reactor_;
1057 
1060  start_ops_;
1062  const bool start_corked_;
1063  bool corked_write_needed_; // no lock needed since only accessed in
1064  // Write/WritesDone which cannot be concurrent
1065 
1068  finish_ops_;
1070  grpc::Status finish_status_;
1071 
1075  write_ops_;
1077 
1080  writes_done_ops_;
1081  grpc::internal::CallbackWithSuccessTag writes_done_tag_;
1082 
1083  struct StartCallBacklog {
1084  bool write_ops = false;
1085  bool writes_done_ops = false;
1086  };
1087  StartCallBacklog backlog_ ABSL_GUARDED_BY(start_mu_);
1088 
1089  // Minimum of 3 callbacks to pre-register for start ops, StartCall, and finish
1090  std::atomic<intptr_t> callbacks_outstanding_{3};
1091  std::atomic_bool started_{false};
1092  grpc::internal::Mutex start_mu_;
1093 };
1094 
1095 template <class Request>
1096 class ClientCallbackWriterFactory {
1097  public:
1098  template <class Response>
1099  static void Create(grpc::ChannelInterface* channel,
1100  const grpc::internal::RpcMethod& method,
1101  grpc::ClientContext* context, Response* response,
1102  ClientWriteReactor<Request>* reactor) {
1103  grpc::internal::Call call =
1104  channel->CreateCall(method, context, channel->CallbackCQ());
1105 
1106  grpc_call_ref(call.call());
1107  new (grpc_call_arena_alloc(call.call(),
1109  ClientCallbackWriterImpl<Request>(call, context, response, reactor);
1110  }
1111 };
1112 
1114  public:
1115  // always allocated against a call arena, no memory free required
1116  static void operator delete(void* /*ptr*/, std::size_t size) {
1117  ABSL_CHECK_EQ(size, sizeof(ClientCallbackUnaryImpl));
1118  }
1119 
1120  // This operator should never be called as the memory should be freed as part
1121  // of the arena destruction. It only exists to provide a matching operator
1122  // delete to the operator new so that some compilers will not complain (see
1123  // https://github.com/grpc/grpc/issues/11301) Note at the time of adding this
1124  // there are no tests catching the compiler warning.
1125  static void operator delete(void*, void*) { ABSL_CHECK(false); }
1126 
1127  void StartCall() override {
1128  // This call initiates two batches, each with a callback
1129  // 1. Send initial metadata + write + writes done + recv initial metadata
1130  // 2. Read message, recv trailing metadata
1131 
1132  start_tag_.Set(
1133  call_.call(),
1134  [this](bool ok) {
1135  reactor_->OnReadInitialMetadataDone(
1136  ok && !reactor_->InternalTrailersOnly(call_.call()));
1137  MaybeFinish();
1138  },
1139  &start_ops_, /*can_inline=*/false);
1140  start_ops_.SendInitialMetadata(&context_->send_initial_metadata_,
1141  context_->initial_metadata_flags());
1142  start_ops_.RecvInitialMetadata(context_);
1143  start_ops_.set_core_cq_tag(&start_tag_);
1144  call_.PerformOps(&start_ops_);
1145 
1146  finish_tag_.Set(
1147  call_.call(), [this](bool /*ok*/) { MaybeFinish(); }, &finish_ops_,
1148  /*can_inline=*/false);
1149  finish_ops_.ClientRecvStatus(context_, &finish_status_);
1150  finish_ops_.set_core_cq_tag(&finish_tag_);
1151  call_.PerformOps(&finish_ops_);
1152  }
1153 
1154  private:
1156 
1157  template <class Request, class Response>
1159  grpc::ClientContext* context, Request* request,
1160  Response* response, ClientUnaryReactor* reactor)
1161  : context_(context), call_(call), reactor_(reactor) {
1162  this->BindReactor(reactor);
1163  // TODO(vjpai): don't assert
1164  ABSL_CHECK(start_ops_.SendMessagePtr(request).ok());
1165  start_ops_.ClientSendClose();
1166  finish_ops_.RecvMessage(response);
1167  finish_ops_.AllowNoMessage();
1168  }
1169 
1170  // In the unary case, MaybeFinish is only ever invoked from a
1171  // library-initiated reaction, so it will just directly call OnDone if this is
1172  // the last reaction for this RPC.
1173  void MaybeFinish() {
1174  if (GPR_UNLIKELY(callbacks_outstanding_.fetch_sub(
1175  1, std::memory_order_acq_rel) == 1)) {
1176  grpc::Status s = std::move(finish_status_);
1177  auto* reactor = reactor_;
1178  auto* call = call_.call();
1179  this->~ClientCallbackUnaryImpl();
1180  grpc_call_unref(call);
1181  reactor->OnDone(s);
1182  }
1183  }
1184 
1185  grpc::ClientContext* const context_;
1186  grpc::internal::Call call_;
1187  ClientUnaryReactor* const reactor_;
1188 
1193  start_ops_;
1195 
1198  finish_ops_;
1200  grpc::Status finish_status_;
1201 
1202  // This call will have 2 callbacks: start and finish
1203  std::atomic<intptr_t> callbacks_outstanding_{2};
1204 };
1205 
1207  public:
1208  template <class Request, class Response, class BaseRequest = Request,
1209  class BaseResponse = Response>
1210  static void Create(grpc::ChannelInterface* channel,
1211  const grpc::internal::RpcMethod& method,
1212  grpc::ClientContext* context, const Request* request,
1213  Response* response, ClientUnaryReactor* reactor) {
1214  grpc::internal::Call call =
1215  channel->CreateCall(method, context, channel->CallbackCQ());
1216 
1217  grpc_call_ref(call.call());
1218 
1219  new (grpc_call_arena_alloc(call.call(), sizeof(ClientCallbackUnaryImpl)))
1220  ClientCallbackUnaryImpl(call, context,
1221  static_cast<const BaseRequest*>(request),
1222  static_cast<BaseResponse*>(response), reactor);
1223  }
1224 };
1225 
1226 } // namespace internal
1227 } // namespace grpc
1228 
1229 #endif // GRPCPP_SUPPORT_CLIENT_CALLBACK_H
grpc::internal::ClientCallbackUnaryImpl
Definition: client_callback.h:1113
grpc::internal::CallbackWithSuccessTag
CallbackWithSuccessTag can be reused multiple times, and will be used in this fashion for streaming o...
Definition: callback_common.h:149
grpc::ClientReadReactor::OnReadInitialMetadataDone
virtual void OnReadInitialMetadataDone(bool)
Definition: client_callback.h:381
grpc::ClientWriteReactor::OnReadInitialMetadataDone
virtual void OnReadInitialMetadataDone(bool)
Definition: client_callback.h:413
grpc::ClientWriteReactor::StartWritesDone
void StartWritesDone()
Definition: client_callback.h:403
grpc::internal::CallOpRecvInitialMetadata
Definition: call_op_set.h:723
grpc::ClientCallbackWriter::~ClientCallbackWriter
virtual ~ClientCallbackWriter()
Definition: client_callback.h:187
grpc::internal::ClientCallbackReaderWriterImpl::Read
void Read(Response *msg) override
Definition: client_callback.h:514
grpc::internal::ClientCallbackWriterImpl::AddHold
void AddHold(int holds) override
Definition: client_callback.h:983
grpc::internal::ClientCallbackReaderWriterImpl::StartCall
void StartCall() ABSL_LOCKS_EXCLUDED(start_mu_) override
Definition: client_callback.h:478
grpc::internal::CallOpClientSendClose
Definition: call_op_set.h:621
grpc::ClientBidiReactor::StartWrite
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
grpc_call_arena_alloc
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.
grpc::internal::CallOpGenericRecvMessage
Definition: call_op_set.h:528
grpc::ClientBidiReactor::AddHold
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
grpc::internal::ClientCallbackReaderWriterImpl
Definition: client_context.h:69
grpc::ClientReadReactor::OnReadDone
virtual void OnReadDone(bool)
Definition: client_callback.h:382
grpc
An Alarm posts the user-provided tag to its associated completion queue or invokes the user-provided ...
Definition: alarm.h:33
grpc::internal::CallOpSet
Primary implementation of CallOpSetInterface.
Definition: completion_queue.h:97
grpc::internal::ClientCallbackReaderWriterImpl::Write
void Write(const Request *msg, grpc::WriteOptions options) ABSL_LOCKS_EXCLUDED(start_mu_) override
Definition: client_callback.h:527
grpc::internal::ClientCallbackReaderImpl::RemoveHold
void RemoveHold() override
Definition: client_callback.h:799
grpc::internal::CallOpSendMessage
Definition: call_op_set.h:288
grpc::internal::CallbackUnaryCallImpl::CallbackUnaryCallImpl
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
grpc::WriteOptions::set_last_message
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
grpc::ClientUnaryReactor
ClientUnaryReactor is a reactor-style interface for a unary RPC.
Definition: client_callback.h:435
grpc::ClientCallbackReaderWriter::Read
virtual void Read(Response *resp)=0
grpc::internal::ClientCallbackReaderWriterFactory::Create
static void Create(grpc::ChannelInterface *channel, const grpc::internal::RpcMethod &method, grpc::ClientContext *context, ClientBidiReactor< Request, Response > *reactor)
Definition: client_callback.h:706
grpc::ClientWriteReactor::StartWrite
void StartWrite(const Request *req, grpc::WriteOptions options)
Definition: client_callback.h:397
grpc::ClientWriteReactor::StartCall
void StartCall()
Definition: client_callback.h:395
grpc::ClientWriteReactor::OnDone
void OnDone(const grpc::Status &) override
Definition: client_callback.h:412
grpc::internal::ClientReactor::OnDone
virtual void OnDone(const grpc::Status &)=0
Called by the library when all operations associated with this RPC have completed and all Holds have ...
grpc::internal::ClientCallbackReaderWriterImpl::RemoveHold
void RemoveHold() override
Definition: client_callback.h:580
grpc::ClientReadReactor::OnDone
void OnDone(const grpc::Status &) override
Definition: client_callback.h:380
grpc::internal::Call
Straightforward wrapping of the C call object.
Definition: call.h:36
grpc::internal::CallbackUnaryCall
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
grpc::ClientCallbackReaderWriter::WritesDone
virtual void WritesDone()=0
grpc::internal::ClientCallbackWriterImpl::RemoveHold
void RemoveHold() override
Definition: client_callback.h:986
status.h
grpc::internal::CallOpSendInitialMetadata
Definition: call_op_set.h:218
grpc::internal::ClientCallbackWriterFactory::Create
static void Create(grpc::ChannelInterface *channel, const grpc::internal::RpcMethod &method, grpc::ClientContext *context, Response *response, ClientWriteReactor< Request > *reactor)
Definition: client_callback.h:1099
grpc::ClientBidiReactor::OnReadInitialMetadataDone
virtual void OnReadInitialMetadataDone(bool)
Notifies the application that a read of initial metadata from the server is done.
Definition: client_callback.h:333
grpc::internal::CallbackWithStatusTag
Definition: callback_common.h:72
grpc::ClientCallbackReaderWriter::BindReactor
void BindReactor(ClientBidiReactor< Request, Response > *reactor)
Definition: client_callback.h:164
grpc::Status::ok
bool ok() const
Is the status OK?
Definition: status.h:125
grpc::ClientCallbackUnary::BindReactor
void BindReactor(ClientUnaryReactor *reactor)
Definition: client_callback.h:448
grpc_call_ref
GRPCAPI void grpc_call_ref(grpc_call *call)
Ref a call.
grpc::ClientBidiReactor::StartRead
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
grpc::ClientReadReactor::AddMultipleHolds
void AddMultipleHolds(int holds)
Definition: client_callback.h:374
grpc::internal::ClientCallbackWriterImpl::StartCall
void StartCall() ABSL_LOCKS_EXCLUDED(start_mu_) override
Definition: client_callback.h:897
grpc::internal::ClientCallbackWriterImpl::Write
void Write(const Request *msg, grpc::WriteOptions options) ABSL_LOCKS_EXCLUDED(start_mu_) override
Definition: client_callback.h:929
grpc::ClientBidiReactor::StartWrite
void StartWrite(const Request *req, grpc::WriteOptions options)
Initiate/post a write operation with specified options.
Definition: client_callback.h:260
grpc::ClientBidiReactor::OnDone
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
grpc::internal::ClientReactor::~ClientReactor
virtual ~ClientReactor()=default
grpc::ClientCallbackUnary::StartCall
virtual void StartCall()=0
grpc::ClientCallbackReaderWriter::AddHold
virtual void AddHold(int holds)=0
grpc::ClientBidiReactor::OnReadDone
virtual void OnReadDone(bool)
Notifies the application that a StartRead operation completed.
Definition: client_callback.h:339
grpc::Status
Did it work? If it didn't, why?
Definition: status.h:34
GPR_UNLIKELY
#define GPR_UNLIKELY(x)
Definition: port_platform.h:858
grpc::ClientCallbackWriter::WritesDone
virtual void WritesDone()=0
grpc_call_unref
GRPCAPI void grpc_call_unref(grpc_call *call)
Unref a call.
grpc::internal::ClientCallbackWriterFactory
Definition: channel_interface.h:49
grpc::ClientReadReactor::StartCall
void StartCall()
Definition: client_callback.h:370
callback_common.h
grpc::ClientBidiReactor::OnWriteDone
virtual void OnWriteDone(bool)
Notifies the application that a StartWrite or StartWriteLast operation completed.
Definition: client_callback.h:346
grpc::ClientContext
A ClientContext allows the person implementing a service client to:
Definition: client_context.h:194
grpc::internal::ClientCallbackReaderImpl::StartCall
void StartCall() override
Definition: client_callback.h:736
grpc::internal::ClientCallbackReaderWriterFactory
Definition: channel_interface.h:45
grpc.h
grpc_call
struct grpc_call grpc_call
A Call represents an RPC.
Definition: grpc_types.h:68
grpc::internal::CallbackUnaryCallImpl
Definition: client_context.h:67
grpc::ClientUnaryReactor::OnReadInitialMetadataDone
virtual void OnReadInitialMetadataDone(bool)
Definition: client_callback.h:439
grpc::ClientCallbackWriter::BindReactor
void BindReactor(ClientWriteReactor< Request > *reactor)
Definition: client_callback.h:200
grpc::ClientCallbackReader::RemoveHold
virtual void RemoveHold()=0
grpc::ClientCallbackReaderWriter
Definition: client_callback.h:153
grpc::ClientBidiReactor::StartWritesDone
void StartWritesDone()
Indicate that the RPC will have no more write operations.
Definition: client_callback.h:282
grpc::ClientCallbackReader::Read
virtual void Read(Response *resp)=0
grpc::ClientReadReactor::StartRead
void StartRead(Response *resp)
Definition: client_callback.h:371
grpc::ChannelInterface
Codegen interface for grpc::Channel.
Definition: channel_interface.h:71
grpc::internal::ClientReactor
Definition: client_callback.h:115
grpc::internal::ClientCallbackUnaryFactory
Definition: client_callback.h:1206
grpc::internal::ClientCallbackReaderImpl::Read
void Read(Response *msg) override
Definition: client_callback.h:783
grpc::ClientWriteReactor::StartWriteLast
void StartWriteLast(const Request *req, grpc::WriteOptions options)
Definition: client_callback.h:400
grpc::internal::ClientCallbackWriterImpl
Definition: client_context.h:73
grpc::ClientCallbackReaderWriter::Write
virtual void Write(const Request *req, grpc::WriteOptions options)=0
grpc::ClientWriteReactor
ClientWriteReactor is the interface for a client-streaming RPC.
Definition: client_callback.h:146
grpc_call_run_in_event_engine
void grpc_call_run_in_event_engine(const grpc_call *call, absl::AnyInvocable< void()> cb)
grpc::ClientCallbackUnary
Definition: client_callback.h:205
grpc::ClientBidiReactor::AddMultipleHolds
void AddMultipleHolds(int holds)
Definition: client_callback.h:307
grpc::ClientReadReactor::RemoveHold
void RemoveHold()
Definition: client_callback.h:378
grpc::internal::ClientCallbackUnaryFactory::Create
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
grpc::ClientBidiReactor::StartWriteLast
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
grpc::WriteOptions
Per-message write options.
Definition: call_op_set.h:80
grpc::ClientCallbackWriter::RemoveHold
virtual void RemoveHold()=0
grpc::ClientBidiReactor::OnWritesDoneDone
virtual void OnWritesDoneDone(bool)
Notifies the application that a StartWritesDone operation completed.
Definition: client_callback.h:355
grpc::internal::ClientCallbackWriterImpl::WritesDone
void WritesDone() ABSL_LOCKS_EXCLUDED(start_mu_) override
Definition: client_callback.h:955
grpc::ClientCallbackReader::~ClientCallbackReader
virtual ~ClientCallbackReader()
Definition: client_callback.h:172
grpc::internal::CallbackWithSuccessTag::Set
void Set(grpc_call *call, std::function< void(bool)> f, CompletionQueueTag *ops, bool can_inline)
Definition: callback_common.h:176
grpc::internal::ClientCallbackReaderImpl::AddHold
void AddHold(int holds) override
Definition: client_callback.h:796
grpc::ClientCallbackReader::BindReactor
void BindReactor(ClientReadReactor< Response > *reactor)
Definition: client_callback.h:179
grpc::internal::MutexLock
Definition: sync.h:80
grpc::ClientCallbackWriter
Definition: client_callback.h:185
grpc::ClientCallbackWriter::AddHold
virtual void AddHold(int holds)=0
grpc::ClientBidiReactor::RemoveHold
void RemoveHold()
Definition: client_callback.h:311
grpc::ClientCallbackReaderWriter::~ClientCallbackReaderWriter
virtual ~ClientCallbackReaderWriter()
Definition: client_callback.h:155
grpc::ClientCallbackReaderWriter::RemoveHold
virtual void RemoveHold()=0
grpc::ClientCallbackWriter::Write
void Write(const Request *req)
Definition: client_callback.h:189
config.h
grpc::ClientCallbackReader::StartCall
virtual void StartCall()=0
call.h
grpc::ClientWriteReactor::AddHold
void AddHold()
Definition: client_callback.h:405
grpc::internal::Call::PerformOps
void PerformOps(CallOpSetInterface *ops)
Definition: call.h:66
grpc::internal::Call::call
grpc_call * call() const
Definition: call.h:70
grpc::ClientUnaryReactor::StartCall
void StartCall()
Definition: client_callback.h:437
grpc::ClientCallbackReaderWriter::StartCall
virtual void StartCall()=0
call_op_set.h
call.h
grpc::internal::CallOpClientRecvStatus
Definition: call_op_set.h:771
grpc::CompletionQueue
A thin wrapper around grpc_completion_queue (see src/core/lib/surface/completion_queue....
Definition: completion_queue.h:104
grpc::ClientBidiReactor
ClientBidiReactor is the interface for a bidirectional streaming RPC.
Definition: client_callback.h:142
grpc::internal::ClientCallbackReaderFactory
Definition: channel_interface.h:47
grpc::ClientCallbackWriter::WriteLast
void WriteLast(const Request *req, grpc::WriteOptions options)
Definition: client_callback.h:191
grpc::internal::ClientCallbackReaderImpl
Definition: client_context.h:71
grpc::internal::ClientReactor::InternalTrailersOnly
virtual bool InternalTrailersOnly(const grpc_call *call) const
InternalTrailersOnly is not part of the API and is not meant to be overridden.
grpc::ClientCallbackWriter::StartCall
virtual void StartCall()=0
grpc::internal::ClientCallbackUnaryImpl::StartCall
void StartCall() override
Definition: client_callback.h:1127
grpc::ClientWriteReactor::StartWrite
void StartWrite(const Request *req)
Definition: client_callback.h:396
grpc::ClientBidiReactor::StartCall
void StartCall()
Activate the RPC and initiate any reads or writes that have been Start'ed before this call.
Definition: client_callback.h:237
grpc::ClientWriteReactor::OnWriteDone
virtual void OnWriteDone(bool)
Definition: client_callback.h:414
grpc::internal::CallOpRecvMessage
Definition: call_op_set.h:426
grpc::internal::Mutex
Definition: sync.h:57
grpc::internal::RpcMethod
Descriptor of an RPC method.
Definition: rpc_method.h:29
grpc::ClientCallbackReader::AddHold
virtual void AddHold(int holds)=0
grpc::ClientWriteReactor::AddMultipleHolds
void AddMultipleHolds(int holds)
Definition: client_callback.h:406
grpc::ClientCallbackReader
Definition: client_callback.h:170
GPR_LIKELY
#define GPR_LIKELY(x)
Definition: port_platform.h:857
grpc::ClientCallbackUnary::~ClientCallbackUnary
virtual ~ClientCallbackUnary()
Definition: client_callback.h:207
grpc::internal::CallOpSet::set_core_cq_tag
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
sync.h
grpc::internal::ClientCallbackReaderWriterImpl::AddHold
void AddHold(int holds) override
Definition: client_callback.h:577
grpc::ClientWriteReactor::RemoveHold
void RemoveHold()
Definition: client_callback.h:410
grpc::ClientReadReactor
ClientReadReactor is the interface for a server-streaming RPC.
Definition: client_callback.h:144
grpc::internal::ClientCallbackReaderWriterImpl::WritesDone
void WritesDone() ABSL_LOCKS_EXCLUDED(start_mu_) override
Definition: client_callback.h:551
grpc::ClientReadReactor::AddHold
void AddHold()
Definition: client_callback.h:373
grpc::ClientUnaryReactor::OnDone
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
grpc::internal::ClientCallbackReaderFactory::Create
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
grpc::ClientWriteReactor::OnWritesDoneDone
virtual void OnWritesDoneDone(bool)
Definition: client_callback.h:415