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