65.9K
CodeProject is changing. Read more.
Home

Threaded Functions

emptyStarIconemptyStarIconemptyStarIconemptyStarIconemptyStarIcon

0/5 (0 vote)

Nov 5, 2011

BSD
viewsIcon

6020

Here's an interesting thought experiment for functions that get executed in a separate thread.

Here's an interesting thought experiment for functions that get executed in a separate thread.

void doit( int i ) {
   printf( "Hello from doit! i: %d\n", i );
}

void doit2( Thread* th, int i ) {
  printf( "Hello from doit2! i: %d, th: %p, tid: 0x%04x \n", 
          i, th, th->getThreadID() );
}

class Snarfy {
public:
  void thisBlows( int g ) {
     printf( "Hello from thisBlows! i: %d, this ptr: %p\n", g, this );
  }
};

class Swanky {
public:
  void doit( double& d, const String& s ) {
     printf( "Hello from Swanky::doit! d: %0.3f, s: %s, this ptr: %p\n",
               d, s.ansi_c_str(), this );
  }

  void doit2( Thread* th, double& d, const String& s ) {
     printf( "Hello from Swanky::doit! d: %0.3f, s: %s, this ptr: %p\n",
               d, s.ansi_c_str(), this );

     for (int i=0;i<10;i++){
       th->sleep(1000);
   }
}
};

int main( int argc, char** argv ){
FoundationKit::init( argc, argv );

Thread* th = ThreadedProcedure1<int>(10,doit);
th->wait();
th = ThreadedProcedure1<int>(231,doit2);
th->wait();

Snarfy sn;
th = ThreadedProcedure1<int,Snarfy >(&sn,38112,&Snarfy::thisBlows);
th->wait();

String s = "hello";
Swanky sk;

double d = 0.0332;

th = ThreadedProcedure2< double&,const String&, 
      Swanky >(&sk,d,s,&Swanky::doit2);
th->wait();

printf( "Bye!\n");

FoundationKit::terminate();
return 0;

The actual implementation gets a bit long winded, but looks something like this:

template <typename ParamType1>
class NullClassType1 {
 public:
  void m(ParamType1){}
  void m(Thread*, ParamType1){}
};

template <typename ParamType1, typename ClassType=NullClassType1<ParamType1> >
class ThreadedProcedure1: public Runnable {
public:

 typedef NullClassType1<ParamType1> NullClassType;

 typedef void (*ProcPtr1)(ParamType1 p1);
 typedef void (*ProcThreadPtr1)(Thread* thread, ParamType1 p1); 

 typedef void (ClassType::*ClassProcPtr1)( ParamType1 p1 );
 typedef void (ClassType::*ClassThreadProcPtr1)( Thread* thread, ParamType1 p1 );

 

 ThreadedProcedure1( ParamType1 p1, ProcPtr1 procPtr ): param1_(p1),
  runningThread_(NULL),
   procPtr_(NULL),
   procThreadPtr_(NULL),
   classProcPtr_(NULL),
   classThreadProcPtr_(NULL),
   instancePtr_(NULL){

  ThreadedProcedure1<ParamType1,ClassType>* params = 
   new ThreadedProcedure1<ParamType1,ClassType>(p1);

  params->procPtr_ = procPtr;

  runningThread_ = new Thread( params, true, true );
  params->runningThread_ = runningThread_;

  runningThread_->start();
 }

 ThreadedProcedure1( ParamType1 p1, ProcThreadPtr1 procPtr ): param1_(p1),
   runningThread_(NULL),
   procPtr_(NULL),
   procThreadPtr_(NULL),
   classProcPtr_(NULL),
   classThreadProcPtr_(NULL),
   instancePtr_(NULL){

  ThreadedProcedure1<ParamType1,ClassType>* params = 
   new ThreadedProcedure1<ParamType1,ClassType>(p1);

  params->procThreadPtr_ = procPtr;

  runningThread_ = new Thread( params, true, true );
  params->runningThread_ = runningThread_;

  runningThread_->start();
 }

 ThreadedProcedure1( ClassType* src, ParamType1 p1, ClassProcPtr1 procPtr ): param1_(p1),
  runningThread_(NULL),
   procPtr_(NULL),
   procThreadPtr_(NULL),
   classProcPtr_(NULL),
   classThreadProcPtr_(NULL),
   instancePtr_(NULL) {

  ThreadedProcedure1<ParamType1,ClassType>* params = 
   new ThreadedProcedure1<ParamType1,ClassType>(p1);


  params->classProcPtr_ = procPtr;
  params->instancePtr_ = src;

  runningThread_ = new Thread( params, true, true );
  params->runningThread_ = runningThread_;

  runningThread_->start();
 }


 ThreadedProcedure1( ClassType* src, ParamType1 p1, 
                     ClassThreadProcPtr1 procPtr ): param1_(p1),
   runningThread_(NULL),
   procPtr_(NULL),
   procThreadPtr_(NULL),
   classProcPtr_(NULL),
   classThreadProcPtr_(NULL),
   instancePtr_(NULL){

  ThreadedProcedure1<ParamType1,ClassType>* params = 
   new ThreadedProcedure1<ParamType1,ClassType>(p1);

  params->classThreadProcPtr_ = procPtr;
  params->instancePtr_ = src;

  runningThread_ = new Thread( params, true, true );
  params->runningThread_ = runningThread_;

  runningThread_->start();
 }


protected:

 ThreadedProcedure1( ParamType1 p1 ): param1_(p1),
   runningThread_(NULL),
   procPtr_(NULL),
   procThreadPtr_(NULL),
   classProcPtr_(NULL),
   classThreadProcPtr_(NULL),
   instancePtr_(NULL){
 }

public:
 virtual bool run() {


  if ( typeid(ClassType) == typeid(NullClassType) ) {
   if ( NULL != procThreadPtr_ ) {
    (*procThreadPtr_)( runningThread_, param1_ );
   }
   else if ( NULL != procPtr_ ) {
    (*procPtr_)( param1_ );
   }
   else {
    return false;
   }   
  }
  else {
   if ( NULL != instancePtr_ ) {
    if ( NULL != classThreadProcPtr_ ) {
     (instancePtr_->*classThreadProcPtr_)( runningThread_, param1_ );
    }
    else if ( NULL != classProcPtr_ ) {
     (instancePtr_->*classProcPtr_)( param1_ );
    }
    else {
     return false;
    } 
    
   }
  }
  

  return true;
 }

 virtual void stop(){}


 operator Thread* () {
  return runningThread_;
 }
protected:
 
 ParamType1 param1_;
 Thread* runningThread_;
 ProcPtr1 procPtr_;
 ProcThreadPtr1 procThreadPtr_;
 ClassProcPtr1 classProcPtr_;
 ClassThreadProcPtr1 classThreadProcPtr_;
 ClassType* instancePtr_;
};

This allows us to attach a function and execute it in a separate thread, using the various VCF thread classes, such as VCF::Thread and VCF::Runnable 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.