GRPC C++  1.4.0
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
async_unary_call.h
Go to the documentation of this file.
1 /*
2  *
3  * Copyright 2015, Google Inc.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are
8  * met:
9  *
10  * * Redistributions of source code must retain the above copyright
11  * notice, this list of conditions and the following disclaimer.
12  * * Redistributions in binary form must reproduce the above
13  * copyright notice, this list of conditions and the following disclaimer
14  * in the documentation and/or other materials provided with the
15  * distribution.
16  * * Neither the name of Google Inc. nor the names of its
17  * contributors may be used to endorse or promote products derived from
18  * this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  *
32  */
33 
34 #ifndef GRPCXX_IMPL_CODEGEN_ASYNC_UNARY_CALL_H
35 #define GRPCXX_IMPL_CODEGEN_ASYNC_UNARY_CALL_H
36 
37 #include <assert.h>
44 
45 namespace grpc {
46 
47 class CompletionQueue;
48 extern CoreCodegenInterface* g_core_codegen_interface;
49 
52 template <class R>
54  public:
56 
63  virtual void ReadInitialMetadata(void* tag) = 0;
64 
79  virtual void Finish(R* msg, Status* status, void* tag) = 0;
80 };
81 
84 template <class R>
87  public:
93  template <class W>
95  CompletionQueue* cq,
96  const RpcMethod& method,
97  ClientContext* context,
98  const W& request) {
99  Call call = channel->CreateCall(method, context, cq);
101  call.call(), sizeof(ClientAsyncResponseReader)))
102  ClientAsyncResponseReader(call, context, request);
103  }
104 
105  // always allocated against a call arena, no memory free required
106  static void operator delete(void* ptr, std::size_t size) {
107  assert(size == sizeof(ClientAsyncResponseReader));
108  }
109 
116  void ReadInitialMetadata(void* tag) {
117  GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_);
118 
119  meta_buf_.set_output_tag(tag);
120  meta_buf_.RecvInitialMetadata(context_);
121  call_.PerformOps(&meta_buf_);
122  }
123 
129  void Finish(R* msg, Status* status, void* tag) {
130  finish_buf_.set_output_tag(tag);
131  if (!context_->initial_metadata_received_) {
132  finish_buf_.RecvInitialMetadata(context_);
133  }
134  finish_buf_.RecvMessage(msg);
135  finish_buf_.AllowNoMessage();
136  finish_buf_.ClientRecvStatus(context_, status);
137  call_.PerformOps(&finish_buf_);
138  }
139 
140  private:
141  ClientContext* const context_;
142  Call call_;
143 
144  template <class W>
145  ClientAsyncResponseReader(Call call, ClientContext* context, const W& request)
146  : context_(context), call_(call) {
147  init_buf_.SendInitialMetadata(context->send_initial_metadata_,
148  context->initial_metadata_flags());
149  // TODO(ctiller): don't assert
150  GPR_CODEGEN_ASSERT(init_buf_.SendMessage(request).ok());
151  init_buf_.ClientSendClose();
152  call_.PerformOps(&init_buf_);
153  }
154 
155  // disable operator new
156  static void* operator new(std::size_t size);
157  static void* operator new(std::size_t size, void* p) { return p; };
158 
159  SneakyCallOpSet<CallOpSendInitialMetadata, CallOpSendMessage,
160  CallOpClientSendClose>
161  init_buf_;
162  CallOpSet<CallOpRecvInitialMetadata> meta_buf_;
163  CallOpSet<CallOpRecvInitialMetadata, CallOpRecvMessage<R>,
164  CallOpClientRecvStatus>
165  finish_buf_;
166 };
167 
170 template <class W>
172  public:
174  : call_(nullptr, nullptr, nullptr), ctx_(ctx) {}
175 
183  void SendInitialMetadata(void* tag) override {
184  GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_);
185 
186  meta_buf_.set_output_tag(tag);
187  meta_buf_.SendInitialMetadata(ctx_->initial_metadata_,
188  ctx_->initial_metadata_flags());
189  if (ctx_->compression_level_set()) {
190  meta_buf_.set_compression_level(ctx_->compression_level());
191  }
192  ctx_->sent_initial_metadata_ = true;
193  call_.PerformOps(&meta_buf_);
194  }
195 
211  void Finish(const W& msg, const Status& status, void* tag) {
212  finish_buf_.set_output_tag(tag);
213  if (!ctx_->sent_initial_metadata_) {
214  finish_buf_.SendInitialMetadata(ctx_->initial_metadata_,
215  ctx_->initial_metadata_flags());
216  if (ctx_->compression_level_set()) {
217  finish_buf_.set_compression_level(ctx_->compression_level());
218  }
219  ctx_->sent_initial_metadata_ = true;
220  }
221  // The response is dropped if the status is not OK.
222  if (status.ok()) {
223  finish_buf_.ServerSendStatus(ctx_->trailing_metadata_,
224  finish_buf_.SendMessage(msg));
225  } else {
226  finish_buf_.ServerSendStatus(ctx_->trailing_metadata_, status);
227  }
228  call_.PerformOps(&finish_buf_);
229  }
230 
243  void FinishWithError(const Status& status, void* tag) {
244  GPR_CODEGEN_ASSERT(!status.ok());
245  finish_buf_.set_output_tag(tag);
246  if (!ctx_->sent_initial_metadata_) {
247  finish_buf_.SendInitialMetadata(ctx_->initial_metadata_,
248  ctx_->initial_metadata_flags());
249  if (ctx_->compression_level_set()) {
250  finish_buf_.set_compression_level(ctx_->compression_level());
251  }
252  ctx_->sent_initial_metadata_ = true;
253  }
254  finish_buf_.ServerSendStatus(ctx_->trailing_metadata_, status);
255  call_.PerformOps(&finish_buf_);
256  }
257 
258  private:
259  void BindCall(Call* call) override { call_ = *call; }
260 
261  Call call_;
262  ServerContext* ctx_;
263  CallOpSet<CallOpSendInitialMetadata> meta_buf_;
264  CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage,
265  CallOpServerSendStatus>
266  finish_buf_;
267 };
268 
269 } // namespace grpc
270 
271 namespace std {
272 template <class R>
273 class default_delete<grpc::ClientAsyncResponseReader<R>> {
274  public:
275  void operator()(void* p) {}
276 };
277 }
278 
279 #endif // GRPCXX_IMPL_CODEGEN_ASYNC_UNARY_CALL_H
void FinishWithError(const Status &status, void *tag)
Indicate that the stream is to be finished with a non-OK status, and request notification for when th...
Definition: async_unary_call.h:243
virtual ~ClientAsyncResponseReaderInterface()
Definition: async_unary_call.h:55
grpc_compression_level compression_level() const
Return the compression algorithm to be used by the server call.
Definition: server_context.h:184
virtual void Finish(R *msg, Status *status, void *tag)=0
Request to receive the server's response msg and final status for the call, and to notify tag on this...
void Finish(const W &msg, const Status &status, void *tag)
Indicate that the stream is to be finished and request notification when the server has sent the appr...
Definition: async_unary_call.h:211
#define GPR_CODEGEN_ASSERT(x)
Codegen specific version of GPR_ASSERT.
Definition: core_codegen_interface.h:137
Definition: service_type.h:53
void Finish(R *msg, Status *status, void *tag)
See ClientAysncResponseReaderInterface::Finish for semantics.
Definition: async_unary_call.h:129
virtual void ReadInitialMetadata(void *tag)=0
Request notification of the reading of initial metadata.
static ClientAsyncResponseReader * Create(ChannelInterface *channel, CompletionQueue *cq, const RpcMethod &method, ClientContext *context, const W &request)
Start a call and write the request out.
Definition: async_unary_call.h:94
Async API for client-side unary RPCs, where the message response received from the server is of type ...
Definition: async_unary_call.h:85
A ClientContext allows the person implementing a service client to:
Definition: client_context.h:168
void operator()(void *p)
Definition: async_unary_call.h:275
void SendInitialMetadata(void *tag) override
See ServerAsyncStreamingInterface::SendInitialMetadata for semantics.
Definition: async_unary_call.h:183
void ReadInitialMetadata(void *tag)
See ClientAsyncResponseReaderInterface::ReadInitialMetadata for semantics.
Definition: async_unary_call.h:116
An interface relevant for async client side unary RPCS (which send one request message to a server an...
Definition: async_unary_call.h:53
Straightforward wrapping of the C call object.
Definition: call.h:638
Codegen interface for grpc::Channel.
Definition: channel_interface.h:64
CoreCodegenInterface * g_core_codegen_interface
Definition: call.h:64
A ServerContext allows the person implementing a service handler to:
Definition: server_context.h:109
A thin wrapper around grpc_completion_queue (see src/core/lib/surface/completion_queue.h).
Definition: completion_queue.h:101
virtual void * grpc_call_arena_alloc(grpc_call *call, size_t length)=0
ServerAsyncResponseWriter(ServerContext *ctx)
Definition: async_unary_call.h:173
Descriptor of an RPC method.
Definition: rpc_method.h:44
void PerformOps(CallOpSetInterface *ops)
Definition: call.h:654
bool ok() const
Is the status OK?
Definition: status.h:76
Did it work? If it didn't, why?
Definition: status.h:45
Async server-side API for handling unary calls, where the single response message sent to the client ...
Definition: async_unary_call.h:171
grpc_call * call() const
Definition: call.h:658
bool compression_level_set() const
Return a bool indicating whether the compression level for this call has been set (either implicitly ...
Definition: server_context.h:199