@@ -60,8 +60,35 @@ class ProxyClientBase : public Impl_
6060 ProxyClientBase (typename Interface::Client client, Connection* connection, bool destroy_connection);
6161 ~ProxyClientBase () noexcept ;
6262
63- // Methods called during client construction/destruction that can optionally
64- // be defined in capnp interface to trigger the server.
63+ // construct/destroy methods called during client construction/destruction
64+ // that can optionally be defined in capnp interfaces to invoke code on the
65+ // server when proxy client objects are created and destroyed.
66+ //
67+ // The construct() method is not generally very useful, but can be used to
68+ // run custom code on the server automatically when a ProxyClient client is
69+ // constructed. The only current use is adding a construct method to Init
70+ // interfaces that is called automatically on construction, so client and
71+ // server exchange ThreadMap references and set Connection::m_thread_map
72+ // values as soon as the Init client is created.
73+ //
74+ // construct @0 (threadMap: Proxy.ThreadMap) -> (threadMap: Proxy.ThreadMap);
75+ //
76+ // But construct() is not necessary for this, thread maps could be passed
77+ // through a normal method that is just called explicitly rather than
78+ // implicitly.
79+ //
80+ // The destroy() method is more generally useful than construct(), because
81+ // it ensures that the server object will be destroyed synchronously before
82+ // the client destructor returns, instead of asynchronously at some
83+ // unpredictable time after the client object is already destroyed and
84+ // client code has moved on. If the destroy method accepts a Context
85+ // parameter like:
86+ //
87+ // destroy @0 (context: Proxy.Context) -> ();
88+ //
89+ // then it will also ensure that the destructor runs on the same thread the
90+ // client used to make other RPC calls, instead of running on the server
91+ // EventLoop thread and possibly blocking it.
6592 void construct () {}
6693 void destroy () {}
6794
@@ -109,20 +136,52 @@ struct ProxyServerBase : public virtual Interface_::Server
109136 ProxyContext m_context;
110137};
111138
112- // ! Customizable (through template specialization) base class used in generated ProxyServer implementations from
113- // ! proxy-codegen.cpp.
139+ // ! Customizable (through template specialization) base class which ProxyServer
140+ // ! classes produced by generated code will inherit from. The default
141+ // ! specialization of this class just inherits from ProxyServerBase, but custom
142+ // ! specializations can be defined to control ProxyServer behavior.
143+ // !
144+ // ! Specifically, it can be useful to specialize this class to add additional
145+ // ! state to ProxyServer classes, for example to cache state between IPC calls.
146+ // ! If this is done, however, care should be taken to ensure that the extra
147+ // ! state can be destroyed without blocking, because ProxyServer destructors are
148+ // ! called from the EventLoop thread, and if they block, it could deadlock the
149+ // ! program. One way to do avoid blocking is to clean up the state by pushing
150+ // ! cleanup callbacks to the m_context.cleanup list, which run after the server
151+ // ! m_impl object is destroyed on the same thread destroying it (which will
152+ // ! either be an IPC worker thread if the ProxyServer is being explicitly
153+ // ! destroyed by a client calling a destroy() method with a Context argument and
154+ // ! Context.thread value set, or the temporary EventLoop::m_async_thread used to
155+ // ! run destructors without blocking the event loop when no-longer used server
156+ // ! objects are garbage collected by Cap'n Proto.) Alternately, if cleanup needs
157+ // ! to run before m_impl is destroyed, the specialization can override
158+ // ! invokeDestroy and destructor methods to do that.
114159template <typename Interface, typename Impl>
115160struct ProxyServerCustom : public ProxyServerBase <Interface, Impl>
116161{
117162 using ProxyServerBase<Interface, Impl>::ProxyServerBase;
118163};
119164
120- // ! Function traits class used to get method parameter and result types in generated ProxyClient implementations from
121- // ! proxy-codegen.cpp.
165+ // ! Function traits class used to get method parameter and result types, used in
166+ // ! generated ProxyClient and ProxyServer classes produced by gen.cpp to get C++
167+ // ! method type information. The generated code accesses these traits via
168+ // ! intermediate ProxyClientMethodTraits and ProxyServerMethodTraits classes,
169+ // ! which it is possible to specialize to change the way method arguments and
170+ // ! return values are handled.
171+ // !
172+ // ! Fields of the trait class are:
173+ // !
174+ // ! Params - TypeList of C++ ClassName::methodName parameter types
175+ // ! Result - Return type of ClassName::method
176+ // ! Param<N> - helper to access individual parameters by index number.
177+ // ! Fields - helper alias that appends Result type to the Params typelist if
178+ // ! it not void.
122179template <class Fn >
123180struct FunctionTraits ;
124181
125- // ! Specialization of above to extract result and params types.
182+ // ! Specialization of above extracting result and params types assuming the
183+ // ! template argument is a pointer-to-method type,
184+ // ! decltype(&ClassName::methodName)
126185template <class _Class , class _Result , class ... _Params>
127186struct FunctionTraits <_Result (_Class::*const )(_Params...)>
128187{
@@ -134,16 +193,20 @@ struct FunctionTraits<_Result (_Class::*const)(_Params...)>
134193 typename std::conditional<std::is_same<void , Result>::value, Params, TypeList<_Params..., _Result>>::type;
135194};
136195
137- // ! Traits class for a method specialized by method parameters.
138- // !
139- // ! Param and Result typedefs can be customized to adjust parameter and return types on client side.
196+ // ! Traits class for a proxy method, providing the same
197+ // ! Params/Result/Param/Fields described in the FunctionTraits class above, plus
198+ // ! an additional invoke() method that calls the C++ method which is being
199+ // ! proxied, forwarding any arguments.
140200// !
141- // ! Invoke method customized to adjust parameter and return types on server side.
201+ // ! The template argument should be the InterfaceName::MethodNameParams class
202+ // ! (generated by Cap'n Proto) associated with the method.
142203// !
143- // ! Normal method calls go through the ProxyMethodTraits struct specialization
144- // ! below, not this default struct, which is only used if there is no
145- // ! ProxyMethod::impl method pointer, which is only true for construct/destroy
146- // ! methods.
204+ // ! Note: The class definition here is just the fallback definition used when
205+ // ! the other specialization below doesn't match. The fallback is only used for
206+ // ! capnp methods which do not have corresponding C++ methods, which in practice
207+ // ! is just the two special construct() and destroy() methods described in \ref
208+ // ! ProxyClientBase. These methods don't have any C++ parameters or return
209+ // ! types, so the trait information below reflects that.
147210template <typename MethodParams, typename Enable = void >
148211struct ProxyMethodTraits
149212{
@@ -157,7 +220,18 @@ struct ProxyMethodTraits
157220 }
158221};
159222
160- // ! Specialization of above.
223+ // ! Specialization of above for proxy methods that have a
224+ // ! ProxyMethod<InterfaceName::MethodNameParams>::impl pointer-to-method
225+ // ! constant defined by generated code. This includes all functions defined in
226+ // ! the capnp interface except any construct() or destroy() methods, that are
227+ // ! assumed not to correspond to real member functions in the C++ class, and
228+ // ! will use the fallback traits definition above. The generated code this
229+ // ! specialization relies on looks like:
230+ // !
231+ // ! struct ProxyMethod<InterfaceName::MethodNameParams>
232+ // ! {
233+ // ! static constexpr auto impl = &ClassName::methodName;
234+ // ! };
161235template <typename MethodParams>
162236struct ProxyMethodTraits <MethodParams, Require<decltype (ProxyMethod<MethodParams>::impl)>>
163237 : public FunctionTraits<decltype (ProxyMethod<MethodParams>::impl)>
0 commit comments