Click here to Skip to main content
15,895,084 members
Articles / Programming Languages / C++

RCF - Interprocess Communication for C++

Rate me:
Please Sign up or sign in to vote.
4.94/5 (147 votes)
25 Oct 2011CPOL20 min read 4.6M   8.4K   331  
A server/client IPC framework, using the C++ preprocessor as an IDL compiler.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
<title>RCF: ServerStub.hpp Source File</title>
<link href="doxygen.css" rel="stylesheet" type="text/css">
<link href="tabs.css" rel="stylesheet" type="text/css">
</head><body>
<!-- Generated by Doxygen 1.4.5 -->
<div class="tabs">
  <ul>
    <li><a href="main.html"><span>Main&nbsp;Page</span></a></li>
    <li><a href="annotated.html"><span>Data&nbsp;Structures</span></a></li>
    <li id="current"><a href="files.html"><span>Files</span></a></li>
    <li><a href="dirs.html"><span>Directories</span></a></li>
  </ul></div>
<div class="nav">
<a class="el" href="dir_G_3A_2FDevelopment_2Fbuild_2Fscripts_2Fwin_2FBuildRcf2_5FOutput_2FRCF_2D0_2E4_2Finclude_2F.html">include</a>&nbsp;&raquo&nbsp;<a class="el" href="dir_G_3A_2FDevelopment_2Fbuild_2Fscripts_2Fwin_2FBuildRcf2_5FOutput_2FRCF_2D0_2E4_2Finclude_2FRCF_2F.html">RCF</a></div>
<h1>ServerStub.hpp</h1><div class="fragment"><pre class="fragment"><a name="l00001"></a>00001 
<a name="l00002"></a>00002 <span class="comment">//*****************************************************************************</span>
<a name="l00003"></a>00003 <span class="comment">// RCF - Remote Call Framework</span>
<a name="l00004"></a>00004 <span class="comment">// Copyright (c) 2005. All rights reserved.</span>
<a name="l00005"></a>00005 <span class="comment">// Developed by Jarl Lindrud.</span>
<a name="l00006"></a>00006 <span class="comment">// Contact: jlindrud@hotmail.com .</span>
<a name="l00007"></a>00007 <span class="comment">//*****************************************************************************</span>
<a name="l00008"></a>00008 
<a name="l00009"></a>00009 <span class="preprocessor">#ifndef INCLUDE_RCF_SERVERSTUB_HPP</span>
<a name="l00010"></a>00010 <span class="preprocessor"></span><span class="preprocessor">#define INCLUDE_RCF_SERVERSTUB_HPP</span>
<a name="l00011"></a>00011 <span class="preprocessor"></span>
<a name="l00012"></a>00012 <span class="preprocessor">#include &lt;memory&gt;</span>
<a name="l00013"></a>00013 
<a name="l00014"></a>00014 <span class="preprocessor">#include &lt;boost/shared_ptr.hpp&gt;</span>
<a name="l00015"></a>00015 
<a name="l00016"></a>00016 <span class="preprocessor">#include &lt;RCF/GetInterfaceName.hpp&gt;</span>
<a name="l00017"></a>00017 <span class="preprocessor">#include &lt;RCF/SerializationProtocol.hpp&gt;</span>
<a name="l00018"></a>00018 <span class="preprocessor">#include &lt;RCF/Token.hpp&gt;</span>
<a name="l00019"></a>00019 
<a name="l00020"></a>00020 <span class="comment">// NB: occurrences of "interface" in this file have been replaced with "interface_", due to obscure bugs with Visual C++</span>
<a name="l00021"></a>00021 
<a name="l00022"></a>00022 <span class="keyword">namespace </span>RCF {
<a name="l00023"></a>00023 
<a name="l00024"></a>00024     <span class="keyword">class </span>Connection;
<a name="l00025"></a>00025 
<a name="l00026"></a>00026     <span class="keyword">template</span>&lt;<span class="keyword">typename</span> T&gt;
<a name="l00027"></a>00027     <span class="keyword">class </span>I_Deref
<a name="l00028"></a>00028     {
<a name="l00029"></a>00029     <span class="keyword">public</span>:
<a name="l00030"></a>00030         <span class="keyword">virtual</span> ~I_Deref() {}
<a name="l00031"></a>00031         <span class="keyword">virtual</span> T &amp;deref() = 0;
<a name="l00032"></a>00032     };
<a name="l00033"></a>00033 
<a name="l00034"></a>00034     <span class="keyword">template</span>&lt;<span class="keyword">typename</span> T&gt;
<a name="l00035"></a>00035     <span class="keyword">class </span>DerefPtr
<a name="l00036"></a>00036     {
<a name="l00037"></a>00037     <span class="keyword">public</span>:
<a name="l00038"></a>00038         <span class="keyword">typedef</span> boost::shared_ptr&lt; I_Deref&lt;T&gt; &gt; type;
<a name="l00039"></a>00039     };
<a name="l00040"></a>00040 
<a name="l00041"></a>00041     <span class="keyword">template</span>&lt;<span class="keyword">typename</span> T&gt;
<a name="l00042"></a>00042     <span class="keyword">class </span>DerefObj : <span class="keyword">public</span> I_Deref&lt;T&gt;
<a name="l00043"></a>00043     {
<a name="l00044"></a>00044     <span class="keyword">public</span>:
<a name="l00045"></a>00045         DerefObj(T &amp;t) : t(t) {}
<a name="l00046"></a>00046         T &amp;deref() { <span class="keywordflow">return</span> t; }
<a name="l00047"></a>00047     <span class="keyword">private</span>:
<a name="l00048"></a>00048         T &amp;t;
<a name="l00049"></a>00049     };
<a name="l00050"></a>00050 
<a name="l00051"></a>00051     <span class="keyword">template</span>&lt;<span class="keyword">typename</span> T&gt;
<a name="l00052"></a>00052     <span class="keyword">class </span>DerefSharedPtr : <span class="keyword">public</span> I_Deref&lt;T&gt;
<a name="l00053"></a>00053     {
<a name="l00054"></a>00054     <span class="keyword">public</span>:
<a name="l00055"></a>00055         DerefSharedPtr(boost::shared_ptr&lt;T&gt; ptr) : ptr(ptr) {}
<a name="l00056"></a>00056         T &amp;deref() { <span class="keywordflow">return</span> *ptr; }
<a name="l00057"></a>00057     <span class="keyword">private</span>:
<a name="l00058"></a>00058         boost::shared_ptr&lt;T&gt; ptr;
<a name="l00059"></a>00059     };
<a name="l00060"></a>00060 
<a name="l00061"></a>00061     <span class="keyword">template</span>&lt;<span class="keyword">typename</span> T&gt;
<a name="l00062"></a>00062     <span class="keyword">class </span>DerefWeakPtr : <span class="keyword">public</span> I_Deref&lt;T&gt;
<a name="l00063"></a>00063     {
<a name="l00064"></a>00064     <span class="keyword">public</span>:
<a name="l00065"></a>00065         DerefWeakPtr(boost::weak_ptr&lt;T&gt; weakPtr) : weakPtr(weakPtr) {}
<a name="l00066"></a>00066         T &amp;deref() 
<a name="l00067"></a>00067         {
<a name="l00068"></a>00068             boost::shared_ptr&lt;T&gt; ptr( weakPtr );
<a name="l00069"></a>00069             <span class="keywordflow">if</span> (ptr.get())
<a name="l00070"></a>00070             {
<a name="l00071"></a>00071                 <span class="keywordflow">return</span> *ptr;
<a name="l00072"></a>00072             }
<a name="l00073"></a>00073             RCF_THROW(Exception, <span class="stringliteral">"weak_ptr to server object failed to lock"</span>);
<a name="l00074"></a>00074         }
<a name="l00075"></a>00075     <span class="keyword">private</span>:
<a name="l00076"></a>00076         boost::weak_ptr&lt;T&gt; weakPtr;
<a name="l00077"></a>00077     };
<a name="l00078"></a>00078 
<a name="l00079"></a>00079     <span class="keyword">template</span>&lt;<span class="keyword">typename</span> T&gt;
<a name="l00080"></a>00080     <span class="keyword">class </span>DerefAutoPtr : <span class="keyword">public</span> I_Deref&lt;T&gt;
<a name="l00081"></a>00081     {
<a name="l00082"></a>00082     <span class="keyword">public</span>:
<a name="l00083"></a>00083         DerefAutoPtr(std::auto_ptr&lt;T&gt; ptr) : ptr(ptr) {}
<a name="l00084"></a>00084         T &amp;deref() { <span class="keywordflow">return</span> *ptr; }
<a name="l00085"></a>00085     <span class="keyword">private</span>:
<a name="l00086"></a>00086         std::auto_ptr&lt;T&gt; ptr;
<a name="l00087"></a>00087     };
<a name="l00088"></a>00088 
<a name="l00089"></a>00089     <span class="keyword">typedef</span> boost::function3&lt;void, int, SerializationProtocolIn &amp;, SerializationProtocolOut &amp;&gt; InvokeFunctor;
<a name="l00090"></a>00090 
<a name="l00091"></a>00091     <span class="keyword">typedef</span> std::map&lt;std::string,  InvokeFunctor&gt; InvokeFunctorMap;
<a name="l00092"></a>00092 
<a name="l00093"></a>00093     <span class="keyword">class </span>StubAccess
<a name="l00094"></a>00094     {
<a name="l00095"></a>00095     <span class="keyword">public</span>:
<a name="l00096"></a>00096 
<a name="l00097"></a>00097         <span class="keyword">template</span>&lt;<span class="keyword">typename</span> InterfaceT, <span class="keyword">typename</span> IdT, <span class="keyword">typename</span> ImplementationT&gt;
<a name="l00098"></a>00098         <span class="keywordtype">void</span> invoke(InterfaceT &amp;interface_, <span class="keyword">const</span> IdT &amp;<span class="keywordtype">id</span>, SerializationProtocolIn &amp;in, SerializationProtocolOut &amp;out, ImplementationT &amp;t)
<a name="l00099"></a>00099         {
<a name="l00100"></a>00100             interface_.invoke(<span class="keywordtype">id</span>, in, out, t);
<a name="l00101"></a>00101         }
<a name="l00102"></a>00102 
<a name="l00103"></a>00103         <span class="keyword">template</span>&lt;<span class="keyword">typename</span> InterfaceT, <span class="keyword">typename</span> DerefPtrT&gt;
<a name="l00104"></a>00104         <span class="keywordtype">void</span> registerInvokeFunctors(InterfaceT &amp;interface_, InvokeFunctorMap &amp;invokeFunctorMap, DerefPtrT derefPtr)
<a name="l00105"></a>00105         {
<a name="l00106"></a>00106             interface_.registerInvokeFunctors(invokeFunctorMap, derefPtr);
<a name="l00107"></a>00107         }
<a name="l00108"></a>00108 
<a name="l00109"></a>00109         <span class="keyword">template</span>&lt;<span class="keyword">typename</span> ParentInterfaceT, <span class="keyword">typename</span> InterfaceT, <span class="keyword">typename</span> DerefPtrT&gt;
<a name="l00110"></a>00110         <span class="keywordtype">void</span> registerParentInvokeFunctors(InterfaceT &amp;interface_, InvokeFunctorMap &amp;invokeFunctorMap, DerefPtrT derefPtr)
<a name="l00111"></a>00111         {
<a name="l00112"></a>00112             interface_.ParentInterfaceT::registerInvokeFunctors(invokeFunctorMap, derefPtr);
<a name="l00113"></a>00113         }
<a name="l00114"></a>00114     };
<a name="l00115"></a>00115 
<a name="l00116"></a>00116     <span class="keyword">template</span>&lt;<span class="keyword">typename</span> InterfaceT, <span class="keyword">typename</span> ImplementationT&gt;
<a name="l00117"></a>00117     <span class="keyword">inline</span> <span class="keywordtype">void</span> invoke(InterfaceT &amp;interface_, ImplementationT &amp;t, <span class="keywordtype">int</span> fnId, SerializationProtocolIn &amp;in, SerializationProtocolOut &amp;out)
<a name="l00118"></a>00118     {
<a name="l00119"></a>00119         <span class="keywordflow">switch</span> (fnId) {
<a name="l00120"></a>00120         <span class="keywordflow">case</span>  0: StubAccess().invoke(interface_, Meta::Int&lt; 0&gt;(), in, out, t); <span class="keywordflow">break</span>;
<a name="l00121"></a>00121         <span class="keywordflow">case</span>  1: StubAccess().invoke(interface_, Meta::Int&lt; 1&gt;(), in, out, t); <span class="keywordflow">break</span>;
<a name="l00122"></a>00122         <span class="keywordflow">case</span>  2: StubAccess().invoke(interface_, Meta::Int&lt; 2&gt;(), in, out, t); <span class="keywordflow">break</span>;
<a name="l00123"></a>00123         <span class="keywordflow">case</span>  3: StubAccess().invoke(interface_, Meta::Int&lt; 3&gt;(), in, out, t); <span class="keywordflow">break</span>;
<a name="l00124"></a>00124         <span class="keywordflow">case</span>  4: StubAccess().invoke(interface_, Meta::Int&lt; 4&gt;(), in, out, t); <span class="keywordflow">break</span>;
<a name="l00125"></a>00125         <span class="keywordflow">case</span>  5: StubAccess().invoke(interface_, Meta::Int&lt; 5&gt;(), in, out, t); <span class="keywordflow">break</span>;
<a name="l00126"></a>00126         <span class="keywordflow">case</span>  6: StubAccess().invoke(interface_, Meta::Int&lt; 6&gt;(), in, out, t); <span class="keywordflow">break</span>;
<a name="l00127"></a>00127         <span class="keywordflow">case</span>  7: StubAccess().invoke(interface_, Meta::Int&lt; 7&gt;(), in, out, t); <span class="keywordflow">break</span>;
<a name="l00128"></a>00128         <span class="keywordflow">case</span>  8: StubAccess().invoke(interface_, Meta::Int&lt; 8&gt;(), in, out, t); <span class="keywordflow">break</span>;
<a name="l00129"></a>00129         <span class="keywordflow">case</span>  9: StubAccess().invoke(interface_, Meta::Int&lt; 9&gt;(), in, out, t); <span class="keywordflow">break</span>;
<a name="l00130"></a>00130         <span class="keywordflow">case</span> 10: StubAccess().invoke(interface_, Meta::Int&lt;10&gt;(), in, out, t); <span class="keywordflow">break</span>;
<a name="l00131"></a>00131         <span class="keywordflow">case</span> 11: StubAccess().invoke(interface_, Meta::Int&lt;11&gt;(), in, out, t); <span class="keywordflow">break</span>;
<a name="l00132"></a>00132         <span class="keywordflow">case</span> 12: StubAccess().invoke(interface_, Meta::Int&lt;12&gt;(), in, out, t); <span class="keywordflow">break</span>;
<a name="l00133"></a>00133         <span class="keywordflow">case</span> 13: StubAccess().invoke(interface_, Meta::Int&lt;13&gt;(), in, out, t); <span class="keywordflow">break</span>;
<a name="l00134"></a>00134         <span class="keywordflow">case</span> 14: StubAccess().invoke(interface_, Meta::Int&lt;14&gt;(), in, out, t); <span class="keywordflow">break</span>;
<a name="l00135"></a>00135         <span class="keywordflow">case</span> 15: StubAccess().invoke(interface_, Meta::Int&lt;15&gt;(), in, out, t); <span class="keywordflow">break</span>;
<a name="l00136"></a>00136         <span class="keywordflow">case</span> 16: StubAccess().invoke(interface_, Meta::Int&lt;16&gt;(), in, out, t); <span class="keywordflow">break</span>;
<a name="l00137"></a>00137         <span class="keywordflow">case</span> 17: StubAccess().invoke(interface_, Meta::Int&lt;17&gt;(), in, out, t); <span class="keywordflow">break</span>;
<a name="l00138"></a>00138         <span class="keywordflow">case</span> 18: StubAccess().invoke(interface_, Meta::Int&lt;18&gt;(), in, out, t); <span class="keywordflow">break</span>;
<a name="l00139"></a>00139         <span class="keywordflow">case</span> 19: StubAccess().invoke(interface_, Meta::Int&lt;19&gt;(), in, out, t); <span class="keywordflow">break</span>;
<a name="l00140"></a>00140         <span class="keywordflow">case</span> 20: StubAccess().invoke(interface_, Meta::Int&lt;20&gt;(), in, out, t); <span class="keywordflow">break</span>;
<a name="l00141"></a>00141         <span class="keywordflow">case</span> 21: StubAccess().invoke(interface_, Meta::Int&lt;21&gt;(), in, out, t); <span class="keywordflow">break</span>;
<a name="l00142"></a>00142         <span class="keywordflow">case</span> 22: StubAccess().invoke(interface_, Meta::Int&lt;22&gt;(), in, out, t); <span class="keywordflow">break</span>;
<a name="l00143"></a>00143         <span class="keywordflow">case</span> 23: StubAccess().invoke(interface_, Meta::Int&lt;23&gt;(), in, out, t); <span class="keywordflow">break</span>;
<a name="l00144"></a>00144         <span class="keywordflow">case</span> 24: StubAccess().invoke(interface_, Meta::Int&lt;24&gt;(), in, out, t); <span class="keywordflow">break</span>;
<a name="l00145"></a>00145         <span class="keywordflow">case</span> 25: StubAccess().invoke(interface_, Meta::Int&lt;25&gt;(), in, out, t); <span class="keywordflow">break</span>;
<a name="l00146"></a>00146         <span class="keywordflow">default</span>: RCF_THROW(Exception, <span class="stringliteral">"invalid function id"</span>)(fnId); <span class="comment">// TODO: exception type</span>
<a name="l00147"></a>00147         }
<a name="l00148"></a>00148     }
<a name="l00149"></a>00149 
<a name="l00150"></a>00150     template&lt;typename InterfaceT, typename DerefPtrT&gt;
<a name="l00151"></a>00151     <span class="keyword">class</span> InterfaceInvocator
<a name="l00152"></a>00152     {
<a name="l00153"></a>00153     <span class="keyword">public</span>:
<a name="l00154"></a>00154         InterfaceInvocator(InterfaceT &amp;interface_, DerefPtrT derefPtr) : interface_(interface_), derefPtr(derefPtr) {}
<a name="l00155"></a>00155         <span class="keywordtype">void</span> operator()( <span class="keywordtype">int</span> fnId, SerializationProtocolIn &amp;in, SerializationProtocolOut &amp;out) 
<a name="l00156"></a>00156         { 
<a name="l00157"></a>00157             invoke&lt;InterfaceT&gt;(interface_, derefPtr-&gt;deref(), fnId, in, out); 
<a name="l00158"></a>00158         }
<a name="l00159"></a>00159     <span class="keyword">private</span>:
<a name="l00160"></a>00160         InterfaceT &amp;interface_;
<a name="l00161"></a>00161         DerefPtrT derefPtr;
<a name="l00162"></a>00162     };
<a name="l00163"></a>00163 
<a name="l00164"></a>00164     template&lt;typename InterfaceT, typename DerefPtrT&gt;
<a name="l00165"></a>00165     <span class="keywordtype">void</span> registerInvokeFunctors(InterfaceT &amp;interface_, InvokeFunctorMap &amp;invokeFunctorMap, DerefPtrT derefPtr)
<a name="l00166"></a>00166     {
<a name="l00167"></a>00167         <span class="comment">// NB: same interface may occur more than once in the inheritance hierarchy of another interface, and in</span>
<a name="l00168"></a>00168         <span class="comment">// that case, via overwriting, only one InterfaceInvocator is registered, so only the functions in one of the interfaces will ever be called.</span>
<a name="l00169"></a>00169         <span class="comment">// But it doesn't matter, since even if an interface occurs several times in the inheritance hierarchy, each occurrence</span>
<a name="l00170"></a>00170         <span class="comment">// of the interface will be bound to derefPtr in exactly the same way.</span>
<a name="l00171"></a>00171 
<a name="l00172"></a>00172         <span class="keyword">typedef</span> <span class="keyword">typename</span> InterfaceT::Interface Interface;
<a name="l00173"></a>00173         std::string interfaceName = ::RCF::getInterfaceName&lt;Interface&gt;();
<a name="l00174"></a>00174         invokeFunctorMap[ interfaceName ] = InterfaceInvocator&lt;InterfaceT, DerefPtrT&gt;(interface_, derefPtr);
<a name="l00175"></a>00175     }
<a name="l00176"></a>00176 
<a name="l00177"></a>00177     <span class="keyword">class </span>ServerStub;
<a name="l00178"></a>00178 
<a name="l00179"></a>00179     <span class="keyword">typedef</span> boost::shared_ptr&lt;ServerStub&gt; ServerStubPtr;
<a name="l00180"></a>00180 
<a name="l00181"></a>00181     <span class="keyword">class </span>ServerStub
<a name="l00182"></a>00182     {
<a name="l00183"></a>00183     <span class="keyword">public</span>:
<a name="l00184"></a>00184 
<a name="l00185"></a>00185         <span class="keyword">template</span>&lt;<span class="keyword">typename</span> InterfaceT, <span class="keyword">typename</span> DerefPtrT&gt;
<a name="l00186"></a>00186         <span class="keywordtype">void</span> registerInvokeFunctors(InterfaceT &amp;interface_, DerefPtrT derefPtr)
<a name="l00187"></a>00187         {
<a name="l00188"></a>00188             StubAccess access;
<a name="l00189"></a>00189             access.registerInvokeFunctors(interface_, mInvokeFunctorMap, derefPtr);
<a name="l00190"></a>00190         }
<a name="l00191"></a>00191 
<a name="l00192"></a>00192         <span class="keywordtype">void</span> invoke(<span class="keyword">const</span> std::string &amp;subInterface, <span class="keywordtype">int</span> fnId, SerializationProtocolIn &amp;in, SerializationProtocolOut &amp;out)
<a name="l00193"></a>00193         {
<a name="l00194"></a>00194             <span class="comment">// no mutex here, since there is never anyone writing to mInvokeFunctorMap</span>
<a name="l00195"></a>00195             <span class="keywordflow">if</span> (mInvokeFunctorMap.find(subInterface) != mInvokeFunctorMap.end())
<a name="l00196"></a>00196             {
<a name="l00197"></a>00197                 mInvokeFunctorMap[subInterface](fnId, in, out);
<a name="l00198"></a>00198             }
<a name="l00199"></a>00199             <span class="keywordflow">else</span>
<a name="l00200"></a>00200             {
<a name="l00201"></a>00201                 RCF_THROW(Exception, <span class="stringliteral">"invalid subinterface name"</span>)(subInterface)(fnId);
<a name="l00202"></a>00202             }
<a name="l00203"></a>00203         }
<a name="l00204"></a>00204 
<a name="l00205"></a>00205     <span class="keyword">private</span>:
<a name="l00206"></a>00206         InvokeFunctorMap mInvokeFunctorMap;
<a name="l00207"></a>00207     };
<a name="l00208"></a>00208 
<a name="l00209"></a>00209 } <span class="comment">// namespace RCF</span>
<a name="l00210"></a>00210 
<a name="l00211"></a>00211 <span class="preprocessor">#include &lt;RCF/ServerStub.inl&gt;</span>
<a name="l00212"></a>00212 
<a name="l00213"></a>00213 <span class="preprocessor">#endif // ! INCLUDE_RCF_SERVERSTUB_HPP</span>
</pre></div><hr size="1"><address style="align: right;"><small>Generated on Tue Sep 19 19:02:37 2006 for RCF by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.4.5 </small></address>
</body>
</html>

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Australia Australia
Software developer, from Sweden and now living in Canberra, Australia, working on distributed C++ applications. When he is not programming, Jarl enjoys skiing and playing table tennis. He derives immense satisfaction from referring to himself in third person.

Comments and Discussions