• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_IMPL_CODEGEN_CLIENT_CALLBACK_H
20 #define GRPCPP_IMPL_CODEGEN_CLIENT_CALLBACK_H
21 
22 #include <functional>
23 
24 #include <grpcpp/impl/codegen/call.h>
25 #include <grpcpp/impl/codegen/callback_common.h>
26 #include <grpcpp/impl/codegen/channel_interface.h>
27 #include <grpcpp/impl/codegen/config.h>
28 #include <grpcpp/impl/codegen/core_codegen_interface.h>
29 #include <grpcpp/impl/codegen/status.h>
30 
31 namespace grpc {
32 
33 class Channel;
34 class ClientContext;
35 class CompletionQueue;
36 
37 namespace internal {
38 class RpcMethod;
39 
40 /// Perform a callback-based unary call
41 /// TODO(vjpai): Combine as much as possible with the blocking unary call code
42 template <class InputMessage, class OutputMessage>
CallbackUnaryCall(ChannelInterface * channel,const RpcMethod & method,ClientContext * context,const InputMessage * request,OutputMessage * result,std::function<void (Status)> on_completion)43 void CallbackUnaryCall(ChannelInterface* channel, const RpcMethod& method,
44                        ClientContext* context, const InputMessage* request,
45                        OutputMessage* result,
46                        std::function<void(Status)> on_completion) {
47   CallbackUnaryCallImpl<InputMessage, OutputMessage> x(
48       channel, method, context, request, result, on_completion);
49 }
50 
51 template <class InputMessage, class OutputMessage>
52 class CallbackUnaryCallImpl {
53  public:
CallbackUnaryCallImpl(ChannelInterface * channel,const RpcMethod & method,ClientContext * context,const InputMessage * request,OutputMessage * result,std::function<void (Status)> on_completion)54   CallbackUnaryCallImpl(ChannelInterface* channel, const RpcMethod& method,
55                         ClientContext* context, const InputMessage* request,
56                         OutputMessage* result,
57                         std::function<void(Status)> on_completion) {
58     CompletionQueue* cq = channel->CallbackCQ();
59     GPR_CODEGEN_ASSERT(cq != nullptr);
60     Call call(channel->CreateCall(method, context, cq));
61 
62     using FullCallOpSet =
63         CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage,
64                   CallOpRecvInitialMetadata, CallOpRecvMessage<OutputMessage>,
65                   CallOpClientSendClose, CallOpClientRecvStatus>;
66 
67     auto* ops = new (g_core_codegen_interface->grpc_call_arena_alloc(
68         call.call(), sizeof(FullCallOpSet))) FullCallOpSet;
69 
70     auto* tag = new (g_core_codegen_interface->grpc_call_arena_alloc(
71         call.call(), sizeof(CallbackWithStatusTag)))
72         CallbackWithStatusTag(call.call(), on_completion, ops);
73 
74     // TODO(vjpai): Unify code with sync API as much as possible
75     Status s = ops->SendMessage(*request);
76     if (!s.ok()) {
77       tag->force_run(s);
78       return;
79     }
80     ops->SendInitialMetadata(context->send_initial_metadata_,
81                              context->initial_metadata_flags());
82     ops->RecvInitialMetadata(context);
83     ops->RecvMessage(result);
84     ops->AllowNoMessage();
85     ops->ClientSendClose();
86     ops->ClientRecvStatus(context, tag->status_ptr());
87     ops->set_cq_tag(tag);
88     call.PerformOps(ops);
89   }
90 };
91 
92 }  // namespace internal
93 }  // namespace grpc
94 
95 #endif  // GRPCPP_IMPL_CODEGEN_CLIENT_CALLBACK_H
96