GRPC C++  1.82.0
server_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_SERVER_CALLBACK_H
20 #define GRPCPP_SUPPORT_SERVER_CALLBACK_H
21 
22 #include <grpc/impl/call.h>
23 #include <grpcpp/impl/call.h>
25 #include <grpcpp/impl/sync.h>
27 #include <grpcpp/support/config.h>
29 #include <grpcpp/support/status.h>
30 
31 #include <atomic>
32 #include <functional>
33 #include <type_traits>
34 
35 #include "absl/functional/any_invocable.h"
36 #include "absl/status/status.h"
37 
38 struct grpc_endpoint;
39 namespace grpc_core {
40 class Transport;
41 }
42 
43 namespace grpc {
44 
45 class Server;
46 
47 // Declare base class of all reactors as internal
48 namespace experimental {
49 namespace internal {
50 void BindSessionToInnerServer(grpc_call* call, grpc::Server* inner_server,
51  grpc_core::Transport** out_transport,
52  grpc_endpoint** out_endpoint);
54  grpc_core::Transport* transport, grpc_endpoint* endpoint,
55  absl::AnyInvocable<void(absl::Status)> on_shutdown);
56 } // namespace internal
57 } // namespace experimental
58 
59 namespace internal {
60 
61 // Forward declarations
62 template <class Request, class Response>
63 class CallbackUnaryHandler;
64 template <class Request, class Response>
65 class CallbackClientStreamingHandler;
66 template <class Request, class Response>
67 class CallbackServerStreamingHandler;
68 template <class Request, class Response>
69 class CallbackBidiHandler;
70 
72  public:
73  virtual ~ServerReactor() = default;
74  virtual void OnDone() = 0;
75  virtual void OnCancel() = 0;
76 
77  // The following is not API. It is for internal use only and specifies whether
78  // all reactions of this Reactor can be run without extra EventEngine
79  // scheduling. This should only be used for internally-defined reactors with
80  // trivial reactions.
81  virtual bool InternalInlineable() { return false; }
82 
83  private:
84  template <class Request, class Response>
85  friend class CallbackUnaryHandler;
86  template <class Request, class Response>
88  template <class Request, class Response>
90  template <class Request, class Response>
91  friend class CallbackBidiHandler;
92 };
93 
96  public:
97  virtual ~ServerCallbackCall() {}
98 
99  // This object is responsible for tracking when it is safe to call OnDone and
100  // OnCancel. OnDone should not be called until the method handler is complete,
101  // Finish has been called, the ServerContext CompletionOp (which tracks
102  // cancellation or successful completion) has completed, and all outstanding
103  // Read/Write actions have seen their reactions. OnCancel should not be called
104  // until after the method handler is done and the RPC has completed with a
105  // cancellation. This is tracked by counting how many of these conditions have
106  // been met and calling OnCancel when none remain unmet.
107 
108  // Public versions of MaybeDone: one where we don't know the reactor in
109  // advance (used for the ServerContext CompletionOp), and one for where we
110  // know the inlineability of the OnDone reaction. You should set the inline
111  // flag to true if either the Reactor is InternalInlineable() or if this
112  // callback is already being forced to run dispatched to an EventEngine thread
113  // (typically because it contains additional work than just the MaybeDone).
114 
115  void MaybeDone() {
116  if (GPR_UNLIKELY(Unref() == 1)) {
117  ScheduleOnDone(reactor()->InternalInlineable());
118  }
119  }
120 
121  void MaybeDone(bool inline_ondone) {
122  if (GPR_UNLIKELY(Unref() == 1)) {
123  ScheduleOnDone(inline_ondone);
124  }
125  }
126 
127  // Fast version called with known reactor passed in, used from derived
128  // classes, typically in non-cancel case
130  if (GPR_UNLIKELY(UnblockCancellation())) {
131  CallOnCancel(reactor);
132  }
133  }
134 
135  // Slower version called from object that doesn't know the reactor a priori
136  // (such as the ServerContext CompletionOp which is formed before the
137  // reactor). This is used in cancel cases only, so it's ok to be slower and
138  // invoke a virtual function.
140  if (GPR_UNLIKELY(UnblockCancellation())) {
141  CallOnCancel(reactor());
142  }
143  }
144 
145  protected:
147  void Ref() { callbacks_outstanding_.fetch_add(1, std::memory_order_relaxed); }
148 
149  private:
150  virtual ServerReactor* reactor() = 0;
151 
152  virtual grpc_call* call() = 0;
153 
154  virtual void RunAsync(absl::AnyInvocable<void()> cb) {
155  grpc_call_run_in_event_engine(call(), std::move(cb));
156  }
157 
158  // CallOnDone performs the work required at completion of the RPC: invoking
159  // the OnDone function and doing all necessary cleanup. This function is only
160  // ever invoked on a fully-Unref'fed ServerCallbackCall.
161  virtual void CallOnDone() = 0;
162 
163  // If the OnDone reaction is inlineable, execute it inline. Otherwise run it
164  // async on EventEngine.
165  void ScheduleOnDone(bool inline_ondone);
166 
167  // If the OnCancel reaction is inlineable, execute it inline. Otherwise run it
168  // async on EventEngine.
169  void CallOnCancel(ServerReactor* reactor);
170 
171  // Implement the cancellation constraint counter. Return true if OnCancel
172  // should be called, false otherwise.
173  bool UnblockCancellation() {
174  return on_cancel_conditions_remaining_.fetch_sub(
175  1, std::memory_order_acq_rel) == 1;
176  }
177 
179  int Unref() {
180  return callbacks_outstanding_.fetch_sub(1, std::memory_order_acq_rel);
181  }
182 
183  std::atomic_int on_cancel_conditions_remaining_{2};
184  std::atomic_int callbacks_outstanding_{
185  3}; // reserve for start, Finish, and CompletionOp
186 };
187 
188 template <class Request, class Response>
189 class DefaultMessageHolder : public MessageHolder<Request, Response> {
190  public:
192  this->set_request(&request_obj_);
193  this->set_response(&response_obj_);
194  }
195  void Release() override {
196  // the object is allocated in the call arena.
198  }
199 
200  private:
201  Request request_obj_;
202  Response response_obj_;
203 };
204 
205 } // namespace internal
206 
207 // Forward declarations
208 class ServerUnaryReactor;
209 template <class Request>
211 template <class Response>
213 template <class Request, class Response>
215 
216 namespace experimental {
217 class ServerSessionReactor;
218 class ServerCallbackSession;
219 } // namespace experimental
220 
221 // NOTE: The actual call/stream object classes are provided as API only to
222 // support mocking. There are no implementations of these class interfaces in
223 // the API.
225  public:
226  ~ServerCallbackUnary() override {}
227  virtual void Finish(grpc::Status s) = 0;
228  virtual void SendInitialMetadata() = 0;
229 
230  protected:
231  // Use a template rather than explicitly specifying ServerUnaryReactor to
232  // delay binding and avoid a circular forward declaration issue
233  template <class Reactor>
234  void BindReactor(Reactor* reactor) {
235  reactor->InternalBindCall(this);
236  }
237 };
238 
239 namespace experimental {
241  public:
243 
244  virtual void Finish(grpc::Status s) = 0;
245  virtual void SendInitialMetadata() = 0;
246  virtual void BindInnerServer(grpc::Server* inner_server) = 0;
247  virtual void InitiateGracefulShutdown(
248  absl::AnyInvocable<void(absl::Status)> on_shutdown) = 0;
249 
250  protected:
251  template <class Reactor>
252  void BindReactor(Reactor* reactor) {
253  reactor->InternalBindSession(this);
254  }
255 };
256 } // namespace experimental
257 
258 template <class Request>
260  public:
261  ~ServerCallbackReader() override {}
262  virtual void Finish(grpc::Status s) = 0;
263  virtual void SendInitialMetadata() = 0;
264  virtual void Read(Request* msg) = 0;
265 
266  protected:
268  reactor->InternalBindReader(this);
269  }
270 };
271 
272 template <class Response>
274  public:
275  ~ServerCallbackWriter() override {}
276 
277  virtual void Finish(grpc::Status s) = 0;
278  virtual void SendInitialMetadata() = 0;
279  virtual void Write(const Response* msg, grpc::WriteOptions options) = 0;
280  virtual void WriteAndFinish(const Response* msg, grpc::WriteOptions options,
281  grpc::Status s) = 0;
282 
283  protected:
285  reactor->InternalBindWriter(this);
286  }
287 };
288 
289 template <class Request, class Response>
291  public:
293 
294  virtual void Finish(grpc::Status s) = 0;
295  virtual void SendInitialMetadata() = 0;
296  virtual void Read(Request* msg) = 0;
297  virtual void Write(const Response* msg, grpc::WriteOptions options) = 0;
298  virtual void WriteAndFinish(const Response* msg, grpc::WriteOptions options,
299  grpc::Status s) = 0;
300 
301  protected:
303  reactor->InternalBindStream(this);
304  }
305 };
306 
307 // The following classes are the reactor interfaces that are to be implemented
308 // by the user, returned as the output parameter of the method handler for a
309 // callback method. Note that none of the classes are pure; all reactions have a
310 // default empty reaction so that the user class only needs to override those
311 // reactions that it cares about. The reaction methods will be invoked by the
312 // library in response to the completion of various operations. Reactions must
313 // not include blocking operations (such as blocking I/O, starting synchronous
314 // RPCs, or waiting on condition variables). Reactions may be invoked
315 // concurrently, except that OnDone is called after all others (assuming proper
316 // API usage). The reactor may not be deleted until OnDone is called.
317 
319 template <class Request, class Response>
320 class ServerBidiReactor : public internal::ServerReactor {
321  public:
322  // NOTE: Initializing stream_ as a constructor initializer rather than a
323  // default initializer because gcc-4.x requires a copy constructor for
324  // default initializing a templated member, which isn't ok for atomic.
325  // TODO(vjpai): Switch to default constructor and default initializer when
326  // gcc-4.x is no longer supported
327  ServerBidiReactor() : stream_(nullptr) {}
328  ~ServerBidiReactor() override = default;
329 
333  void StartSendInitialMetadata() ABSL_LOCKS_EXCLUDED(stream_mu_) {
335  stream_.load(std::memory_order_acquire);
336  if (stream == nullptr) {
337  grpc::internal::MutexLock l(&stream_mu_);
338  stream = stream_.load(std::memory_order_relaxed);
339  if (stream == nullptr) {
340  backlog_.send_initial_metadata_wanted = true;
341  return;
342  }
343  }
344  stream->SendInitialMetadata();
345  }
346 
351  void StartRead(Request* req) ABSL_LOCKS_EXCLUDED(stream_mu_) {
353  stream_.load(std::memory_order_acquire);
354  if (stream == nullptr) {
355  grpc::internal::MutexLock l(&stream_mu_);
356  stream = stream_.load(std::memory_order_relaxed);
357  if (stream == nullptr) {
358  backlog_.read_wanted = req;
359  return;
360  }
361  }
362  stream->Read(req);
363  }
364 
370  void StartWrite(const Response* resp) {
372  }
373 
380  void StartWrite(const Response* resp, grpc::WriteOptions options)
381  ABSL_LOCKS_EXCLUDED(stream_mu_) {
383  stream_.load(std::memory_order_acquire);
384  if (stream == nullptr) {
385  grpc::internal::MutexLock l(&stream_mu_);
386  stream = stream_.load(std::memory_order_relaxed);
387  if (stream == nullptr) {
388  backlog_.write_wanted = resp;
389  backlog_.write_options_wanted = options;
390  return;
391  }
392  }
393  stream->Write(resp, options);
394  }
395 
409  void StartWriteAndFinish(const Response* resp, grpc::WriteOptions options,
410  grpc::Status s) ABSL_LOCKS_EXCLUDED(stream_mu_) {
412  stream_.load(std::memory_order_acquire);
413  if (stream == nullptr) {
414  grpc::internal::MutexLock l(&stream_mu_);
415  stream = stream_.load(std::memory_order_relaxed);
416  if (stream == nullptr) {
417  backlog_.write_and_finish_wanted = true;
418  backlog_.write_wanted = resp;
419  backlog_.write_options_wanted = options;
420  backlog_.status_wanted = std::move(s);
421  return;
422  }
423  }
424  stream->WriteAndFinish(resp, options, std::move(s));
425  }
426 
435  void StartWriteLast(const Response* resp, grpc::WriteOptions options) {
436  StartWrite(resp, options.set_last_message());
437  }
438 
445  void Finish(grpc::Status s) ABSL_LOCKS_EXCLUDED(stream_mu_) {
447  stream_.load(std::memory_order_acquire);
448  if (stream == nullptr) {
449  grpc::internal::MutexLock l(&stream_mu_);
450  stream = stream_.load(std::memory_order_relaxed);
451  if (stream == nullptr) {
452  backlog_.finish_wanted = true;
453  backlog_.status_wanted = std::move(s);
454  return;
455  }
456  }
457  stream->Finish(std::move(s));
458  }
459 
466  virtual void OnSendInitialMetadataDone(bool /*ok*/) {}
467 
472  virtual void OnReadDone(bool /*ok*/) {}
473 
479  virtual void OnWriteDone(bool /*ok*/) {}
480 
484  void OnDone() override = 0;
485 
489  void OnCancel() override {}
490 
491  private:
492  friend class ServerCallbackReaderWriter<Request, Response>;
493  // May be overridden by internal implementation details. This is not a public
494  // customization point.
495  virtual void InternalBindStream(
497  grpc::internal::MutexLock l(&stream_mu_);
498 
499  if (GPR_UNLIKELY(backlog_.send_initial_metadata_wanted)) {
500  stream->SendInitialMetadata();
501  }
502  if (GPR_UNLIKELY(backlog_.read_wanted != nullptr)) {
503  stream->Read(backlog_.read_wanted);
504  }
505  if (GPR_UNLIKELY(backlog_.write_and_finish_wanted)) {
506  stream->WriteAndFinish(backlog_.write_wanted,
507  std::move(backlog_.write_options_wanted),
508  std::move(backlog_.status_wanted));
509  } else {
510  if (GPR_UNLIKELY(backlog_.write_wanted != nullptr)) {
511  stream->Write(backlog_.write_wanted,
512  std::move(backlog_.write_options_wanted));
513  }
514  if (GPR_UNLIKELY(backlog_.finish_wanted)) {
515  stream->Finish(std::move(backlog_.status_wanted));
516  }
517  }
518  // Set stream_ last so that other functions can use it lock-free
519  stream_.store(stream, std::memory_order_release);
520  }
521 
522  grpc::internal::Mutex stream_mu_;
523  // TODO(vjpai): Make stream_or_backlog_ into an std::variant once C++17 or
524  // ABSL is supported since stream and backlog are mutually exclusive in this
525  // class. Do likewise with the remaining reactor classes and their backlogs
526  // as well.
527  std::atomic<ServerCallbackReaderWriter<Request, Response>*> stream_{nullptr};
528  struct PreBindBacklog {
529  bool send_initial_metadata_wanted = false;
530  bool write_and_finish_wanted = false;
531  bool finish_wanted = false;
532  Request* read_wanted = nullptr;
533  const Response* write_wanted = nullptr;
534  grpc::WriteOptions write_options_wanted;
535  grpc::Status status_wanted;
536  };
537  PreBindBacklog backlog_ ABSL_GUARDED_BY(stream_mu_);
538 };
539 
541 template <class Request>
542 class ServerReadReactor : public internal::ServerReactor {
543  public:
544  ServerReadReactor() : reader_(nullptr) {}
545  ~ServerReadReactor() override = default;
546 
548  void StartSendInitialMetadata() ABSL_LOCKS_EXCLUDED(reader_mu_) {
550  reader_.load(std::memory_order_acquire);
551  if (reader == nullptr) {
552  grpc::internal::MutexLock l(&reader_mu_);
553  reader = reader_.load(std::memory_order_relaxed);
554  if (reader == nullptr) {
555  backlog_.send_initial_metadata_wanted = true;
556  return;
557  }
558  }
559  reader->SendInitialMetadata();
560  }
561  void StartRead(Request* req) ABSL_LOCKS_EXCLUDED(reader_mu_) {
563  reader_.load(std::memory_order_acquire);
564  if (reader == nullptr) {
565  grpc::internal::MutexLock l(&reader_mu_);
566  reader = reader_.load(std::memory_order_relaxed);
567  if (reader == nullptr) {
568  backlog_.read_wanted = req;
569  return;
570  }
571  }
572  reader->Read(req);
573  }
574  void Finish(grpc::Status s) ABSL_LOCKS_EXCLUDED(reader_mu_) {
576  reader_.load(std::memory_order_acquire);
577  if (reader == nullptr) {
578  grpc::internal::MutexLock l(&reader_mu_);
579  reader = reader_.load(std::memory_order_relaxed);
580  if (reader == nullptr) {
581  backlog_.finish_wanted = true;
582  backlog_.status_wanted = std::move(s);
583  return;
584  }
585  }
586  reader->Finish(std::move(s));
587  }
588 
590  virtual void OnSendInitialMetadataDone(bool /*ok*/) {}
591  virtual void OnReadDone(bool /*ok*/) {}
592  void OnDone() override = 0;
593  void OnCancel() override {}
594 
595  private:
596  friend class ServerCallbackReader<Request>;
597 
598  // May be overridden by internal implementation details. This is not a public
599  // customization point.
600  virtual void InternalBindReader(ServerCallbackReader<Request>* reader)
601  ABSL_LOCKS_EXCLUDED(reader_mu_) {
602  grpc::internal::MutexLock l(&reader_mu_);
603 
604  if (GPR_UNLIKELY(backlog_.send_initial_metadata_wanted)) {
605  reader->SendInitialMetadata();
606  }
607  if (GPR_UNLIKELY(backlog_.read_wanted != nullptr)) {
608  reader->Read(backlog_.read_wanted);
609  }
610  if (GPR_UNLIKELY(backlog_.finish_wanted)) {
611  reader->Finish(std::move(backlog_.status_wanted));
612  }
613  // Set reader_ last so that other functions can use it lock-free
614  reader_.store(reader, std::memory_order_release);
615  }
616 
617  grpc::internal::Mutex reader_mu_;
618  std::atomic<ServerCallbackReader<Request>*> reader_{nullptr};
619  struct PreBindBacklog {
620  bool send_initial_metadata_wanted = false;
621  bool finish_wanted = false;
622  Request* read_wanted = nullptr;
623  grpc::Status status_wanted;
624  };
625  PreBindBacklog backlog_ ABSL_GUARDED_BY(reader_mu_);
626 };
627 
629 template <class Response>
630 class ServerWriteReactor : public internal::ServerReactor {
631  public:
632  ServerWriteReactor() : writer_(nullptr) {}
633  ~ServerWriteReactor() override = default;
634 
636  void StartSendInitialMetadata() ABSL_LOCKS_EXCLUDED(writer_mu_) {
638  writer_.load(std::memory_order_acquire);
639  if (writer == nullptr) {
640  grpc::internal::MutexLock l(&writer_mu_);
641  writer = writer_.load(std::memory_order_relaxed);
642  if (writer == nullptr) {
643  backlog_.send_initial_metadata_wanted = true;
644  return;
645  }
646  }
647  writer->SendInitialMetadata();
648  }
649  void StartWrite(const Response* resp) {
651  }
652  void StartWrite(const Response* resp, grpc::WriteOptions options)
653  ABSL_LOCKS_EXCLUDED(writer_mu_) {
655  writer_.load(std::memory_order_acquire);
656  if (writer == nullptr) {
657  grpc::internal::MutexLock l(&writer_mu_);
658  writer = writer_.load(std::memory_order_relaxed);
659  if (writer == nullptr) {
660  backlog_.write_wanted = resp;
661  backlog_.write_options_wanted = options;
662  return;
663  }
664  }
665  writer->Write(resp, options);
666  }
667  void StartWriteAndFinish(const Response* resp, grpc::WriteOptions options,
668  grpc::Status s) ABSL_LOCKS_EXCLUDED(writer_mu_) {
670  writer_.load(std::memory_order_acquire);
671  if (writer == nullptr) {
672  grpc::internal::MutexLock l(&writer_mu_);
673  writer = writer_.load(std::memory_order_relaxed);
674  if (writer == nullptr) {
675  backlog_.write_and_finish_wanted = true;
676  backlog_.write_wanted = resp;
677  backlog_.write_options_wanted = options;
678  backlog_.status_wanted = std::move(s);
679  return;
680  }
681  }
682  writer->WriteAndFinish(resp, options, std::move(s));
683  }
684  void StartWriteLast(const Response* resp, grpc::WriteOptions options) {
685  StartWrite(resp, options.set_last_message());
686  }
687  void Finish(grpc::Status s) ABSL_LOCKS_EXCLUDED(writer_mu_) {
689  writer_.load(std::memory_order_acquire);
690  if (writer == nullptr) {
691  grpc::internal::MutexLock l(&writer_mu_);
692  writer = writer_.load(std::memory_order_relaxed);
693  if (writer == nullptr) {
694  backlog_.finish_wanted = true;
695  backlog_.status_wanted = std::move(s);
696  return;
697  }
698  }
699  writer->Finish(std::move(s));
700  }
701 
703  virtual void OnSendInitialMetadataDone(bool /*ok*/) {}
704  virtual void OnWriteDone(bool /*ok*/) {}
705  void OnDone() override = 0;
706  void OnCancel() override {}
707 
708  private:
709  friend class ServerCallbackWriter<Response>;
710  // May be overridden by internal implementation details. This is not a public
711  // customization point.
712  virtual void InternalBindWriter(ServerCallbackWriter<Response>* writer)
713  ABSL_LOCKS_EXCLUDED(writer_mu_) {
714  grpc::internal::MutexLock l(&writer_mu_);
715 
716  if (GPR_UNLIKELY(backlog_.send_initial_metadata_wanted)) {
717  writer->SendInitialMetadata();
718  }
719  if (GPR_UNLIKELY(backlog_.write_and_finish_wanted)) {
720  writer->WriteAndFinish(backlog_.write_wanted,
721  std::move(backlog_.write_options_wanted),
722  std::move(backlog_.status_wanted));
723  } else {
724  if (GPR_UNLIKELY(backlog_.write_wanted != nullptr)) {
725  writer->Write(backlog_.write_wanted,
726  std::move(backlog_.write_options_wanted));
727  }
728  if (GPR_UNLIKELY(backlog_.finish_wanted)) {
729  writer->Finish(std::move(backlog_.status_wanted));
730  }
731  }
732  // Set writer_ last so that other functions can use it lock-free
733  writer_.store(writer, std::memory_order_release);
734  }
735 
736  grpc::internal::Mutex writer_mu_;
737  std::atomic<ServerCallbackWriter<Response>*> writer_{nullptr};
738  struct PreBindBacklog {
739  bool send_initial_metadata_wanted = false;
740  bool write_and_finish_wanted = false;
741  bool finish_wanted = false;
742  const Response* write_wanted = nullptr;
743  grpc::WriteOptions write_options_wanted;
744  grpc::Status status_wanted;
745  };
746  PreBindBacklog backlog_ ABSL_GUARDED_BY(writer_mu_);
747 };
748 
750  public:
751  ServerUnaryReactor() : call_(nullptr) {}
752  ~ServerUnaryReactor() override = default;
753 
755  void StartSendInitialMetadata() ABSL_LOCKS_EXCLUDED(call_mu_) {
756  ServerCallbackUnary* call = call_.load(std::memory_order_acquire);
757  if (call == nullptr) {
758  grpc::internal::MutexLock l(&call_mu_);
759  call = call_.load(std::memory_order_relaxed);
760  if (call == nullptr) {
761  backlog_.send_initial_metadata_wanted = true;
762  return;
763  }
764  }
765  call->SendInitialMetadata();
766  }
770  void Finish(grpc::Status s) ABSL_LOCKS_EXCLUDED(call_mu_) {
771  ServerCallbackUnary* call = call_.load(std::memory_order_acquire);
772  if (call == nullptr) {
773  grpc::internal::MutexLock l(&call_mu_);
774  call = call_.load(std::memory_order_relaxed);
775  if (call == nullptr) {
776  backlog_.finish_wanted = true;
777  backlog_.status_wanted = std::move(s);
778  return;
779  }
780  }
781  call->Finish(std::move(s));
782  }
783 
785  virtual void OnSendInitialMetadataDone(bool /*ok*/) {}
786  void OnDone() override = 0;
787  void OnCancel() override {}
788 
789  private:
790  friend class ServerCallbackUnary;
791  // May be overridden by internal implementation details. This is not a public
792  // customization point.
793  virtual void InternalBindCall(ServerCallbackUnary* call)
794  ABSL_LOCKS_EXCLUDED(call_mu_) {
795  grpc::internal::MutexLock l(&call_mu_);
796 
797  if (GPR_UNLIKELY(backlog_.send_initial_metadata_wanted)) {
798  call->SendInitialMetadata();
799  }
800  if (GPR_UNLIKELY(backlog_.finish_wanted)) {
801  call->Finish(std::move(backlog_.status_wanted));
802  }
803  // Set call_ last so that other functions can use it lock-free
804  call_.store(call, std::memory_order_release);
805  }
806 
807  grpc::internal::Mutex call_mu_;
808  std::atomic<ServerCallbackUnary*> call_{nullptr};
809  struct PreBindBacklog {
810  bool send_initial_metadata_wanted = false;
811  bool finish_wanted = false;
812  grpc::Status status_wanted;
813  };
814  PreBindBacklog backlog_ ABSL_GUARDED_BY(call_mu_);
815 };
816 
817 namespace experimental {
819  public:
820  ServerSessionReactor() : session_(nullptr) {}
821  ~ServerSessionReactor() override = default;
822 
825  void StartVirtualRPCs() ABSL_LOCKS_EXCLUDED(session_mu_) {
826  ServerCallbackSession* session = session_.load(std::memory_order_acquire);
827  if (session == nullptr) {
828  grpc::internal::MutexLock l(&session_mu_);
829  session = session_.load(std::memory_order_relaxed);
830  if (session == nullptr) {
831  backlog_.send_initial_metadata_wanted = true;
832  return;
833  }
834  }
835  session->SendInitialMetadata();
836  }
837 
841  void Finish(grpc::Status s) ABSL_LOCKS_EXCLUDED(session_mu_) {
842  ServerCallbackSession* session = session_.load(std::memory_order_acquire);
843  if (session == nullptr) {
844  grpc::internal::MutexLock l(&session_mu_);
845  session = session_.load(std::memory_order_relaxed);
846  if (session == nullptr) {
847  backlog_.finish_wanted = true;
848  backlog_.status_wanted = std::move(s);
849  return;
850  }
851  }
852  session->Finish(std::move(s));
853  }
854 
862  absl::AnyInvocable<void(absl::Status)> on_shutdown)
863  ABSL_LOCKS_EXCLUDED(session_mu_) {
864  ServerCallbackSession* session = session_.load(std::memory_order_acquire);
865  if (session == nullptr) {
866  grpc::internal::MutexLock l(&session_mu_);
867  session = session_.load(std::memory_order_relaxed);
868  if (session == nullptr) {
869  backlog_.graceful_shutdown_wanted_callback = std::move(on_shutdown);
870  return;
871  }
872  }
873  session->InitiateGracefulShutdown(std::move(on_shutdown));
874  }
875 
877  virtual void OnSendInitialMetadataDone(bool /*ok*/) {}
878  void OnDone() override = 0;
879  void OnCancel() override {}
880 
881  private:
882  friend class ServerCallbackSession;
883  // May be overridden by internal implementation details. This is not a public
884  // customization point.
885  virtual void InternalBindSession(ServerCallbackSession* session)
886  ABSL_LOCKS_EXCLUDED(session_mu_) {
887  grpc::internal::MutexLock l(&session_mu_);
888 
889  if (GPR_UNLIKELY(backlog_.send_initial_metadata_wanted)) {
890  session->SendInitialMetadata();
891  }
892  if (GPR_UNLIKELY(backlog_.graceful_shutdown_wanted_callback != nullptr)) {
893  session->InitiateGracefulShutdown(
894  std::move(backlog_.graceful_shutdown_wanted_callback));
895  }
896  if (GPR_UNLIKELY(backlog_.finish_wanted)) {
897  session->Finish(std::move(backlog_.status_wanted));
898  }
899  // Set session_ last so that other functions can use it lock-free
900  session_.store(session, std::memory_order_release);
901  }
902 
903  grpc::internal::Mutex session_mu_;
904  std::atomic<ServerCallbackSession*> session_{nullptr};
905  struct PreBindBacklog {
906  bool send_initial_metadata_wanted = false;
907  bool finish_wanted = false;
908  absl::AnyInvocable<void(absl::Status)> graceful_shutdown_wanted_callback;
909  grpc::Status status_wanted;
910  };
911 
912  // Resolves a race condition where application code calls reactor methods
913  // before gRPC binds the session to the reactor.
914  // These early operations are stored here and executed during
915  // InternalBindSession().
916  PreBindBacklog backlog_ ABSL_GUARDED_BY(session_mu_);
917 };
918 } // namespace experimental
919 
920 namespace internal {
921 
922 template <class Base>
923 class FinishOnlyReactor : public Base {
924  public:
925  explicit FinishOnlyReactor(grpc::Status s) { this->Finish(std::move(s)); }
926  void OnDone() override { this->~FinishOnlyReactor(); }
927 };
928 
930 template <class Request>
932 template <class Response>
935 template <class Request, class Response>
938 
939 } // namespace internal
940 
941 namespace experimental {
942 namespace internal {
945 } // namespace internal
946 } // namespace experimental
947 
948 // TODO(vjpai): Remove namespace experimental when last known users are migrated
949 // off.
950 namespace experimental {
951 
952 template <class Request, class Response>
954 
955 } // namespace experimental
956 
957 } // namespace grpc
958 
959 #endif // GRPCPP_SUPPORT_SERVER_CALLBACK_H
grpc::ServerReadReactor
ServerReadReactor is the interface for a client-streaming RPC.
Definition: server_callback.h:210
grpc::ServerCallbackReaderWriter::SendInitialMetadata
virtual void SendInitialMetadata()=0
grpc::ServerCallbackReader::~ServerCallbackReader
~ServerCallbackReader() override
Definition: server_callback.h:261
grpc::MessageHolder< Request, Response >::set_response
void set_response(Response *response)
Definition: message_allocator.h:50
grpc::ServerReadReactor::OnCancel
void OnCancel() override
Definition: server_callback.h:593
grpc::ServerBidiReactor::StartSendInitialMetadata
void StartSendInitialMetadata() ABSL_LOCKS_EXCLUDED(stream_mu_)
Send any initial metadata stored in the RPC context.
Definition: server_callback.h:333
grpc::experimental::ServerSessionReactor::StartVirtualRPCs
void StartVirtualRPCs() ABSL_LOCKS_EXCLUDED(session_mu_)
StartVirtualRPCs is exactly like ServerBidiReactor's StartSendInitialMetadata.
Definition: server_callback.h:825
grpc::MessageHolder< Request, Response >::set_request
void set_request(Request *request)
Definition: message_allocator.h:49
message_allocator.h
grpc::ServerReadReactor::ServerReadReactor
ServerReadReactor()
Definition: server_callback.h:544
grpc::ServerReadReactor::OnDone
void OnDone() override=0
grpc::ServerCallbackReaderWriter::Finish
virtual void Finish(grpc::Status s)=0
grpc::ServerWriteReactor::StartWrite
void StartWrite(const Response *resp)
Definition: server_callback.h:649
grpc::Server
Represents a gRPC server.
Definition: server.h:58
grpc::ServerCallbackWriter::Finish
virtual void Finish(grpc::Status s)=0
grpc
An Alarm posts the user-provided tag to its associated completion queue or invokes the user-provided ...
Definition: alarm.h:33
grpc::ServerUnaryReactor::OnDone
void OnDone() override=0
grpc::ServerBidiReactor::StartWriteAndFinish
void StartWriteAndFinish(const Response *resp, grpc::WriteOptions options, grpc::Status s) ABSL_LOCKS_EXCLUDED(stream_mu_)
Initiate a write operation with specified options and final RPC Status, which also causes any trailin...
Definition: server_callback.h:409
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:156
grpc_core
Definition: context_types.h:20
grpc::internal::ServerReactor::~ServerReactor
virtual ~ServerReactor()=default
grpc::internal::ServerCallbackCall::MaybeCallOnCancel
void MaybeCallOnCancel()
Definition: server_callback.h:139
grpc::ServerWriteReactor::StartWrite
void StartWrite(const Response *resp, grpc::WriteOptions options) ABSL_LOCKS_EXCLUDED(writer_mu_)
Definition: server_callback.h:652
grpc::ServerWriteReactor::OnWriteDone
virtual void OnWriteDone(bool)
Definition: server_callback.h:704
grpc::ServerBidiReactor::ServerBidiReactor
ServerBidiReactor()
Definition: server_callback.h:327
grpc::ServerWriteReactor::OnSendInitialMetadataDone
virtual void OnSendInitialMetadataDone(bool)
The following notifications are exactly like ServerBidiReactor.
Definition: server_callback.h:703
grpc::ServerCallbackReader::Finish
virtual void Finish(grpc::Status s)=0
grpc::ServerReadReactor::StartRead
void StartRead(Request *req) ABSL_LOCKS_EXCLUDED(reader_mu_)
Definition: server_callback.h:561
grpc::internal::DefaultMessageHolder::DefaultMessageHolder
DefaultMessageHolder()
Definition: server_callback.h:191
grpc::experimental::ServerSessionReactor::~ServerSessionReactor
~ServerSessionReactor() override=default
grpc::ServerCallbackReaderWriter::~ServerCallbackReaderWriter
~ServerCallbackReaderWriter() override
Definition: server_callback.h:292
status.h
grpc::ServerCallbackUnary::BindReactor
void BindReactor(Reactor *reactor)
Definition: server_callback.h:234
grpc::internal::ServerCallbackCall::MaybeCallOnCancel
void MaybeCallOnCancel(ServerReactor *reactor)
Definition: server_callback.h:129
grpc::ServerWriteReactor::StartWriteLast
void StartWriteLast(const Response *resp, grpc::WriteOptions options)
Definition: server_callback.h:684
grpc::ServerReadReactor::~ServerReadReactor
~ServerReadReactor() override=default
grpc::experimental::ServerCallbackSession::InitiateGracefulShutdown
virtual void InitiateGracefulShutdown(absl::AnyInvocable< void(absl::Status)> on_shutdown)=0
grpc::ServerCallbackReaderWriter
Definition: server_callback.h:290
grpc::ServerBidiReactor::StartWrite
void StartWrite(const Response *resp)
Initiate a write operation.
Definition: server_callback.h:370
grpc::experimental::ServerCallbackSession::BindInnerServer
virtual void BindInnerServer(grpc::Server *inner_server)=0
grpc::ServerBidiReactor::OnCancel
void OnCancel() override
Notifies the application that this RPC has been cancelled.
Definition: server_callback.h:489
grpc::ServerCallbackReaderWriter::Write
virtual void Write(const Response *msg, grpc::WriteOptions options)=0
grpc::experimental::ServerCallbackSession::~ServerCallbackSession
~ServerCallbackSession() override
Definition: server_callback.h:242
grpc::ServerBidiReactor::StartRead
void StartRead(Request *req) ABSL_LOCKS_EXCLUDED(stream_mu_)
Initiate a read operation.
Definition: server_callback.h:351
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::ServerWriteReactor::OnDone
void OnDone() override=0
grpc::ServerCallbackUnary::~ServerCallbackUnary
~ServerCallbackUnary() override
Definition: server_callback.h:226
grpc::ServerUnaryReactor::OnSendInitialMetadataDone
virtual void OnSendInitialMetadataDone(bool)
The following notifications are exactly like ServerBidiReactor.
Definition: server_callback.h:785
grpc::experimental::ServerSessionReactor::ServerSessionReactor
ServerSessionReactor()
Definition: server_callback.h:820
grpc::experimental::ServerSessionReactor
Definition: server_callback.h:818
grpc::internal::ServerCallbackCall
The base class of ServerCallbackUnary etc.
Definition: server_callback.h:95
grpc::experimental::ServerSessionReactor::OnSendInitialMetadataDone
virtual void OnSendInitialMetadataDone(bool)
The following notifications are exactly like ServerBidiReactor.
Definition: server_callback.h:877
grpc::ServerBidiReactor::OnWriteDone
virtual void OnWriteDone(bool)
Notifies the application that a StartWrite (or StartWriteLast) operation completed.
Definition: server_callback.h:479
grpc::ServerBidiReactor::StartWrite
void StartWrite(const Response *resp, grpc::WriteOptions options) ABSL_LOCKS_EXCLUDED(stream_mu_)
Initiate a write operation with specified options.
Definition: server_callback.h:380
callback_common.h
grpc::experimental::ServerSessionReactor::Finish
void Finish(grpc::Status s) ABSL_LOCKS_EXCLUDED(session_mu_)
Finish is similar to ServerBidiReactor except for one detail.
Definition: server_callback.h:841
grpc::ServerCallbackReaderWriter::WriteAndFinish
virtual void WriteAndFinish(const Response *msg, grpc::WriteOptions options, grpc::Status s)=0
grpc::ServerBidiReactor::OnDone
void OnDone() override=0
Notifies the application that all operations associated with this RPC have completed.
grpc_call
struct grpc_call grpc_call
A Call represents an RPC.
Definition: grpc_types.h:68
grpc::ServerBidiReactor
ServerBidiReactor is the interface for a bidirectional streaming RPC.
Definition: server_callback.h:214
grpc::internal::CallbackUnaryHandler
Definition: server_callback_handlers.h:38
grpc::ServerCallbackWriter::SendInitialMetadata
virtual void SendInitialMetadata()=0
grpc::ServerBidiReactor::~ServerBidiReactor
~ServerBidiReactor() override=default
grpc::internal::DefaultMessageHolder
Definition: server_callback.h:189
grpc::internal::FinishOnlyReactor::FinishOnlyReactor
FinishOnlyReactor(grpc::Status s)
Definition: server_callback.h:925
grpc::ServerBidiReactor::OnReadDone
virtual void OnReadDone(bool)
Notifies the application that a StartRead operation completed.
Definition: server_callback.h:472
grpc::internal::ServerReactor::OnDone
virtual void OnDone()=0
grpc::ServerWriteReactor::StartWriteAndFinish
void StartWriteAndFinish(const Response *resp, grpc::WriteOptions options, grpc::Status s) ABSL_LOCKS_EXCLUDED(writer_mu_)
Definition: server_callback.h:667
grpc::internal::CallbackServerStreamingHandler
Definition: server_callback_handlers.h:452
grpc::experimental::ServerCallbackSession
Definition: server_callback.h:240
grpc::experimental::internal::InitiateSessionGracefulShutdown
void InitiateSessionGracefulShutdown(grpc_core::Transport *transport, grpc_endpoint *endpoint, absl::AnyInvocable< void(absl::Status)> on_shutdown)
grpc::ServerCallbackReaderWriter::Read
virtual void Read(Request *msg)=0
grpc::ServerBidiReactor::Finish
void Finish(grpc::Status s) ABSL_LOCKS_EXCLUDED(stream_mu_)
Indicate that the stream is to be finished and the trailing metadata and RPC status are to be sent.
Definition: server_callback.h:445
grpc::ServerCallbackReader::BindReactor
void BindReactor(ServerReadReactor< Request > *reactor)
Definition: server_callback.h:267
grpc::ServerCallbackWriter::BindReactor
void BindReactor(ServerWriteReactor< Response > *reactor)
Definition: server_callback.h:284
grpc::internal::FinishOnlyReactor
Definition: server_context.h:90
grpc::ServerCallbackWriter::~ServerCallbackWriter
~ServerCallbackWriter() override
Definition: server_callback.h:275
grpc_call_run_in_event_engine
void grpc_call_run_in_event_engine(const grpc_call *call, absl::AnyInvocable< void()> cb)
grpc::ServerReadReactor::StartSendInitialMetadata
void StartSendInitialMetadata() ABSL_LOCKS_EXCLUDED(reader_mu_)
The following operation initiations are exactly like ServerBidiReactor.
Definition: server_callback.h:548
grpc::internal::ServerCallbackCall::~ServerCallbackCall
virtual ~ServerCallbackCall()
Definition: server_callback.h:97
grpc::WriteOptions
Per-message write options.
Definition: call_op_set.h:79
grpc::experimental::ServerCallbackSession::BindReactor
void BindReactor(Reactor *reactor)
Definition: server_callback.h:252
grpc::internal::ServerCallbackCall::MaybeDone
void MaybeDone(bool inline_ondone)
Definition: server_callback.h:121
grpc::ServerWriteReactor
ServerWriteReactor is the interface for a server-streaming RPC.
Definition: server_callback.h:212
grpc::ServerReadReactor::OnReadDone
virtual void OnReadDone(bool)
Definition: server_callback.h:591
grpc::ServerCallbackReader::Read
virtual void Read(Request *msg)=0
grpc::internal::CallbackBidiHandler
Definition: server_callback_handlers.h:683
grpc::internal::MutexLock
Definition: sync.h:80
grpc::ServerWriteReactor::OnCancel
void OnCancel() override
Definition: server_callback.h:706
grpc::ServerWriteReactor::~ServerWriteReactor
~ServerWriteReactor() override=default
grpc::ServerCallbackReaderWriter::BindReactor
void BindReactor(ServerBidiReactor< Request, Response > *reactor)
Definition: server_callback.h:302
config.h
grpc::ServerCallbackWriter
Definition: server_callback.h:273
call.h
grpc::experimental::ServerSessionReactor::OnDone
void OnDone() override=0
grpc::ServerWriteReactor::StartSendInitialMetadata
void StartSendInitialMetadata() ABSL_LOCKS_EXCLUDED(writer_mu_)
The following operation initiations are exactly like ServerBidiReactor.
Definition: server_callback.h:636
call_op_set.h
call.h
grpc::experimental::internal::UnimplementedSessionReactor
grpc::internal::FinishOnlyReactor< ServerSessionReactor > UnimplementedSessionReactor
Definition: server_callback.h:944
grpc::internal::ServerReactor::InternalInlineable
virtual bool InternalInlineable()
Definition: server_callback.h:81
grpc::ServerCallbackUnary::SendInitialMetadata
virtual void SendInitialMetadata()=0
grpc::ServerReadReactor::OnSendInitialMetadataDone
virtual void OnSendInitialMetadataDone(bool)
The following notifications are exactly like ServerBidiReactor.
Definition: server_callback.h:590
grpc::ServerBidiReactor::StartWriteLast
void StartWriteLast(const Response *resp, grpc::WriteOptions options)
Inform system of a planned write operation with specified options, but allow the library to schedule ...
Definition: server_callback.h:435
grpc::internal::FinishOnlyReactor::OnDone
void OnDone() override
Definition: server_callback.h:926
grpc::internal::ServerReactor
Definition: server_callback.h:71
grpc::experimental::ServerCallbackSession::SendInitialMetadata
virtual void SendInitialMetadata()=0
grpc::internal::CallbackClientStreamingHandler
Definition: server_callback_handlers.h:258
grpc::ServerUnaryReactor::OnCancel
void OnCancel() override
Definition: server_callback.h:787
grpc::internal::ServerCallbackCall::Ref
void Ref()
Increases the reference count.
Definition: server_callback.h:147
grpc::internal::ServerReactor::OnCancel
virtual void OnCancel()=0
grpc::ServerCallbackReader
Definition: server_callback.h:259
grpc::ServerReadReactor::Finish
void Finish(grpc::Status s) ABSL_LOCKS_EXCLUDED(reader_mu_)
Definition: server_callback.h:574
grpc::ServerCallbackWriter::Write
virtual void Write(const Response *msg, grpc::WriteOptions options)=0
grpc::MessageHolder
Definition: message_allocator.h:39
grpc::internal::Mutex
Definition: sync.h:57
grpc::ServerUnaryReactor::StartSendInitialMetadata
void StartSendInitialMetadata() ABSL_LOCKS_EXCLUDED(call_mu_)
StartSendInitialMetadata is exactly like ServerBidiReactor.
Definition: server_callback.h:755
grpc::ServerWriteReactor::Finish
void Finish(grpc::Status s) ABSL_LOCKS_EXCLUDED(writer_mu_)
Definition: server_callback.h:687
grpc::experimental::internal::BindSessionToInnerServer
void BindSessionToInnerServer(grpc_call *call, grpc::Server *inner_server, grpc_core::Transport **out_transport, grpc_endpoint **out_endpoint)
grpc::experimental::ServerSessionReactor::InitiateGracefulShutdown
void InitiateGracefulShutdown(absl::AnyInvocable< void(absl::Status)> on_shutdown) ABSL_LOCKS_EXCLUDED(session_mu_)
Initiate a graceful shutdown of a SESSION_RPC.
Definition: server_callback.h:861
grpc::ServerUnaryReactor::Finish
void Finish(grpc::Status s) ABSL_LOCKS_EXCLUDED(call_mu_)
Finish is similar to ServerBidiReactor except for one detail.
Definition: server_callback.h:770
grpc::ServerBidiReactor::OnSendInitialMetadataDone
virtual void OnSendInitialMetadataDone(bool)
Notifies the application that an explicit StartSendInitialMetadata operation completed.
Definition: server_callback.h:466
grpc::ServerUnaryReactor::~ServerUnaryReactor
~ServerUnaryReactor() override=default
grpc::ServerCallbackUnary
Definition: server_callback.h:224
grpc::ServerUnaryReactor::ServerUnaryReactor
ServerUnaryReactor()
Definition: server_callback.h:751
grpc::experimental::ServerCallbackSession::Finish
virtual void Finish(grpc::Status s)=0
grpc::ServerWriteReactor::ServerWriteReactor
ServerWriteReactor()
Definition: server_callback.h:632
grpc::ServerUnaryReactor
Definition: server_callback.h:749
grpc::protobuf::util::Status
::absl::Status Status
Definition: config_protobuf.h:107
grpc::ServerCallbackWriter::WriteAndFinish
virtual void WriteAndFinish(const Response *msg, grpc::WriteOptions options, grpc::Status s)=0
sync.h
grpc::ServerCallbackUnary::Finish
virtual void Finish(grpc::Status s)=0
grpc::ServerCallbackReader::SendInitialMetadata
virtual void SendInitialMetadata()=0
grpc::internal::ServerCallbackCall::MaybeDone
void MaybeDone()
Definition: server_callback.h:115
grpc::experimental::ServerSessionReactor::OnCancel
void OnCancel() override
Definition: server_callback.h:879
grpc::internal::DefaultMessageHolder::Release
void Release() override
Definition: server_callback.h:195
grpc::experimental::ServerBidiReactor
::grpc::ServerBidiReactor< Request, Response > ServerBidiReactor
Definition: server_callback.h:953