aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/compiler/cpp_generator.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler/cpp_generator.cc')
-rw-r--r--src/compiler/cpp_generator.cc352
1 files changed, 345 insertions, 7 deletions
diff --git a/src/compiler/cpp_generator.cc b/src/compiler/cpp_generator.cc
index 1e0c36451b..7986aca696 100644
--- a/src/compiler/cpp_generator.cc
+++ b/src/compiler/cpp_generator.cc
@@ -128,12 +128,14 @@ grpc::string GetHeaderIncludes(grpc_generator::File* file,
"");
}
static const char* headers_strs[] = {
+ "functional",
"grpcpp/impl/codegen/async_generic_service.h",
"grpcpp/impl/codegen/async_stream.h",
"grpcpp/impl/codegen/async_unary_call.h",
"grpcpp/impl/codegen/method_handler_impl.h",
"grpcpp/impl/codegen/proto_utils.h",
"grpcpp/impl/codegen/rpc_method.h",
+ "grpcpp/impl/codegen/server_callback.h",
"grpcpp/impl/codegen/service_type.h",
"grpcpp/impl/codegen/status.h",
"grpcpp/impl/codegen/stub_options.h",
@@ -547,6 +549,116 @@ void PrintHeaderClientMethod(grpc_generator::Printer* printer,
}
}
+void PrintHeaderClientMethodCallbackInterfacesStart(
+ grpc_generator::Printer* printer,
+ std::map<grpc::string, grpc::string>* vars) {
+ // This declares the interface for the callback-based API. The components
+ // are pure; even though this is new (post-1.0) API, it can be pure because
+ // it is an entirely new interface that happens to be scoped within
+ // StubInterface, not new additions to StubInterface itself
+ printer->Print("class experimental_async_interface {\n");
+ // All methods in this new interface are public. There is no need for private
+ // "Raw" methods since the callback-based API returns unowned raw pointers
+ printer->Print(" public:\n");
+ printer->Indent();
+ printer->Print("virtual ~experimental_async_interface() {}\n");
+}
+
+void PrintHeaderClientMethodCallbackInterfaces(
+ grpc_generator::Printer* printer, const grpc_generator::Method* method,
+ std::map<grpc::string, grpc::string>* vars, bool is_public) {
+ // Reserve is_public for future expansion
+ assert(is_public);
+
+ (*vars)["Method"] = method->name();
+ (*vars)["Request"] = method->input_type_name();
+ (*vars)["Response"] = method->output_type_name();
+
+ if (method->NoStreaming()) {
+ printer->Print(*vars,
+ "virtual void $Method$(::grpc::ClientContext* context, "
+ "const $Request$* request, $Response$* response, "
+ "std::function<void(::grpc::Status)>) = 0;\n");
+ } else if (ClientOnlyStreaming(method)) {
+ // TODO(vjpai): Add support for client-side streaming
+ } else if (ServerOnlyStreaming(method)) {
+ // TODO(vjpai): Add support for server-side streaming
+ } else if (method->BidiStreaming()) {
+ // TODO(vjpai): Add support for bidi streaming
+ }
+}
+
+void PrintHeaderClientMethodCallbackInterfacesEnd(
+ grpc_generator::Printer* printer,
+ std::map<grpc::string, grpc::string>* vars) {
+ printer->Outdent();
+ printer->Print("};\n");
+
+ // Declare a function to give the async stub contents. It can't be pure
+ // since this is a new API in StubInterface, but it is meaningless by default
+ // (since any stub that wants to use it must have its own implementation of
+ // the callback functions therein), so make the default return value nullptr.
+ // Intentionally include the word "class" to avoid possible shadowing.
+ printer->Print(
+ "virtual class experimental_async_interface* experimental_async() { "
+ "return nullptr; }\n");
+}
+
+void PrintHeaderClientMethodCallbackStart(
+ grpc_generator::Printer* printer,
+ std::map<grpc::string, grpc::string>* vars) {
+ // This declares the stub entry for the callback-based API.
+ printer->Print("class experimental_async final :\n");
+ printer->Print(" public StubInterface::experimental_async_interface {\n");
+ printer->Print(" public:\n");
+ printer->Indent();
+}
+
+void PrintHeaderClientMethodCallback(grpc_generator::Printer* printer,
+ const grpc_generator::Method* method,
+ std::map<grpc::string, grpc::string>* vars,
+ bool is_public) {
+ // Reserve is_public for future expansion
+ assert(is_public);
+
+ (*vars)["Method"] = method->name();
+ (*vars)["Request"] = method->input_type_name();
+ (*vars)["Response"] = method->output_type_name();
+
+ if (method->NoStreaming()) {
+ printer->Print(*vars,
+ "void $Method$(::grpc::ClientContext* context, "
+ "const $Request$* request, $Response$* response, "
+ "std::function<void(::grpc::Status)>) override;\n");
+ } else if (ClientOnlyStreaming(method)) {
+ // TODO(vjpai): Add support for client-side streaming
+ } else if (ServerOnlyStreaming(method)) {
+ // TODO(vjpai): Add support for server-side streaming
+ } else if (method->BidiStreaming()) {
+ // TODO(vjpai): Add support for bidi streaming
+ }
+}
+
+void PrintHeaderClientMethodCallbackEnd(
+ grpc_generator::Printer* printer,
+ std::map<grpc::string, grpc::string>* vars) {
+ printer->Outdent();
+ printer->Print(" private:\n");
+ printer->Indent();
+ printer->Print("friend class Stub;\n");
+ printer->Print("explicit experimental_async(Stub* stub): stub_(stub) { }\n");
+ // include a function with a dummy use of stub_ to avoid an unused
+ // private member warning for service with no methods
+ printer->Print("Stub* stub() { return stub_; }\n");
+ printer->Print("Stub* stub_;\n");
+ printer->Outdent();
+ printer->Print("};\n");
+
+ printer->Print(
+ "class experimental_async_interface* experimental_async() override { "
+ "return &async_stub_; }\n");
+}
+
void PrintHeaderClientMethodData(grpc_generator::Printer* printer,
const grpc_generator::Method* method,
std::map<grpc::string, grpc::string>* vars) {
@@ -589,9 +701,9 @@ void PrintHeaderServerMethodSync(grpc_generator::Printer* printer,
printer->Print(method->GetTrailingComments("//").c_str());
}
-// Helper generator. Disabled the sync API for Request and Response, then adds
+// Helper generator. Disables the sync API for Request and Response, then adds
// in an async API for RealRequest and RealResponse types. This is to be used
-// to generate async and raw APIs.
+// to generate async and raw async APIs.
void PrintHeaderServerAsyncMethodsHelper(
grpc_generator::Printer* printer, const grpc_generator::Method* method,
std::map<grpc::string, grpc::string>* vars) {
@@ -718,6 +830,170 @@ void PrintHeaderServerMethodAsync(grpc_generator::Printer* printer,
printer->Print(*vars, "};\n");
}
+// Helper generator. Disables the sync API for Request and Response, then adds
+// in a callback API for RealRequest and RealResponse types. This is to be used
+// to generate callback and raw callback APIs.
+void PrintHeaderServerCallbackMethodsHelper(
+ grpc_generator::Printer* printer, const grpc_generator::Method* method,
+ std::map<grpc::string, grpc::string>* vars) {
+ if (method->NoStreaming()) {
+ printer->Print(
+ *vars,
+ "// disable synchronous version of this method\n"
+ "::grpc::Status $Method$("
+ "::grpc::ServerContext* context, const $Request$* request, "
+ "$Response$* response) override {\n"
+ " abort();\n"
+ " return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
+ "}\n");
+ printer->Print(
+ *vars,
+ "virtual void $Method$("
+ "::grpc::ServerContext* context, const $RealRequest$* request, "
+ "$RealResponse$* response, "
+ "::grpc::experimental::ServerCallbackRpcController* "
+ "controller) { controller->Finish(::grpc::Status("
+ "::grpc::StatusCode::UNIMPLEMENTED, \"\")); }\n");
+ } else if (ClientOnlyStreaming(method)) {
+ printer->Print(
+ *vars,
+ "// disable synchronous version of this method\n"
+ "::grpc::Status $Method$("
+ "::grpc::ServerContext* context, "
+ "::grpc::ServerReader< $Request$>* reader, "
+ "$Response$* response) override {\n"
+ " abort();\n"
+ " return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
+ "}\n");
+ } else if (ServerOnlyStreaming(method)) {
+ printer->Print(
+ *vars,
+ "// disable synchronous version of this method\n"
+ "::grpc::Status $Method$("
+ "::grpc::ServerContext* context, const $Request$* request, "
+ "::grpc::ServerWriter< $Response$>* writer) override "
+ "{\n"
+ " abort();\n"
+ " return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
+ "}\n");
+ } else if (method->BidiStreaming()) {
+ printer->Print(
+ *vars,
+ "// disable synchronous version of this method\n"
+ "::grpc::Status $Method$("
+ "::grpc::ServerContext* context, "
+ "::grpc::ServerReaderWriter< $Response$, $Request$>* stream) "
+ " override {\n"
+ " abort();\n"
+ " return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
+ "}\n");
+ }
+}
+
+void PrintHeaderServerMethodCallback(
+ grpc_generator::Printer* printer, const grpc_generator::Method* method,
+ std::map<grpc::string, grpc::string>* vars) {
+ (*vars)["Method"] = method->name();
+ // These will be disabled
+ (*vars)["Request"] = method->input_type_name();
+ (*vars)["Response"] = method->output_type_name();
+ // These will be used for the callback API
+ (*vars)["RealRequest"] = method->input_type_name();
+ (*vars)["RealResponse"] = method->output_type_name();
+ printer->Print(*vars, "template <class BaseClass>\n");
+ printer->Print(
+ *vars,
+ "class ExperimentalWithCallbackMethod_$Method$ : public BaseClass {\n");
+ printer->Print(
+ " private:\n"
+ " void BaseClassMustBeDerivedFromService(const Service *service) {}\n");
+ printer->Print(" public:\n");
+ printer->Indent();
+ printer->Print(*vars, "ExperimentalWithCallbackMethod_$Method$() {\n");
+ if (method->NoStreaming()) {
+ printer->Print(
+ *vars,
+ " ::grpc::Service::experimental().MarkMethodCallback($Idx$,\n"
+ " new ::grpc::internal::CallbackUnaryHandler< "
+ "ExperimentalWithCallbackMethod_$Method$<BaseClass>, $RealRequest$, "
+ "$RealResponse$>(\n"
+ " [this](::grpc::ServerContext* context,\n"
+ " const $RealRequest$* request,\n"
+ " $RealResponse$* response,\n"
+ " ::grpc::experimental::ServerCallbackRpcController* "
+ "controller) {\n"
+ " this->$"
+ "Method$(context, request, response, controller);\n"
+ " }, this));\n");
+ } else if (ClientOnlyStreaming(method)) {
+ // TODO(vjpai): Add in code generation for all streaming methods
+ } else if (ServerOnlyStreaming(method)) {
+ // TODO(vjpai): Add in code generation for all streaming methods
+ } else if (method->BidiStreaming()) {
+ // TODO(vjpai): Add in code generation for all streaming methods
+ }
+ printer->Print(*vars, "}\n");
+ printer->Print(*vars,
+ "~ExperimentalWithCallbackMethod_$Method$() override {\n"
+ " BaseClassMustBeDerivedFromService(this);\n"
+ "}\n");
+ PrintHeaderServerCallbackMethodsHelper(printer, method, vars);
+ printer->Outdent();
+ printer->Print(*vars, "};\n");
+}
+
+void PrintHeaderServerMethodRawCallback(
+ grpc_generator::Printer* printer, const grpc_generator::Method* method,
+ std::map<grpc::string, grpc::string>* vars) {
+ (*vars)["Method"] = method->name();
+ // These will be disabled
+ (*vars)["Request"] = method->input_type_name();
+ (*vars)["Response"] = method->output_type_name();
+ // These will be used for raw API
+ (*vars)["RealRequest"] = "::grpc::ByteBuffer";
+ (*vars)["RealResponse"] = "::grpc::ByteBuffer";
+ printer->Print(*vars, "template <class BaseClass>\n");
+ printer->Print(*vars,
+ "class ExperimentalWithRawCallbackMethod_$Method$ : public "
+ "BaseClass {\n");
+ printer->Print(
+ " private:\n"
+ " void BaseClassMustBeDerivedFromService(const Service *service) {}\n");
+ printer->Print(" public:\n");
+ printer->Indent();
+ printer->Print(*vars, "ExperimentalWithRawCallbackMethod_$Method$() {\n");
+ if (method->NoStreaming()) {
+ printer->Print(
+ *vars,
+ " ::grpc::Service::experimental().MarkMethodRawCallback($Idx$,\n"
+ " new ::grpc::internal::CallbackUnaryHandler< "
+ "ExperimentalWithRawCallbackMethod_$Method$<BaseClass>, $RealRequest$, "
+ "$RealResponse$>(\n"
+ " [this](::grpc::ServerContext* context,\n"
+ " const $RealRequest$* request,\n"
+ " $RealResponse$* response,\n"
+ " ::grpc::experimental::ServerCallbackRpcController* "
+ "controller) {\n"
+ " this->$"
+ "Method$(context, request, response, controller);\n"
+ " }, this));\n");
+ } else if (ClientOnlyStreaming(method)) {
+ // TODO(vjpai): Add in code generation for all streaming methods
+ } else if (ServerOnlyStreaming(method)) {
+ // TODO(vjpai): Add in code generation for all streaming methods
+ } else if (method->BidiStreaming()) {
+ // TODO(vjpai): Add in code generation for all streaming methods
+ }
+ printer->Print(*vars, "}\n");
+ printer->Print(*vars,
+ "~ExperimentalWithRawCallbackMethod_$Method$() override {\n"
+ " BaseClassMustBeDerivedFromService(this);\n"
+ "}\n");
+ PrintHeaderServerCallbackMethodsHelper(printer, method, vars);
+ printer->Outdent();
+ printer->Print(*vars, "};\n");
+}
+
void PrintHeaderServerMethodStreamedUnary(
grpc_generator::Printer* printer, const grpc_generator::Method* method,
std::map<grpc::string, grpc::string>* vars) {
@@ -951,6 +1227,14 @@ void PrintHeaderService(grpc_generator::Printer* printer,
true);
printer->Print(service->method(i)->GetTrailingComments("//").c_str());
}
+ PrintHeaderClientMethodCallbackInterfacesStart(printer, vars);
+ for (int i = 0; i < service->method_count(); ++i) {
+ printer->Print(service->method(i)->GetLeadingComments("//").c_str());
+ PrintHeaderClientMethodCallbackInterfaces(printer, service->method(i).get(),
+ vars, true);
+ printer->Print(service->method(i)->GetTrailingComments("//").c_str());
+ }
+ PrintHeaderClientMethodCallbackInterfacesEnd(printer, vars);
printer->Outdent();
printer->Print("private:\n");
printer->Indent();
@@ -970,10 +1254,17 @@ void PrintHeaderService(grpc_generator::Printer* printer,
for (int i = 0; i < service->method_count(); ++i) {
PrintHeaderClientMethod(printer, service->method(i).get(), vars, true);
}
+ PrintHeaderClientMethodCallbackStart(printer, vars);
+ for (int i = 0; i < service->method_count(); ++i) {
+ PrintHeaderClientMethodCallback(printer, service->method(i).get(), vars,
+ true);
+ }
+ PrintHeaderClientMethodCallbackEnd(printer, vars);
printer->Outdent();
printer->Print("\n private:\n");
printer->Indent();
printer->Print("std::shared_ptr< ::grpc::ChannelInterface> channel_;\n");
+ printer->Print("class experimental_async async_stub_{this};\n");
for (int i = 0; i < service->method_count(); ++i) {
PrintHeaderClientMethod(printer, service->method(i).get(), vars, false);
}
@@ -1011,7 +1302,7 @@ void PrintHeaderService(grpc_generator::Printer* printer,
printer->Print("typedef ");
for (int i = 0; i < service->method_count(); ++i) {
- (*vars)["method_name"] = service->method(i).get()->name();
+ (*vars)["method_name"] = service->method(i)->name();
printer->Print(*vars, "WithAsyncMethod_$method_name$<");
}
printer->Print("Service");
@@ -1020,6 +1311,24 @@ void PrintHeaderService(grpc_generator::Printer* printer,
}
printer->Print(" AsyncService;\n");
+ // Server side - Callback
+ for (int i = 0; i < service->method_count(); ++i) {
+ (*vars)["Idx"] = as_string(i);
+ PrintHeaderServerMethodCallback(printer, service->method(i).get(), vars);
+ }
+
+ printer->Print("typedef ");
+
+ for (int i = 0; i < service->method_count(); ++i) {
+ (*vars)["method_name"] = service->method(i)->name();
+ printer->Print(*vars, "ExperimentalWithCallbackMethod_$method_name$<");
+ }
+ printer->Print("Service");
+ for (int i = 0; i < service->method_count(); ++i) {
+ printer->Print(" >");
+ }
+ printer->Print(" ExperimentalCallbackService;\n");
+
// Server side - Generic
for (int i = 0; i < service->method_count(); ++i) {
(*vars)["Idx"] = as_string(i);
@@ -1032,6 +1341,12 @@ void PrintHeaderService(grpc_generator::Printer* printer,
PrintHeaderServerMethodRaw(printer, service->method(i).get(), vars);
}
+ // Server side - Raw Callback
+ for (int i = 0; i < service->method_count(); ++i) {
+ (*vars)["Idx"] = as_string(i);
+ PrintHeaderServerMethodRawCallback(printer, service->method(i).get(), vars);
+ }
+
// Server side - Streamed Unary
for (int i = 0; i < service->method_count(); ++i) {
(*vars)["Idx"] = as_string(i);
@@ -1041,7 +1356,7 @@ void PrintHeaderService(grpc_generator::Printer* printer,
printer->Print("typedef ");
for (int i = 0; i < service->method_count(); ++i) {
- (*vars)["method_name"] = service->method(i).get()->name();
+ (*vars)["method_name"] = service->method(i)->name();
if (service->method(i)->NoStreaming()) {
printer->Print(*vars, "WithStreamedUnaryMethod_$method_name$<");
}
@@ -1063,7 +1378,7 @@ void PrintHeaderService(grpc_generator::Printer* printer,
printer->Print("typedef ");
for (int i = 0; i < service->method_count(); ++i) {
- (*vars)["method_name"] = service->method(i).get()->name();
+ (*vars)["method_name"] = service->method(i)->name();
auto method = service->method(i);
if (ServerOnlyStreaming(method.get())) {
printer->Print(*vars, "WithSplitStreamingMethod_$method_name$<");
@@ -1081,7 +1396,7 @@ void PrintHeaderService(grpc_generator::Printer* printer,
// Server side - typedef for controlled both unary and server-side streaming
printer->Print("typedef ");
for (int i = 0; i < service->method_count(); ++i) {
- (*vars)["method_name"] = service->method(i).get()->name();
+ (*vars)["method_name"] = service->method(i)->name();
auto method = service->method(i);
if (ServerOnlyStreaming(method.get())) {
printer->Print(*vars, "WithSplitStreamingMethod_$method_name$<");
@@ -1199,12 +1514,15 @@ grpc::string GetSourceIncludes(grpc_generator::File* file,
std::map<grpc::string, grpc::string> vars;
static const char* headers_strs[] = {
+ "functional",
"grpcpp/impl/codegen/async_stream.h",
"grpcpp/impl/codegen/async_unary_call.h",
"grpcpp/impl/codegen/channel_interface.h",
"grpcpp/impl/codegen/client_unary_call.h",
+ "grpcpp/impl/codegen/client_callback.h",
"grpcpp/impl/codegen/method_handler_impl.h",
"grpcpp/impl/codegen/rpc_service_method.h",
+ "grpcpp/impl/codegen/server_callback.h",
"grpcpp/impl/codegen/service_type.h",
"grpcpp/impl/codegen/sync_stream.h"};
std::vector<grpc::string> headers(headers_strs, array_end(headers_strs));
@@ -1247,6 +1565,17 @@ void PrintSourceClientMethod(grpc_generator::Printer* printer,
" return ::grpc::internal::BlockingUnaryCall"
"(channel_.get(), rpcmethod_$Method$_, "
"context, request, response);\n}\n\n");
+
+ printer->Print(*vars,
+ "void $ns$$Service$::Stub::experimental_async::$Method$("
+ "::grpc::ClientContext* context, "
+ "const $Request$* request, $Response$* response, "
+ "std::function<void(::grpc::Status)> f) {\n");
+ printer->Print(*vars,
+ " return ::grpc::internal::CallbackUnaryCall"
+ "(stub_->channel_.get(), stub_->rpcmethod_$Method$_, "
+ "context, request, response, std::move(f));\n}\n\n");
+
for (auto async_prefix : async_prefixes) {
(*vars)["AsyncPrefix"] = async_prefix.prefix;
(*vars)["AsyncStart"] = async_prefix.start;
@@ -1277,6 +1606,9 @@ void PrintSourceClientMethod(grpc_generator::Printer* printer,
"rpcmethod_$Method$_, "
"context, response);\n"
"}\n\n");
+
+ // TODO(vjpai): Add callback version
+
for (auto async_prefix : async_prefixes) {
(*vars)["AsyncPrefix"] = async_prefix.prefix;
(*vars)["AsyncStart"] = async_prefix.start;
@@ -1308,6 +1640,9 @@ void PrintSourceClientMethod(grpc_generator::Printer* printer,
"rpcmethod_$Method$_, "
"context, request);\n"
"}\n\n");
+
+ // TODO(vjpai): Add callback version
+
for (auto async_prefix : async_prefixes) {
(*vars)["AsyncPrefix"] = async_prefix.prefix;
(*vars)["AsyncStart"] = async_prefix.start;
@@ -1339,6 +1674,9 @@ void PrintSourceClientMethod(grpc_generator::Printer* printer,
"rpcmethod_$Method$_, "
"context);\n"
"}\n\n");
+
+ // TODO(vjpai): Add callback version
+
for (auto async_prefix : async_prefixes) {
(*vars)["AsyncPrefix"] = async_prefix.prefix;
(*vars)["AsyncStart"] = async_prefix.start;
@@ -1429,7 +1767,7 @@ void PrintSourceService(grpc_generator::Printer* printer,
printer->Print(*vars,
"static const char* $prefix$$Service$_method_names[] = {\n");
for (int i = 0; i < service->method_count(); ++i) {
- (*vars)["Method"] = service->method(i).get()->name();
+ (*vars)["Method"] = service->method(i)->name();
printer->Print(*vars, " \"/$Package$$Service$/$Method$\",\n");
}
printer->Print(*vars, "};\n\n");