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.