GRPC C++  1.82.0
server_callback_handlers.h
Go to the documentation of this file.
1 //
2 //
3 // Copyright 2019 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 #ifndef GRPCPP_IMPL_SERVER_CALLBACK_HANDLERS_H
19 #define GRPCPP_IMPL_SERVER_CALLBACK_HANDLERS_H
20 
21 #include <grpc/grpc.h>
22 #include <grpc/impl/call.h>
25 #include <grpcpp/server.h>
26 #include <grpcpp/server_context.h>
29 #include <grpcpp/support/status.h>
30 
31 #include "absl/log/absl_check.h"
32 #include "absl/status/status.h"
33 
34 namespace grpc {
35 namespace internal {
36 
37 template <class RequestType, class ResponseType>
39  public:
42  const RequestType*, ResponseType*)>
43  get_reactor)
44  : get_reactor_(std::move(get_reactor)) {}
45 
48  allocator_ = allocator;
49  }
50 
51  void RunHandler(const HandlerParameter& param) final {
52  // Arena allocate a controller structure (that includes request/response)
53  grpc_call_ref(param.call->call());
54  auto* allocator_state =
56  param.internal_data);
57 
58  auto* call = new (grpc_call_arena_alloc(param.call->call(),
59  sizeof(ServerCallbackUnaryImpl)))
60  ServerCallbackUnaryImpl(
61  static_cast<grpc::CallbackServerContext*>(param.server_context),
62  param.call, allocator_state, param.call_requester);
63  param.server_context->BeginCompletionOp(
64  param.call, [call](bool) { call->MaybeDone(); }, call);
65 
66  ServerUnaryReactor* reactor = nullptr;
67  if (param.status.ok()) {
68  reactor = grpc::internal::CatchingReactorGetter<ServerUnaryReactor>(
69  get_reactor_,
70  static_cast<grpc::CallbackServerContext*>(param.server_context),
71  call->request(), call->response());
72  }
73 
74  if (reactor == nullptr) {
75  // if deserialization or reactor creator failed, we need to fail the call
76  reactor = new (grpc_call_arena_alloc(param.call->call(),
80  }
81 
83  call->SetupReactor(reactor);
84  }
85 
87  grpc::Status* status, void** handler_data) final {
88  grpc::ByteBuffer buf;
89  buf.set_buffer(req);
90  RequestType* request = nullptr;
92  if (allocator_ != nullptr) {
93  allocator_state = allocator_->AllocateMessages();
94  } else {
95  allocator_state = new (grpc_call_arena_alloc(
98  }
99  *handler_data = allocator_state;
100  request = allocator_state->request();
101  *status = grpc::Deserialize(&buf, request);
102  buf.Release();
103  if (status->ok()) {
104  return request;
105  }
106  return nullptr;
107  }
108 
109  private:
111  const RequestType*, ResponseType*)>
112  get_reactor_;
113  MessageAllocator<RequestType, ResponseType>* allocator_ = nullptr;
114 
115  class ServerCallbackUnaryImpl : public ServerCallbackUnary {
116  public:
117  void Finish(grpc::Status s) override {
118  // A callback that only contains a call to MaybeDone can be run as an
119  // inline callback regardless of whether or not OnDone is inlineable
120  // because if the actual OnDone callback needs to be scheduled, MaybeDone
121  // is responsible for dispatching to an EventEngine thread if needed.
122  // Thus, when setting up the finish_tag_, we can set its own callback to
123  // inlineable.
124  finish_tag_.Set(
125  call_.call(),
126  [this](bool) {
127  this->MaybeDone(
128  reactor_.load(std::memory_order_relaxed)->InternalInlineable());
129  },
130  &finish_ops_, /*can_inline=*/true);
131  finish_ops_.set_core_cq_tag(&finish_tag_);
132 
133  if (!ctx_->sent_initial_metadata_) {
134  finish_ops_.SendInitialMetadata(&ctx_->initial_metadata_,
135  ctx_->initial_metadata_flags());
136  if (ctx_->compression_level_set()) {
137  finish_ops_.set_compression_level(ctx_->compression_level());
138  }
139  ctx_->MarkInitialMetadataSent();
140  }
141  // The response is dropped if the status is not OK.
142  if (s.ok()) {
143  finish_ops_.ServerSendStatus(
144  &ctx_->trailing_metadata_,
145  finish_ops_.SendMessagePtr(response(), ctx_->memory_allocator()));
146  } else {
147  finish_ops_.ServerSendStatus(&ctx_->trailing_metadata_, s);
148  }
149  finish_ops_.set_core_cq_tag(&finish_tag_);
150  finish_ops_.FillOps(&call_);
151  }
152 
153  void SendInitialMetadata() override {
154  ABSL_CHECK(!ctx_->sent_initial_metadata_);
155  this->Ref();
156  // The callback for this function should not be marked inline because it
157  // is directly invoking a user-controlled reaction
158  // (OnSendInitialMetadataDone). Thus it must be dispatched to an
159  // EventEngine thread. However, any OnDone needed after that can be
160  // inlined because it is already running on an EventEngine thread.
161  meta_tag_.Set(
162  call_.call(),
163  [this](bool ok) {
164  ServerUnaryReactor* reactor =
165  reactor_.load(std::memory_order_relaxed);
166  reactor->OnSendInitialMetadataDone(ok);
167  this->MaybeDone(/*inlineable_ondone=*/true);
168  },
169  &meta_ops_, /*can_inline=*/false);
170  meta_ops_.SendInitialMetadata(&ctx_->initial_metadata_,
171  ctx_->initial_metadata_flags());
172  if (ctx_->compression_level_set()) {
173  meta_ops_.set_compression_level(ctx_->compression_level());
174  }
175  ctx_->MarkInitialMetadataSent();
176  meta_ops_.set_core_cq_tag(&meta_tag_);
177  meta_ops_.FillOps(&call_);
178  }
179 
180  private:
181  friend class CallbackUnaryHandler<RequestType, ResponseType>;
182 
183  ServerCallbackUnaryImpl(
185  MessageHolder<RequestType, ResponseType>* allocator_state,
186  std::function<void()> call_requester)
187  : ctx_(ctx),
188  call_(*call),
189  allocator_state_(allocator_state),
190  call_requester_(std::move(call_requester)) {
191  ctx_->set_message_allocator_state(allocator_state);
192  }
193 
194  grpc_call* call() override { return call_.call(); }
195 
200  void SetupReactor(ServerUnaryReactor* reactor) {
201  reactor_.store(reactor, std::memory_order_relaxed);
202  this->BindReactor(reactor);
203  this->MaybeCallOnCancel(reactor);
204  this->MaybeDone(reactor->InternalInlineable());
205  }
206 
207  const RequestType* request() { return allocator_state_->request(); }
208  ResponseType* response() { return allocator_state_->response(); }
209 
210  void CallOnDone() override {
211  reactor_.load(std::memory_order_relaxed)->OnDone();
212  grpc_call* call = call_.call();
213  auto call_requester = std::move(call_requester_);
214  allocator_state_->Release();
215  if (ctx_->context_allocator() != nullptr) {
216  ctx_->context_allocator()->Release(ctx_);
217  }
218  this->~ServerCallbackUnaryImpl(); // explicitly call destructor
219  grpc_call_unref(call);
220  call_requester();
221  }
222 
223  ServerReactor* reactor() override {
224  return reactor_.load(std::memory_order_relaxed);
225  }
226 
228  meta_ops_;
233  finish_ops_;
235 
236  grpc::CallbackServerContext* const ctx_;
237  grpc::internal::Call call_;
238  MessageHolder<RequestType, ResponseType>* const allocator_state_;
239  std::function<void()> call_requester_;
240  // reactor_ can always be loaded/stored with relaxed memory ordering because
241  // its value is only set once, independently of other data in the object,
242  // and the loads that use it will always actually come provably later even
243  // though they are from different threads since they are triggered by
244  // actions initiated only by the setting up of the reactor_ variable. In
245  // a sense, it's a delayed "const": it gets its value from the SetupReactor
246  // method (not the constructor, so it's not a true const), but it doesn't
247  // change after that and it only gets used by actions caused, directly or
248  // indirectly, by that setup. This comment also applies to the reactor_
249  // variables of the other streaming objects in this file.
250  std::atomic<ServerUnaryReactor*> reactor_;
251  // callbacks_outstanding_ follows a refcount pattern
252  std::atomic<intptr_t> callbacks_outstanding_{
253  3}; // reserve for start, Finish, and CompletionOp
254  };
255 };
256 
257 template <class RequestType, class ResponseType>
259  public:
261  std::function<ServerReadReactor<RequestType>*(
262  grpc::CallbackServerContext*, ResponseType*)>
263  get_reactor)
264  : get_reactor_(std::move(get_reactor)) {}
265  void RunHandler(const HandlerParameter& param) final {
266  // Arena allocate a reader structure (that includes response)
267  grpc_call_ref(param.call->call());
268 
269  auto* reader = new (grpc_call_arena_alloc(param.call->call(),
270  sizeof(ServerCallbackReaderImpl)))
271  ServerCallbackReaderImpl(
272  static_cast<grpc::CallbackServerContext*>(param.server_context),
273  param.call, param.call_requester);
274  // Inlineable OnDone can be false in the CompletionOp callback because there
275  // is no read reactor that has an inlineable OnDone; this only applies to
276  // the DefaultReactor (which is unary).
277  param.server_context->BeginCompletionOp(
278  param.call,
279  [reader](bool) { reader->MaybeDone(/*inlineable_ondone=*/false); },
280  reader);
281 
282  ServerReadReactor<RequestType>* reactor = nullptr;
283  if (param.status.ok()) {
284  reactor =
285  grpc::internal::CatchingReactorGetter<ServerReadReactor<RequestType>>(
286  get_reactor_,
287  static_cast<grpc::CallbackServerContext*>(param.server_context),
288  reader->response());
289  }
290 
291  if (reactor == nullptr) {
292  // if deserialization or reactor creator failed, we need to fail the call
293  reactor = new (grpc_call_arena_alloc(
294  param.call->call(), sizeof(UnimplementedReadReactor<RequestType>)))
297  }
298 
299  reader->SetupReactor(reactor);
300  }
301 
302  private:
303  std::function<ServerReadReactor<RequestType>*(grpc::CallbackServerContext*,
304  ResponseType*)>
305  get_reactor_;
306 
307  class ServerCallbackReaderImpl : public ServerCallbackReader<RequestType> {
308  public:
309  void Finish(grpc::Status s) override {
310  // A finish tag with only MaybeDone can have its callback inlined
311  // regardless even if OnDone is not inlineable because this callback just
312  // checks a ref and then decides whether or not to dispatch OnDone.
313  finish_tag_.Set(
314  call_.call(),
315  [this](bool) {
316  // Inlineable OnDone can be false here because there is
317  // no read reactor that has an inlineable OnDone; this
318  // only applies to the DefaultReactor (which is unary).
319  this->MaybeDone(/*inlineable_ondone=*/false);
320  },
321  &finish_ops_, /*can_inline=*/true);
322  if (!ctx_->sent_initial_metadata_) {
323  finish_ops_.SendInitialMetadata(&ctx_->initial_metadata_,
324  ctx_->initial_metadata_flags());
325  if (ctx_->compression_level_set()) {
326  finish_ops_.set_compression_level(ctx_->compression_level());
327  }
328  ctx_->MarkInitialMetadataSent();
329  }
330  // The response is dropped if the status is not OK.
331  if (s.ok()) {
332  finish_ops_.ServerSendStatus(
333  &ctx_->trailing_metadata_,
334  finish_ops_.SendMessagePtr(&resp_, ctx_->memory_allocator()));
335  } else {
336  finish_ops_.ServerSendStatus(&ctx_->trailing_metadata_, s);
337  }
338  finish_ops_.set_core_cq_tag(&finish_tag_);
339  finish_ops_.FillOps(&call_);
340  }
341 
342  void SendInitialMetadata() override {
343  ABSL_CHECK(!ctx_->sent_initial_metadata_);
344  this->Ref();
345  // The callback for this function should not be inlined because it invokes
346  // a user-controlled reaction, but any resulting OnDone can be inlined in
347  // the EventEngine thread to which this callback is dispatched.
348  meta_tag_.Set(
349  call_.call(),
350  [this](bool ok) {
351  ServerReadReactor<RequestType>* reactor =
352  reactor_.load(std::memory_order_relaxed);
353  reactor->OnSendInitialMetadataDone(ok);
354  this->MaybeDone(/*inlineable_ondone=*/true);
355  },
356  &meta_ops_, /*can_inline=*/false);
357  meta_ops_.SendInitialMetadata(&ctx_->initial_metadata_,
358  ctx_->initial_metadata_flags());
359  if (ctx_->compression_level_set()) {
360  meta_ops_.set_compression_level(ctx_->compression_level());
361  }
362  ctx_->MarkInitialMetadataSent();
363  meta_ops_.set_core_cq_tag(&meta_tag_);
364  meta_ops_.FillOps(&call_);
365  }
366 
367  void Read(RequestType* req) override {
368  this->Ref();
369  read_ops_.RecvMessage(req);
370  read_ops_.FillOps(&call_);
371  }
372 
373  private:
374  friend class CallbackClientStreamingHandler<RequestType, ResponseType>;
375 
376  ServerCallbackReaderImpl(grpc::CallbackServerContext* ctx,
377  grpc::internal::Call* call,
378  std::function<void()> call_requester)
379  : ctx_(ctx), call_(*call), call_requester_(std::move(call_requester)) {}
380 
381  grpc_call* call() override { return call_.call(); }
382 
383  void SetupReactor(ServerReadReactor<RequestType>* reactor) {
384  reactor_.store(reactor, std::memory_order_relaxed);
385  // The callback for this function should not be inlined because it invokes
386  // a user-controlled reaction, but any resulting OnDone can be inlined in
387  // the EventEngine thread to which this callback is dispatched.
388  read_tag_.Set(
389  call_.call(),
390  [this, reactor](bool ok) {
391  if (GPR_UNLIKELY(!ok)) {
392  ctx_->MaybeMarkCancelledOnRead();
393  }
394  reactor->OnReadDone(ok);
395  this->MaybeDone(/*inlineable_ondone=*/true);
396  },
397  &read_ops_, /*can_inline=*/false);
398  read_ops_.set_core_cq_tag(&read_tag_);
399  this->BindReactor(reactor);
400  this->MaybeCallOnCancel(reactor);
401  // Inlineable OnDone can be false here because there is no read
402  // reactor that has an inlineable OnDone; this only applies to the
403  // DefaultReactor (which is unary).
404  this->MaybeDone(/*inlineable_ondone=*/false);
405  }
406 
407  ~ServerCallbackReaderImpl() {}
408 
409  ResponseType* response() { return &resp_; }
410 
411  void CallOnDone() override {
412  reactor_.load(std::memory_order_relaxed)->OnDone();
413  grpc_call* call = call_.call();
414  auto call_requester = std::move(call_requester_);
415  if (ctx_->context_allocator() != nullptr) {
416  ctx_->context_allocator()->Release(ctx_);
417  }
418  this->~ServerCallbackReaderImpl(); // explicitly call destructor
419  grpc_call_unref(call);
420  call_requester();
421  }
422 
423  ServerReactor* reactor() override {
424  return reactor_.load(std::memory_order_relaxed);
425  }
426 
428  meta_ops_;
433  finish_ops_;
436  read_ops_;
438 
439  grpc::CallbackServerContext* const ctx_;
440  grpc::internal::Call call_;
441  ResponseType resp_;
442  std::function<void()> call_requester_;
443  // The memory ordering of reactor_ follows ServerCallbackUnaryImpl.
444  std::atomic<ServerReadReactor<RequestType>*> reactor_;
445  // callbacks_outstanding_ follows a refcount pattern
446  std::atomic<intptr_t> callbacks_outstanding_{
447  3}; // reserve for OnStarted, Finish, and CompletionOp
448  };
449 };
450 
451 template <class RequestType, class ResponseType>
453  public:
455  std::function<ServerWriteReactor<ResponseType>*(
456  grpc::CallbackServerContext*, const RequestType*)>
457  get_reactor)
458  : get_reactor_(std::move(get_reactor)) {}
459  void RunHandler(const HandlerParameter& param) final {
460  // Arena allocate a writer structure
461  grpc_call_ref(param.call->call());
462 
463  auto* writer = new (grpc_call_arena_alloc(param.call->call(),
464  sizeof(ServerCallbackWriterImpl)))
465  ServerCallbackWriterImpl(
466  static_cast<grpc::CallbackServerContext*>(param.server_context),
467  param.call, static_cast<RequestType*>(param.request),
468  param.call_requester);
469  // Inlineable OnDone can be false in the CompletionOp callback because there
470  // is no write reactor that has an inlineable OnDone; this only applies to
471  // the DefaultReactor (which is unary).
472  param.server_context->BeginCompletionOp(
473  param.call,
474  [writer](bool) { writer->MaybeDone(/*inlineable_ondone=*/false); },
475  writer);
476 
477  ServerWriteReactor<ResponseType>* reactor = nullptr;
478  if (param.status.ok()) {
481  get_reactor_,
482  static_cast<grpc::CallbackServerContext*>(param.server_context),
483  writer->request());
484  }
485  if (reactor == nullptr) {
486  // if deserialization or reactor creator failed, we need to fail the call
487  reactor = new (grpc_call_arena_alloc(
488  param.call->call(), sizeof(UnimplementedWriteReactor<ResponseType>)))
491  }
492 
493  writer->SetupReactor(reactor);
494  }
495 
497  grpc::Status* status, void** /*handler_data*/) final {
498  grpc::ByteBuffer buf;
499  buf.set_buffer(req);
500  auto* request =
501  new (grpc_call_arena_alloc(call, sizeof(RequestType))) RequestType();
502  *status = grpc::Deserialize(&buf, request);
503  buf.Release();
504  if (status->ok()) {
505  return request;
506  }
507  request->~RequestType();
508  return nullptr;
509  }
510 
511  private:
512  std::function<ServerWriteReactor<ResponseType>*(grpc::CallbackServerContext*,
513  const RequestType*)>
514  get_reactor_;
515 
516  class ServerCallbackWriterImpl : public ServerCallbackWriter<ResponseType> {
517  public:
518  void Finish(grpc::Status s) override {
519  // A finish tag with only MaybeDone can have its callback inlined
520  // regardless even if OnDone is not inlineable because this callback just
521  // checks a ref and then decides whether or not to dispatch OnDone.
522  finish_tag_.Set(
523  call_.call(),
524  [this](bool) {
525  // Inlineable OnDone can be false here because there is
526  // no write reactor that has an inlineable OnDone; this
527  // only applies to the DefaultReactor (which is unary).
528  this->MaybeDone(/*inlineable_ondone=*/false);
529  },
530  &finish_ops_, /*can_inline=*/true);
531  finish_ops_.set_core_cq_tag(&finish_tag_);
532 
533  if (!ctx_->sent_initial_metadata_) {
534  finish_ops_.SendInitialMetadata(&ctx_->initial_metadata_,
535  ctx_->initial_metadata_flags());
536  if (ctx_->compression_level_set()) {
537  finish_ops_.set_compression_level(ctx_->compression_level());
538  }
539  ctx_->MarkInitialMetadataSent();
540  }
541  finish_ops_.ServerSendStatus(&ctx_->trailing_metadata_, s);
542  finish_ops_.FillOps(&call_);
543  }
544 
545  void SendInitialMetadata() override {
546  ABSL_CHECK(!ctx_->sent_initial_metadata_);
547  this->Ref();
548  // The callback for this function should not be inlined because it invokes
549  // a user-controlled reaction, but any resulting OnDone can be inlined in
550  // the EventEngine thread to which this callback is dispatched.
551  meta_tag_.Set(
552  call_.call(),
553  [this](bool ok) {
554  ServerWriteReactor<ResponseType>* reactor =
555  reactor_.load(std::memory_order_relaxed);
556  reactor->OnSendInitialMetadataDone(ok);
557  this->MaybeDone(/*inlineable_ondone=*/true);
558  },
559  &meta_ops_, /*can_inline=*/false);
560  meta_ops_.SendInitialMetadata(&ctx_->initial_metadata_,
561  ctx_->initial_metadata_flags());
562  if (ctx_->compression_level_set()) {
563  meta_ops_.set_compression_level(ctx_->compression_level());
564  }
565  ctx_->MarkInitialMetadataSent();
566  meta_ops_.set_core_cq_tag(&meta_tag_);
567  meta_ops_.FillOps(&call_);
568  }
569 
570  void Write(const ResponseType* resp, grpc::WriteOptions options) override {
571  this->Ref();
572  if (options.is_last_message()) {
573  options.set_buffer_hint();
574  }
575  if (!ctx_->sent_initial_metadata_) {
576  write_ops_.SendInitialMetadata(&ctx_->initial_metadata_,
577  ctx_->initial_metadata_flags());
578  if (ctx_->compression_level_set()) {
579  write_ops_.set_compression_level(ctx_->compression_level());
580  }
581  ctx_->MarkInitialMetadataSent();
582  }
583  // TODO(vjpai): don't assert
584  ABSL_CHECK(
585  write_ops_.SendMessagePtr(resp, options, ctx_->memory_allocator())
586  .ok());
587  write_ops_.FillOps(&call_);
588  }
589 
590  void WriteAndFinish(const ResponseType* resp, grpc::WriteOptions options,
591  grpc::Status s) override {
592  // This combines the write into the finish callback
593  // TODO(vjpai): don't assert
594  ABSL_CHECK(
595  finish_ops_.SendMessagePtr(resp, options, ctx_->memory_allocator())
596  .ok());
597  Finish(std::move(s));
598  }
599 
600  private:
601  friend class CallbackServerStreamingHandler<RequestType, ResponseType>;
602 
603  ServerCallbackWriterImpl(grpc::CallbackServerContext* ctx,
604  grpc::internal::Call* call, const RequestType* req,
605  std::function<void()> call_requester)
606  : ctx_(ctx),
607  call_(*call),
608  req_(req),
609  call_requester_(std::move(call_requester)) {}
610 
611  grpc_call* call() override { return call_.call(); }
612 
613  void SetupReactor(ServerWriteReactor<ResponseType>* reactor) {
614  reactor_.store(reactor, std::memory_order_relaxed);
615  // The callback for this function should not be inlined because it invokes
616  // a user-controlled reaction, but any resulting OnDone can be inlined in
617  // the EventEngine thread to which this callback is dispatched.
618  write_tag_.Set(
619  call_.call(),
620  [this, reactor](bool ok) {
621  reactor->OnWriteDone(ok);
622  this->MaybeDone(/*inlineable_ondone=*/true);
623  },
624  &write_ops_, /*can_inline=*/false);
625  write_ops_.set_core_cq_tag(&write_tag_);
626  this->BindReactor(reactor);
627  this->MaybeCallOnCancel(reactor);
628  // Inlineable OnDone can be false here because there is no write
629  // reactor that has an inlineable OnDone; this only applies to the
630  // DefaultReactor (which is unary).
631  this->MaybeDone(/*inlineable_ondone=*/false);
632  }
633  ~ServerCallbackWriterImpl() {
634  if (req_ != nullptr) {
635  req_->~RequestType();
636  }
637  }
638 
639  const RequestType* request() { return req_; }
640 
641  void CallOnDone() override {
642  reactor_.load(std::memory_order_relaxed)->OnDone();
643  grpc_call* call = call_.call();
644  auto call_requester = std::move(call_requester_);
645  if (ctx_->context_allocator() != nullptr) {
646  ctx_->context_allocator()->Release(ctx_);
647  }
648  this->~ServerCallbackWriterImpl(); // explicitly call destructor
649  grpc_call_unref(call);
650  call_requester();
651  }
652 
653  ServerReactor* reactor() override {
654  return reactor_.load(std::memory_order_relaxed);
655  }
656 
658  meta_ops_;
663  finish_ops_;
667  write_ops_;
669 
670  grpc::CallbackServerContext* const ctx_;
671  grpc::internal::Call call_;
672  const RequestType* req_;
673  std::function<void()> call_requester_;
674  // The memory ordering of reactor_ follows ServerCallbackUnaryImpl.
675  std::atomic<ServerWriteReactor<ResponseType>*> reactor_;
676  // callbacks_outstanding_ follows a refcount pattern
677  std::atomic<intptr_t> callbacks_outstanding_{
678  3}; // reserve for OnStarted, Finish, and CompletionOp
679  };
680 };
681 
682 template <class RequestType, class ResponseType>
684  public:
688  get_reactor)
689  : get_reactor_(std::move(get_reactor)) {}
690  void RunHandler(const HandlerParameter& param) final {
691  grpc_call_ref(param.call->call());
692 
693  auto* stream = new (grpc_call_arena_alloc(
694  param.call->call(), sizeof(ServerCallbackReaderWriterImpl)))
695  ServerCallbackReaderWriterImpl(
696  static_cast<grpc::CallbackServerContext*>(param.server_context),
697  param.call, param.call_requester);
698  // Inlineable OnDone can be false in the CompletionOp callback because there
699  // is no bidi reactor that has an inlineable OnDone; this only applies to
700  // the DefaultReactor (which is unary).
701  param.server_context->BeginCompletionOp(
702  param.call,
703  [stream](bool) { stream->MaybeDone(/*inlineable_ondone=*/false); },
704  stream);
705 
707  if (param.status.ok()) {
710  get_reactor_,
711  static_cast<grpc::CallbackServerContext*>(param.server_context));
712  }
713 
714  if (reactor == nullptr) {
715  // if deserialization or reactor creator failed, we need to fail the call
716  reactor = new (grpc_call_arena_alloc(
717  param.call->call(),
721  }
722 
723  stream->SetupReactor(reactor);
724  }
725 
726  private:
727  std::function<ServerBidiReactor<RequestType, ResponseType>*(
729  get_reactor_;
730 
731  class ServerCallbackReaderWriterImpl
732  : public ServerCallbackReaderWriter<RequestType, ResponseType> {
733  public:
734  void Finish(grpc::Status s) override {
735  // A finish tag with only MaybeDone can have its callback inlined
736  // regardless even if OnDone is not inlineable because this callback just
737  // checks a ref and then decides whether or not to dispatch OnDone.
738  finish_tag_.Set(
739  call_.call(),
740  [this](bool) {
741  // Inlineable OnDone can be false here because there is
742  // no bidi reactor that has an inlineable OnDone; this
743  // only applies to the DefaultReactor (which is unary).
744  this->MaybeDone(/*inlineable_ondone=*/false);
745  },
746  &finish_ops_, /*can_inline=*/true);
747  finish_ops_.set_core_cq_tag(&finish_tag_);
748 
749  if (!ctx_->sent_initial_metadata_) {
750  finish_ops_.SendInitialMetadata(&ctx_->initial_metadata_,
751  ctx_->initial_metadata_flags());
752  if (ctx_->compression_level_set()) {
753  finish_ops_.set_compression_level(ctx_->compression_level());
754  }
755  ctx_->MarkInitialMetadataSent();
756  }
757  finish_ops_.ServerSendStatus(&ctx_->trailing_metadata_, s);
758  finish_ops_.FillOps(&call_);
759  }
760 
761  void SendInitialMetadata() override {
762  ABSL_CHECK(!ctx_->sent_initial_metadata_);
763  this->Ref();
764  // The callback for this function should not be inlined because it invokes
765  // a user-controlled reaction, but any resulting OnDone can be inlined in
766  // the EventEngine thread to which this callback is dispatched.
767  meta_tag_.Set(
768  call_.call(),
769  [this](bool ok) {
770  ServerBidiReactor<RequestType, ResponseType>* reactor =
771  reactor_.load(std::memory_order_relaxed);
772  reactor->OnSendInitialMetadataDone(ok);
773  this->MaybeDone(/*inlineable_ondone=*/true);
774  },
775  &meta_ops_, /*can_inline=*/false);
776  meta_ops_.SendInitialMetadata(&ctx_->initial_metadata_,
777  ctx_->initial_metadata_flags());
778  if (ctx_->compression_level_set()) {
779  meta_ops_.set_compression_level(ctx_->compression_level());
780  }
781  ctx_->MarkInitialMetadataSent();
782  meta_ops_.set_core_cq_tag(&meta_tag_);
783  meta_ops_.FillOps(&call_);
784  }
785 
786  void Write(const ResponseType* resp, grpc::WriteOptions options) override {
787  this->Ref();
788  if (options.is_last_message()) {
789  options.set_buffer_hint();
790  }
791  if (!ctx_->sent_initial_metadata_) {
792  write_ops_.SendInitialMetadata(&ctx_->initial_metadata_,
793  ctx_->initial_metadata_flags());
794  if (ctx_->compression_level_set()) {
795  write_ops_.set_compression_level(ctx_->compression_level());
796  }
797  ctx_->MarkInitialMetadataSent();
798  }
799  // TODO(vjpai): don't assert
800  ABSL_CHECK(
801  write_ops_.SendMessagePtr(resp, options, ctx_->memory_allocator())
802  .ok());
803  write_ops_.FillOps(&call_);
804  }
805 
806  void WriteAndFinish(const ResponseType* resp, grpc::WriteOptions options,
807  grpc::Status s) override {
808  // TODO(vjpai): don't assert
809  ABSL_CHECK(
810  finish_ops_.SendMessagePtr(resp, options, ctx_->memory_allocator())
811  .ok());
812  Finish(std::move(s));
813  }
814 
815  void Read(RequestType* req) override {
816  this->Ref();
817  read_ops_.RecvMessage(req);
818  read_ops_.FillOps(&call_);
819  }
820 
821  private:
822  friend class CallbackBidiHandler<RequestType, ResponseType>;
823 
824  ServerCallbackReaderWriterImpl(grpc::CallbackServerContext* ctx,
825  grpc::internal::Call* call,
826  std::function<void()> call_requester)
827  : ctx_(ctx), call_(*call), call_requester_(std::move(call_requester)) {}
828 
829  grpc_call* call() override { return call_.call(); }
830 
831  void SetupReactor(ServerBidiReactor<RequestType, ResponseType>* reactor) {
832  reactor_.store(reactor, std::memory_order_relaxed);
833  // The callbacks for these functions should not be inlined because they
834  // invoke user-controlled reactions, but any resulting OnDones can be
835  // inlined in the EventEngine thread to which a callback is dispatched.
836  write_tag_.Set(
837  call_.call(),
838  [this, reactor](bool ok) {
839  reactor->OnWriteDone(ok);
840  this->MaybeDone(/*inlineable_ondone=*/true);
841  },
842  &write_ops_, /*can_inline=*/false);
843  write_ops_.set_core_cq_tag(&write_tag_);
844  read_tag_.Set(
845  call_.call(),
846  [this, reactor](bool ok) {
847  if (GPR_UNLIKELY(!ok)) {
848  ctx_->MaybeMarkCancelledOnRead();
849  }
850  reactor->OnReadDone(ok);
851  this->MaybeDone(/*inlineable_ondone=*/true);
852  },
853  &read_ops_, /*can_inline=*/false);
854  read_ops_.set_core_cq_tag(&read_tag_);
855  this->BindReactor(reactor);
856  this->MaybeCallOnCancel(reactor);
857  // Inlineable OnDone can be false here because there is no bidi
858  // reactor that has an inlineable OnDone; this only applies to the
859  // DefaultReactor (which is unary).
860  this->MaybeDone(/*inlineable_ondone=*/false);
861  }
862 
863  void CallOnDone() override {
864  reactor_.load(std::memory_order_relaxed)->OnDone();
865  grpc_call* call = call_.call();
866  auto call_requester = std::move(call_requester_);
867  if (ctx_->context_allocator() != nullptr) {
868  ctx_->context_allocator()->Release(ctx_);
869  }
870  this->~ServerCallbackReaderWriterImpl(); // explicitly call destructor
871  grpc_call_unref(call);
872  call_requester();
873  }
874 
875  ServerReactor* reactor() override {
876  return reactor_.load(std::memory_order_relaxed);
877  }
878 
880  meta_ops_;
885  finish_ops_;
889  write_ops_;
892  read_ops_;
894 
895  grpc::CallbackServerContext* const ctx_;
896  grpc::internal::Call call_;
897  std::function<void()> call_requester_;
898  // The memory ordering of reactor_ follows ServerCallbackUnaryImpl.
899  std::atomic<ServerBidiReactor<RequestType, ResponseType>*> reactor_;
900  // callbacks_outstanding_ follows a refcount pattern
901  std::atomic<intptr_t> callbacks_outstanding_{
902  3}; // reserve for OnStarted, Finish, and CompletionOp
903  };
904 };
905 
906 } // namespace internal
907 
908 namespace experimental {
909 namespace internal {
910 
911 template <class RequestType>
913  public:
916  grpc::CallbackServerContext*, const RequestType*)>
917  get_reactor,
918  grpc::Service* service = nullptr)
919  : get_reactor_(std::move(get_reactor)), service_(service) {
920  ABSL_CHECK(service_ != nullptr && service_->is_virtual_service_);
921  }
922 
923  void RunHandler(const HandlerParameter& param) final {
924  // Arena allocate a controller structure (that includes request/response)
925  grpc_call_ref(param.call->call());
926  auto* allocator_state =
928  param.internal_data);
929 
930  grpc::Server* inner_server = nullptr;
931  inner_server = static_cast<grpc::Server*>(service_->server_);
932  ABSL_CHECK(inner_server != nullptr);
933 
934  auto* call = new (grpc_call_arena_alloc(param.call->call(),
935  sizeof(ServerCallbackSessionImpl)))
936  ServerCallbackSessionImpl(
937  static_cast<grpc::CallbackServerContext*>(param.server_context),
938  param.call, allocator_state, param.call_requester, inner_server);
939 
940  param.server_context->BeginCompletionOp(
941  param.call, [call](bool) { call->MaybeDone(); }, call);
942 
943  grpc::experimental::ServerSessionReactor* reactor = nullptr;
944  if (param.status.ok()) {
947  get_reactor_,
948  static_cast<grpc::CallbackServerContext*>(param.server_context),
949  call->request());
950  }
951 
952  if (reactor == nullptr) {
953  // if deserialization or reactor creator failed, we need to fail the call.
954  reactor = new (grpc_call_arena_alloc(param.call->call(),
958  }
959 
961  call->SetupReactor(reactor);
962  }
963 
965  grpc::Status* status, void** handler_data) final {
966  grpc::ByteBuffer buf;
967  buf.set_buffer(req);
968  RequestType* request = nullptr;
970  allocator_state = new (grpc_call_arena_alloc(
971  call, sizeof(grpc::internal::DefaultMessageHolder<RequestType,
972  grpc::ByteBuffer>)))
974  *handler_data = allocator_state;
975  request = allocator_state->request();
976  *status = grpc::Deserialize(&buf, request);
977  buf.Release();
978  if (status->ok()) {
979  return request;
980  }
981  return nullptr;
982  }
983 
984  private:
986  grpc::CallbackServerContext*, const RequestType*)>
987  get_reactor_;
988  grpc::Service* service_;
989 
990  class ServerCallbackSessionImpl
992  public:
993  void Finish(grpc::Status s) override {
994  if (ctx_->IsCancelled()) {
995  MaybeDone(
996  reactor_.load(std::memory_order_relaxed)->InternalInlineable());
997  return;
998  }
999  // A callback that only contains a call to MaybeDone can be run as an
1000  // inline callback regardless of whether or not OnDone is inlineable
1001  // because if the actual OnDone callback needs to be scheduled, MaybeDone
1002  // is responsible for dispatching to an EventEngine thread if needed.
1003  // Thus, when setting up the finish_tag_, we can set its own callback to
1004  // inlineable.
1005  finish_tag_.Set(
1006  call_.call(),
1007  [this](bool) {
1008  this->MaybeDone(
1009  reactor_.load(std::memory_order_relaxed)->InternalInlineable());
1010  },
1011  &finish_ops_, /*can_inline=*/true);
1012  finish_ops_.set_core_cq_tag(&finish_tag_);
1013 
1014  bool is_first_metadata = !ctx_->sent_initial_metadata_;
1015  if (is_first_metadata) {
1016  finish_ops_.SendInitialMetadata(&ctx_->initial_metadata_,
1017  ctx_->initial_metadata_flags());
1018  if (ctx_->compression_level_set()) {
1019  finish_ops_.set_compression_level(ctx_->compression_level());
1020  }
1021  ctx_->MarkInitialMetadataSent();
1022  }
1023  finish_ops_.ServerSendStatus(&ctx_->trailing_metadata_, s);
1024  finish_ops_.set_core_cq_tag(&finish_tag_);
1025  finish_ops_.FillOps(&call_);
1026  }
1027 
1028  void SendInitialMetadata() override {
1029  ABSL_CHECK(!ctx_->sent_initial_metadata_);
1030  this->Ref();
1031  // The callback for this function should not be marked inline because it
1032  // is directly invoking a user-controlled reaction
1033  // (OnSendInitialMetadataDone). Thus it must be dispatched to an
1034  // EventEngine thread. However, any OnDone needed after that can be
1035  // inlined because it is already running on an EventEngine thread.
1036  meta_tag_.Set(
1037  call_.call(),
1038  [this](bool ok) {
1039  grpc::experimental::ServerSessionReactor* reactor =
1040  reactor_.load(std::memory_order_relaxed);
1041  reactor->OnSendInitialMetadataDone(ok);
1042  this->MaybeDone(/*inlineable_ondone=*/true);
1043  },
1044  &meta_ops_, /*can_inline=*/false);
1045  meta_ops_.SendInitialMetadata(&ctx_->initial_metadata_,
1046  ctx_->initial_metadata_flags());
1047  if (ctx_->compression_level_set()) {
1048  meta_ops_.set_compression_level(ctx_->compression_level());
1049  }
1050  ctx_->MarkInitialMetadataSent();
1051  meta_ops_.set_core_cq_tag(&meta_tag_);
1052  meta_ops_.FillOps(&call_);
1053  // We bind the inner server only when sending initial metadata because
1054  // this signals that the session handler has completed context
1055  // establishment and virtual RPCs can be started.
1056  BindInnerServer(inner_server_);
1057  }
1058 
1059  void BindInnerServer(grpc::Server* inner_server) override {
1061  call_.call(), inner_server, &transport_, &endpoint_);
1062  }
1063 
1064  void InitiateGracefulShutdown(
1065  absl::AnyInvocable<void(absl::Status)> on_shutdown) override {
1067  transport_, endpoint_, std::move(on_shutdown));
1068  }
1069 
1070  private:
1071  friend class CallbackSessionHandler<RequestType>;
1072 
1073  ServerCallbackSessionImpl(
1075  MessageHolder<RequestType, grpc::ByteBuffer>* allocator_state,
1076  std::function<void()> call_requester, grpc::Server* inner_server)
1077  : ctx_(ctx),
1078  call_(*call),
1079  allocator_state_(allocator_state),
1080  call_requester_(std::move(call_requester)),
1081  inner_server_(inner_server) {
1082  ABSL_CHECK(inner_server_ != nullptr);
1083  ctx_->set_message_allocator_state(allocator_state);
1084  }
1085 
1086  grpc_call* call() override { return call_.call(); }
1087 
1092  void SetupReactor(grpc::experimental::ServerSessionReactor* reactor) {
1093  reactor_.store(reactor, std::memory_order_relaxed);
1094  this->BindReactor(reactor);
1095  this->MaybeCallOnCancel(reactor);
1096  this->MaybeDone(reactor->InternalInlineable());
1097  }
1098 
1099  const RequestType* request() { return allocator_state_->request(); }
1100 
1101  void CallOnDone() override {
1102  reactor_.load(std::memory_order_relaxed)->OnDone();
1103  grpc_call* call = call_.call();
1104  auto call_requester = std::move(call_requester_);
1105  allocator_state_->Release();
1106  if (ctx_->context_allocator() != nullptr) {
1107  ctx_->context_allocator()->Release(ctx_);
1108  }
1109  this->~ServerCallbackSessionImpl(); // explicitly call destructor
1110  grpc_call_unref(call);
1111  call_requester();
1112  }
1113 
1114  grpc::internal::ServerReactor* reactor() override {
1115  return reactor_.load(std::memory_order_relaxed);
1116  }
1117 
1119  meta_ops_;
1123  finish_ops_;
1125 
1126  grpc::CallbackServerContext* const ctx_;
1127  grpc::internal::Call call_;
1128  grpc_core::Transport* transport_ = nullptr;
1129  grpc_endpoint* endpoint_ = nullptr;
1130  MessageHolder<RequestType, grpc::ByteBuffer>* const allocator_state_;
1131  std::function<void()> call_requester_;
1132  grpc::Server* inner_server_;
1133  // The memory ordering of reactor_ follows ServerCallbackUnaryImpl.
1134  std::atomic<grpc::experimental::ServerSessionReactor*> reactor_;
1135  // callbacks_outstanding_ follows a refcount pattern
1136  std::atomic<intptr_t> callbacks_outstanding_{
1137  3}; // reserve for start, Finish, and CompletionOp
1138  };
1139 };
1140 
1141 } // namespace internal
1142 } // namespace experimental
1143 } // namespace grpc
1144 
1145 #endif // GRPCPP_IMPL_SERVER_CALLBACK_HANDLERS_H
grpc::ServerReadReactor
ServerReadReactor is the interface for a client-streaming RPC.
Definition: server_callback.h:210
grpc::internal::CallbackWithSuccessTag
CallbackWithSuccessTag can be reused multiple times, and will be used in this fashion for streaming o...
Definition: callback_common.h:153
grpc::ServerCallbackReaderWriter::SendInitialMetadata
virtual void SendInitialMetadata()=0
message_allocator.h
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::CallOpServerSendStatus
Definition: call_op_set.h:656
grpc::Server
Represents a gRPC server.
Definition: server.h:58
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< grpc::internal::CallOpSendInitialMetadata >
grpc::CallbackServerContext
Definition: server_context.h:741
grpc::Deserialize
auto Deserialize(BufferPtr buffer, Message *msg)
Definition: serialization_traits.h:120
grpc::internal::CallOpSendMessage
Definition: call_op_set.h:287
grpc::internal::MethodHandler::HandlerParameter
Definition: rpc_service_method.h:43
grpc::MessageHolder::response
ResponseT * response()
Definition: message_allocator.h:46
grpc::internal::Call
Straightforward wrapping of the C call object.
Definition: call.h:34
rpc_service_method.h
grpc::Service
Descriptor of an RPC service and its various RPC methods.
Definition: service_type.h:66
grpc::internal::CallbackClientStreamingHandler::RunHandler
void RunHandler(const HandlerParameter &param) final
Definition: server_callback_handlers.h:265
status.h
grpc::ServerCallbackUnary::BindReactor
void BindReactor(Reactor *reactor)
Definition: server_callback.h:234
grpc::internal::CallOpSendInitialMetadata
Definition: call_op_set.h:217
grpc::internal::ServerCallbackCall::MaybeCallOnCancel
void MaybeCallOnCancel(ServerReactor *reactor)
Definition: server_callback.h:129
grpc::internal::CallbackClientStreamingHandler::CallbackClientStreamingHandler
CallbackClientStreamingHandler(std::function< ServerReadReactor< RequestType > *(grpc::CallbackServerContext *, ResponseType *)> get_reactor)
Definition: server_callback_handlers.h:260
grpc::Status::ok
bool ok() const
Is the status OK?
Definition: status.h:124
grpc_call_ref
GRPCAPI void grpc_call_ref(grpc_call *call)
Ref a call.
grpc::ServerCallbackReaderWriter
Definition: server_callback.h:290
grpc::internal::CallbackUnaryHandler::CallbackUnaryHandler
CallbackUnaryHandler(std::function< ServerUnaryReactor *(grpc::CallbackServerContext *, const RequestType *, ResponseType *)> get_reactor)
Definition: server_callback_handlers.h:40
grpc::Status
Did it work? If it didn't, why?
Definition: status.h:34
grpc::experimental::ServerSessionReactor
Definition: server_callback.h:818
grpc_call_unref
GRPCAPI void grpc_call_unref(grpc_call *call)
Unref a call.
grpc::internal::CallbackServerStreamingHandler::Deserialize
void * Deserialize(grpc_call *call, grpc_byte_buffer *req, grpc::Status *status, void **) final
Definition: server_callback_handlers.h:496
grpc::experimental::internal::CallbackSessionHandler::Deserialize
void * Deserialize(grpc_call *call, grpc_byte_buffer *req, grpc::Status *status, void **handler_data) final
Definition: server_callback_handlers.h:964
grpc::MessageAllocator< RequestType, ResponseType >
grpc.h
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_byte_buffer
Definition: grpc_types.h:41
grpc::ByteBuffer
A sequence of bytes.
Definition: byte_buffer.h:67
grpc::internal::CallbackUnaryHandler
Definition: server_callback_handlers.h:38
grpc::ServerCallbackWriter::SendInitialMetadata
virtual void SendInitialMetadata()=0
grpc::internal::DefaultMessageHolder
Definition: server_callback.h:189
grpc::internal::CallbackServerStreamingHandler
Definition: server_callback_handlers.h:452
grpc::experimental::ServerCallbackSession
Definition: server_callback.h:240
grpc::internal::CallbackServerStreamingHandler::CallbackServerStreamingHandler
CallbackServerStreamingHandler(std::function< ServerWriteReactor< ResponseType > *(grpc::CallbackServerContext *, const RequestType *)> get_reactor)
Definition: server_callback_handlers.h:454
grpc::internal::CallbackBidiHandler::RunHandler
void RunHandler(const HandlerParameter &param) final
Definition: server_callback_handlers.h:690
grpc::experimental::internal::InitiateSessionGracefulShutdown
void InitiateSessionGracefulShutdown(grpc_core::Transport *transport, grpc_endpoint *endpoint, absl::AnyInvocable< void(absl::Status)> on_shutdown)
grpc::internal::CallbackUnaryHandler::RunHandler
void RunHandler(const HandlerParameter &param) final
Definition: server_callback_handlers.h:51
grpc::ServerCallbackReader< RequestType >::BindReactor
void BindReactor(ServerReadReactor< RequestType > *reactor)
Definition: server_callback.h:267
grpc::MessageAllocator::AllocateMessages
virtual MessageHolder< RequestT, ResponseT > * AllocateMessages()=0
grpc::experimental::internal::CallbackSessionHandler::CallbackSessionHandler
CallbackSessionHandler(std::function< grpc::experimental::ServerSessionReactor *(grpc::CallbackServerContext *, const RequestType *)> get_reactor, grpc::Service *service=nullptr)
Definition: server_callback_handlers.h:914
grpc::internal::FinishOnlyReactor
Definition: server_context.h:90
grpc::internal::MethodHandler
Base class for running an RPC handler.
Definition: rpc_service_method.h:40
server_callback.h
grpc::experimental::internal::CallbackSessionHandler
Definition: server_callback_handlers.h:912
grpc::MessageHolder::request
RequestT * request()
Definition: message_allocator.h:45
grpc::WriteOptions
Per-message write options.
Definition: call_op_set.h:79
grpc::ServerWriteReactor
ServerWriteReactor is the interface for a server-streaming RPC.
Definition: server_callback.h:212
grpc::internal::UnimplementedUnaryReactor
FinishOnlyReactor< ServerUnaryReactor > UnimplementedUnaryReactor
Definition: server_callback.h:929
grpc::internal::CallbackBidiHandler
Definition: server_callback_handlers.h:683
grpc::UNIMPLEMENTED
@ UNIMPLEMENTED
Operation is not implemented or not supported/enabled in this service.
Definition: status_code_enum.h:117
grpc::ServerCallbackWriter
Definition: server_callback.h:273
call.h
grpc::internal::Call::call
grpc_call * call() const
Definition: call.h:55
server_context.h
std
Definition: async_unary_call.h:410
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::WriteOptions::set_buffer_hint
WriteOptions & set_buffer_hint()
Sets flag indicating that the write may be buffered and need not go out on the wire immediately.
Definition: call_op_set.h:117
grpc::internal::CallbackUnaryHandler::SetMessageAllocator
void SetMessageAllocator(MessageAllocator< RequestType, ResponseType > *allocator)
Definition: server_callback_handlers.h:46
grpc::ServerCallbackUnary::SendInitialMetadata
virtual void SendInitialMetadata()=0
service_type.h
grpc::internal::ServerReactor
Definition: server_callback.h:71
grpc::experimental::internal::CallbackSessionHandler::RunHandler
void RunHandler(const HandlerParameter &param) final
Definition: server_callback_handlers.h:923
grpc::internal::CallbackClientStreamingHandler
Definition: server_callback_handlers.h:258
grpc::internal::ServerCallbackCall::Ref
void Ref()
Increases the reference count.
Definition: server_callback.h:147
grpc::internal::CallbackBidiHandler::CallbackBidiHandler
CallbackBidiHandler(std::function< ServerBidiReactor< RequestType, ResponseType > *(grpc::CallbackServerContext *)> get_reactor)
Definition: server_callback_handlers.h:685
grpc::ServerCallbackReader
Definition: server_callback.h:259
server.h
grpc::WriteOptions::is_last_message
bool is_last_message() const
Get value for the flag indicating that this is the last message, and should be coalesced with trailin...
Definition: call_op_set.h:172
grpc::MessageHolder< RequestType, ResponseType >
grpc::ByteBuffer::Release
void Release()
Forget underlying byte buffer without destroying Use this only for un-owned byte buffers.
Definition: byte_buffer.h:151
grpc::experimental::internal::BindSessionToInnerServer
void BindSessionToInnerServer(grpc_call *call, grpc::Server *inner_server, grpc_core::Transport **out_transport, grpc_endpoint **out_endpoint)
grpc::internal::CatchingReactorGetter
Reactor * CatchingReactorGetter(Func &&func, Args &&... args)
Definition: callback_common.h:57
grpc::ServerCallbackUnary
Definition: server_callback.h:224
grpc::ServerUnaryReactor
Definition: server_callback.h:749
grpc::protobuf::util::Status
::absl::Status Status
Definition: config_protobuf.h:107
grpc::internal::CallbackServerStreamingHandler::RunHandler
void RunHandler(const HandlerParameter &param) final
Definition: server_callback_handlers.h:459
grpc::ServerCallbackReader::SendInitialMetadata
virtual void SendInitialMetadata()=0
grpc::internal::ServerCallbackCall::MaybeDone
void MaybeDone()
Definition: server_callback.h:115
grpc::internal::CallbackUnaryHandler::Deserialize
void * Deserialize(grpc_call *call, grpc_byte_buffer *req, grpc::Status *status, void **handler_data) final
Definition: server_callback_handlers.h:86