tag:blogger.com,1999:blog-3330363568531008511.post-31505100533119351882007-04-26T12:12:00.000-07:002007-04-26T13:07:19.552-07:00Threaded FunctionsHere's an interesting thought experiment for functions that get executed in a separate thread.<br /><pre><br /><br />void doit( int i ) {<br />printf( "Hello from doit! i: %d\n", i );<br />}<br /><br /><br /><br /><br />void doit2( Thread* th, int i ) {<br />printf( "Hello from doit2! i: %d, th: %p, tid: 0x%04x \n", i, th, th-&gt;getThreadID() );<br /><br />}<br /><br />class Snarfy {<br />public:<br />void thisBlows( int g ) {<br /> printf( "Hello from thisBlows! i: %d, this ptr: %p\n", g, this );<br />}<br />};<br /><br /><br />class Swanky {<br />public:<br />void doit( double& d, const String&amp; s ) {<br /> printf( "Hello from Swanky::doit! d: %0.3f, s: %s, this ptr: %p\n",<br /> d, s.ansi_c_str(), this );<br />}<br /><br /><br />void doit2( Thread* th, double& d, const String&amp; s ) {<br /> printf( "Hello from Swanky::doit! d: %0.3f, s: %s, this ptr: %p\n",<br /> d, s.ansi_c_str(), this );<br /><br /> for (int i=0;i&lt;10;i++){<br /> th-&gt;sleep(1000);<br /> }<br />}<br />};<br /><br />int main( int argc, char** argv ){<br /><br />FoundationKit::init( argc, argv );<br /><br /><br /><br />Thread* th = ThreadedProcedure1&lt;int&gt;(10,doit);<br /><br />th-&gt;wait();<br /><br />th = ThreadedProcedure1&lt;int&gt;(231,doit2);<br /><br />th-&gt;wait();<br /><br /><br />Snarfy sn;<br /><br />th = ThreadedProcedure1&lt;int,Snarfy &gt;(&sn,38112,&amp;Snarfy::thisBlows);<br />th-&gt;wait();<br /><br /><br /><br />String s = "hello";<br />Swanky sk;<br /><br />double d = 0.0332;<br /><br />th = ThreadedProcedure2&lt; double&,const String&amp;, Swanky &gt;(&sk,d,s,&amp;Swanky::doit2);<br />th-&gt;wait();<br /><br /><br />printf( "Bye!\n");<br /><br />FoundationKit::terminate();<br />return 0;<br />}<br /></pre><br /><br />The actual implementation gets a bit long winded, but looks something like this:<br /><br /><pre><br /><br /><br />template &lt;typename ParamType1&gt;<br />class NullClassType1 {<br /> public:<br /> void m(ParamType1){}<br /> void m(Thread*, ParamType1){}<br />};<br /><br /><br />template &lt;typename ParamType1, typename ClassType=NullClassType1&lt;ParamType1&gt; &gt;<br />class ThreadedProcedure1: public Runnable {<br />public:<br /><br /> typedef NullClassType1&lt;ParamType1&gt; NullClassType;<br /><br /> typedef void (*ProcPtr1)(ParamType1 p1);<br /> typedef void (*ProcThreadPtr1)(Thread* thread, ParamType1 p1); <br /><br /> typedef void (ClassType::*ClassProcPtr1)( ParamType1 p1 );<br /> typedef void (ClassType::*ClassThreadProcPtr1)( Thread* thread, ParamType1 p1 );<br /><br /> <br /><br /> ThreadedProcedure1( ParamType1 p1, ProcPtr1 procPtr ): param1_(p1),<br /> runningThread_(NULL),<br /> procPtr_(NULL),<br /> procThreadPtr_(NULL),<br /> classProcPtr_(NULL),<br /> classThreadProcPtr_(NULL),<br /> instancePtr_(NULL){<br /><br /> ThreadedProcedure1&lt;ParamType1,ClassType&gt;* params = <br /> new ThreadedProcedure1&lt;ParamType1,ClassType&gt;(p1);<br /><br /> params-&gt;procPtr_ = procPtr;<br /><br /> runningThread_ = new Thread( params, true, true );<br /> params-&gt;runningThread_ = runningThread_;<br /><br /> runningThread_-&gt;start();<br /> }<br /><br /> ThreadedProcedure1( ParamType1 p1, ProcThreadPtr1 procPtr ): param1_(p1),<br /> runningThread_(NULL),<br /> procPtr_(NULL),<br /> procThreadPtr_(NULL),<br /> classProcPtr_(NULL),<br /> classThreadProcPtr_(NULL),<br /> instancePtr_(NULL){<br /><br /> ThreadedProcedure1&lt;ParamType1,ClassType&gt;* params = <br /> new ThreadedProcedure1&lt;ParamType1,ClassType&gt;(p1);<br /><br /> params-&gt;procThreadPtr_ = procPtr;<br /><br /> runningThread_ = new Thread( params, true, true );<br /> params-&gt;runningThread_ = runningThread_;<br /><br /> runningThread_-&gt;start();<br /> }<br /><br /> ThreadedProcedure1( ClassType* src, ParamType1 p1, ClassProcPtr1 procPtr ): param1_(p1),<br /> runningThread_(NULL),<br /> procPtr_(NULL),<br /> procThreadPtr_(NULL),<br /> classProcPtr_(NULL),<br /> classThreadProcPtr_(NULL),<br /> instancePtr_(NULL) {<br /><br /> ThreadedProcedure1&lt;ParamType1,ClassType&gt;* params = <br /> new ThreadedProcedure1&lt;ParamType1,ClassType&gt;(p1);<br /><br /> params-&gt;classProcPtr_ = procPtr;<br /> params-&gt;instancePtr_ = src;<br /><br /> runningThread_ = new Thread( params, true, true );<br /> params-&gt;runningThread_ = runningThread_;<br /><br /> runningThread_-&gt;start();<br /> }<br /><br /><br /> ThreadedProcedure1( ClassType* src, ParamType1 p1, ClassThreadProcPtr1 procPtr ): param1_(p1),<br /> runningThread_(NULL),<br /> procPtr_(NULL),<br /> procThreadPtr_(NULL),<br /> classProcPtr_(NULL),<br /> classThreadProcPtr_(NULL),<br /> instancePtr_(NULL){<br /><br /> ThreadedProcedure1&lt;ParamType1,ClassType&gt;* params = <br /> new ThreadedProcedure1&lt;ParamType1,ClassType&gt;(p1);<br /><br /> params-&gt;classThreadProcPtr_ = procPtr;<br /> params-&gt;instancePtr_ = src;<br /><br /> runningThread_ = new Thread( params, true, true );<br /> params-&gt;runningThread_ = runningThread_;<br /><br /> runningThread_-&gt;start();<br /> }<br /><br /><br /><br /><br /> <br /><br /> <br />protected:<br /><br /> ThreadedProcedure1( ParamType1 p1 ): param1_(p1),<br /> runningThread_(NULL),<br /> procPtr_(NULL),<br /> procThreadPtr_(NULL),<br /> classProcPtr_(NULL),<br /> classThreadProcPtr_(NULL),<br /> instancePtr_(NULL){<br /> }<br /><br />public:<br /> virtual bool run() {<br /><br /><br /> if ( typeid(ClassType) == typeid(NullClassType) ) {<br /> if ( NULL != procThreadPtr_ ) {<br /> (*procThreadPtr_)( runningThread_, param1_ );<br /> }<br /> else if ( NULL != procPtr_ ) {<br /> (*procPtr_)( param1_ );<br /> }<br /> else {<br /> return false;<br /> } <br /> }<br /> else {<br /> if ( NULL != instancePtr_ ) {<br /> if ( NULL != classThreadProcPtr_ ) {<br /> (instancePtr_-&gt;*classThreadProcPtr_)( runningThread_, param1_ );<br /> }<br /> else if ( NULL != classProcPtr_ ) {<br /> (instancePtr_-&gt;*classProcPtr_)( param1_ );<br /> }<br /> else {<br /> return false;<br /> } <br /> <br /> }<br /> }<br /> <br /><br /> return true;<br /> }<br /><br /> virtual void stop(){}<br /><br /><br /> operator Thread* () {<br /> return runningThread_;<br /> }<br />protected:<br /> <br /> ParamType1 param1_;<br /> Thread* runningThread_;<br /> ProcPtr1 procPtr_;<br /> ProcThreadPtr1 procThreadPtr_;<br /> ClassProcPtr1 classProcPtr_;<br /> ClassThreadProcPtr1 classThreadProcPtr_;<br /> ClassType* instancePtr_;<br />};<br /><br /><br /><br /></pre><br /><br />This allows us to attach a function and execute it in a separate thread, using the various VCF thread classes, such as <a href="http://vcf-online.org/docs/src_manual/classVCF_1_1Thread.html">VCF::Thread</a> and <a href="http://vcf-online.org/docs/src_manual/classVCF_1_1Runnable.html">VCF::Runnable</a> to implement it. I'll leave it as an exercise for the reader to add additional arguments. If people like this enough we'll probably put this into the FoundationKit proper.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3330363568531008511-3150510053311935188?l=software-windmills.blogspot.com'/></div>Jim Craftonhttp://www.blogger.com/profile/06342609230425703376noreply@blogger.com0