aboutsummaryrefslogtreecommitdiffhomepage
path: root/include/grpc++/impl/codegen/async_unary_call.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/grpc++/impl/codegen/async_unary_call.h')
-rw-r--r--include/grpc++/impl/codegen/async_unary_call.h41
1 files changed, 31 insertions, 10 deletions
diff --git a/include/grpc++/impl/codegen/async_unary_call.h b/include/grpc++/impl/codegen/async_unary_call.h
index f0f909686b..e472f04f56 100644
--- a/include/grpc++/impl/codegen/async_unary_call.h
+++ b/include/grpc++/impl/codegen/async_unary_call.h
@@ -32,13 +32,18 @@ namespace grpc {
class CompletionQueue;
extern CoreCodegenInterface* g_core_codegen_interface;
-/// An interface relevant for async client side unary RPCS (which send
+/// An interface relevant for async client side unary RPCs (which send
/// one request message to a server and receive one response message).
template <class R>
class ClientAsyncResponseReaderInterface {
public:
virtual ~ClientAsyncResponseReaderInterface() {}
+ /// Start the call that was set up by the constructor, but only if the
+ /// constructor was invoked through the "Prepare" API which doesn't actually
+ /// start the call
+ virtual void StartCall() = 0;
+
/// Request notification of the reading of initial metadata. Completion
/// will be notified by \a tag on the associated completion queue.
/// This call is optional, but if it is used, it cannot be used concurrently
@@ -70,9 +75,10 @@ template <class R>
class ClientAsyncResponseReader final
: public ClientAsyncResponseReaderInterface<R> {
public:
- /// Start a call and write the request out.
+ /// Start a call and write the request out if \a start is set.
/// \a tag will be notified on \a cq when the call has been started (i.e.
/// intitial metadata sent) and \a request has been written out.
+ /// If \a start is not set, the actual call must be initiated by StartCall
/// Note that \a context will be used to fill in custom initial metadata
/// used to send to the server when starting the call.
template <class W>
@@ -80,11 +86,11 @@ class ClientAsyncResponseReader final
CompletionQueue* cq,
const RpcMethod& method,
ClientContext* context,
- const W& request) {
+ const W& request, bool start) {
Call call = channel->CreateCall(method, context, cq);
return new (g_core_codegen_interface->grpc_call_arena_alloc(
call.call(), sizeof(ClientAsyncResponseReader)))
- ClientAsyncResponseReader(call, context, request);
+ ClientAsyncResponseReader(call, context, request, start);
}
// always allocated against a call arena, no memory free required
@@ -92,13 +98,20 @@ class ClientAsyncResponseReader final
assert(size == sizeof(ClientAsyncResponseReader));
}
+ void StartCall() override {
+ assert(!started_);
+ started_ = true;
+ StartCallInternal();
+ }
+
/// See \a ClientAsyncResponseReaderInterface::ReadInitialMetadata for
/// semantics.
///
/// Side effect:
/// - the \a ClientContext associated with this call is updated with
/// possible initial and trailing metadata sent from the server.
- void ReadInitialMetadata(void* tag) {
+ void ReadInitialMetadata(void* tag) override {
+ assert(started_);
GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_);
meta_buf.set_output_tag(tag);
@@ -111,7 +124,8 @@ class ClientAsyncResponseReader final
/// Side effect:
/// - the \a ClientContext associated with this call is updated with
/// possible initial and trailing metadata sent from the server.
- void Finish(R* msg, Status* status, void* tag) {
+ void Finish(R* msg, Status* status, void* tag) override {
+ assert(started_);
finish_buf.set_output_tag(tag);
if (!context_->initial_metadata_received_) {
finish_buf.RecvInitialMetadata(context_);
@@ -125,15 +139,22 @@ class ClientAsyncResponseReader final
private:
ClientContext* const context_;
Call call_;
+ bool started_;
template <class W>
- ClientAsyncResponseReader(Call call, ClientContext* context, const W& request)
- : context_(context), call_(call) {
- init_buf.SendInitialMetadata(context->send_initial_metadata_,
- context->initial_metadata_flags());
+ ClientAsyncResponseReader(Call call, ClientContext* context, const W& request,
+ bool start)
+ : context_(context), call_(call), started_(start) {
+ // Bind the metadata at time of StartCallInternal but set up the rest here
// TODO(ctiller): don't assert
GPR_CODEGEN_ASSERT(init_buf.SendMessage(request).ok());
init_buf.ClientSendClose();
+ if (start) StartCallInternal();
+ }
+
+ void StartCallInternal() {
+ init_buf.SendInitialMetadata(context_->send_initial_metadata_,
+ context_->initial_metadata_flags());
call_.PerformOps(&init_buf);
}