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