diff --git a/include/mp/proxy-io.h b/include/mp/proxy-io.h index 29cd3a45..9b3c876f 100644 --- a/include/mp/proxy-io.h +++ b/include/mp/proxy-io.h @@ -382,7 +382,7 @@ ProxyClientBase::ProxyClientBase(typename Interface::Client cli auto cleanup = m_context.connection->addSyncCleanup([this]() { // Release client capability by move-assigning to temporary. { - typename Interface::Client(std::move(self().m_client)); + typename Interface::Client(std::move(m_client)); } { std::unique_lock lock(m_context.connection->m_loop.m_mutex); @@ -412,13 +412,13 @@ ProxyClientBase::ProxyClientBase(typename Interface::Client cli // the remote object, waiting for it to be deleted server side. If the // capnp interface does not define a destroy method, this will just call // an empty stub defined in the ProxyClientBase class and do nothing. - self().destroy(); + Sub::destroy(*this); // FIXME: Could just invoke removed addCleanup fn here instead of duplicating code m_context.connection->m_loop.sync([&]() { // Release client capability by move-assigning to temporary. { - typename Interface::Client(std::move(self().m_client)); + typename Interface::Client(std::move(m_client)); } { std::unique_lock lock(m_context.connection->m_loop.m_mutex); @@ -432,6 +432,7 @@ ProxyClientBase::ProxyClientBase(typename Interface::Client cli }); } }); + Sub::construct(*this); } template diff --git a/include/mp/proxy.h b/include/mp/proxy.h index 1ee1c753..e1933b9c 100644 --- a/include/mp/proxy.h +++ b/include/mp/proxy.h @@ -56,6 +56,8 @@ class ProxyClientBase : public Impl_ public: using Interface = Interface_; using Impl = Impl_; + using Sub = ProxyClient; + using Super = ProxyClientBase; ProxyClientBase(typename Interface::Client client, Connection* connection, bool destroy_connection); ~ProxyClientBase() noexcept; @@ -89,10 +91,8 @@ class ProxyClientBase : public Impl_ // then it will also ensure that the destructor runs on the same thread the // client used to make other RPC calls, instead of running on the server // EventLoop thread and possibly blocking it. - void construct() {} - void destroy() {} - - ProxyClient& self() { return static_cast&>(*this); } + static void construct(Super&) {} + static void destroy(Super&) {} typename Interface::Client m_client; ProxyContext m_context; diff --git a/src/mp/gen.cpp b/src/mp/gen.cpp index 007d2362..93b001f6 100644 --- a/src/mp/gen.cpp +++ b/src/mp/gen.cpp @@ -357,8 +357,7 @@ void Generate(kj::StringPtr src_prefix, client << "public ProxyClientCustom<" << message_namespace << "::" << node_name << ", " << proxied_class_type << ">\n{\n"; client << "public:\n"; - client << " template \n"; - client << " ProxyClient(Args&&... args) : ProxyClientCustom(std::forward(args)...) { construct(); }\n"; + client << " using ProxyClientCustom::ProxyClientCustom;\n"; client << " ~ProxyClient();\n"; std::ostringstream server; @@ -531,18 +530,22 @@ void Generate(kj::StringPtr src_prefix, server_invoke_end << ")"; } + std::string static_str{is_construct || is_destroy ? "static " : ""}; + std::string super_str{is_construct || is_destroy ? "Super& super" : ""}; + std::string self_str{is_construct || is_destroy ? "super" : "*this"}; + client << " using M" << method_ordinal << " = ProxyClientMethodTraits<" << method_prefix << "Params>;\n"; - client << " typename M" << method_ordinal << "::Result " << method_name << "(" - << client_args.str() << ")"; + client << " " << static_str << "typename M" << method_ordinal << "::Result " << method_name << "(" + << super_str << client_args.str() << ")"; client << ";\n"; def_client << "ProxyClient<" << message_namespace << "::" << node_name << ">::M" << method_ordinal << "::Result ProxyClient<" << message_namespace << "::" << node_name << ">::" << method_name - << "(" << client_args.str() << ") {\n"; + << "(" << super_str << client_args.str() << ") {\n"; if (has_result) { def_client << " typename M" << method_ordinal << "::Result result;\n"; } - def_client << " clientInvoke(*this, &" << message_namespace << "::" << node_name + def_client << " clientInvoke(" << self_str << ", &" << message_namespace << "::" << node_name << "::Client::" << method_name << "Request" << client_invoke.str() << ");\n"; if (has_result) def_client << " return result;\n"; def_client << "}\n";