I wrote a neat little threading class to make spawning off new threads a lot easier, especially when you want to spawn off a class member function on a new thread. The syntax is as simple as it could possibly be:
class my_class
{
void member_function(int argument1, float argument2) { ... }
};
{
...
int arg1;
float arg2;
my_class c;
thread_t thread;
thread.spawn_thread(c, &my_class::member_function, arg1, arg2);
}
And that's it. Plus, you can spawn a thread from a non-member function, too. It works under both Windows threads and pthreads. The main limitation is that it currently only supports up to 4 arguments, but it should be fairly simple to edit the code should you require more. Let me know if (or rather, when) you spot any bugs. Here's the whole code listing, should you want to use it:
#include
#ifndef THREAD_H
#define THREAD_H
#ifdef WIN32
#include
#define CALLING_CONVENTIONS WINAPI
#else
#include
#include
#define CALLING_CONVENTIONS
#endif
//cbigart
class thread_t
{
public:
const static int MAX_NUM_ARGS = 4;
static void sleep(int ms)
{
#ifdef WIN32
Sleep(ms);
#else
usleep(ms * 1000);
#endif
}
private:
template
static RT CALLING_CONVENTIONS method_stub1(SA arg)
{
struct args_t
{
R (*func_ptr)(A1);
A1 arg1val;
};
args_t args = *(args_t*)arg;
(args.func_ptr)(args.arg1val);
return RT();
}
template
static RT CALLING_CONVENTIONS method_stub2(SA arg)
{
struct args_t
{
R (*func_ptr)(A1, A2);
A1 arg1val;
A2 arg2val;
};
args_t args = *(args_t*)arg;
(args.func_ptr)(args.arg1val, args.arg2val);
return RT();
}
template
static RT CALLING_CONVENTIONS method_stub3(SA arg)
{
struct args_t
{
R (*func_ptr)(A1, A2, A3);
A1 arg1val;
A2 arg2val;
A3 arg3val;
};
args_t args = *(args_t*)arg;
(args.func_ptr)(args.arg1val, args.arg2val, args.arg3val);
return RT();
}
template
static RT CALLING_CONVENTIONS method_stub4(SA arg)
{
struct args_t
{
R (*func_ptr)(A1, A2, A3, A4);
A1 arg1val;
A2 arg2val;
A3 arg3val;
A4 arg4val;
};
args_t args = *(args_t*)arg;
(args.func_ptr)(args.arg1val, args.arg2val, args.arg3val, args.arg4val);
return RT();
}
public:
template
{
#ifdef WIN32
LPTHREAD_START_ROUTINE f = (LPTHREAD_START_ROUTINE)func_ptr;;
CreateThread(0, 0, f, 0, 0, 0);
#else
pthread_t thread;
pthread_create(&thread, 0, func_ptr, 0);
#endif
}
template
{
struct args_t
{
R (*func_ptr)(A1);
A1 arg1val;
};
args_t* args = new args_t;
args->arg1val = arg1val;
args->func_ptr = func_ptr;
#ifdef WIN32
CreateThread(0, 0, &method_stub1
#else
pthread_t thread;
pthread_create(&thread, 0, &method_stub1
#endif
}
template
const A1& arg1val = A1(), const A2& arg2val = A2())
{
struct args_t
{
R (*func_ptr)(A1, A2);
A1 arg1val;
A2 arg2val;
};
args_t* args = new args_t;
args->arg1val = arg1val;
args->arg2val = arg2val;
args->func_ptr = func_ptr;
#ifdef WIN32
CreateThread(0, 0, &method_stub2
#else
pthread_t thread;
pthread_create(&thread, 0, &method_stub2
#endif
}
template
const A1& arg1val = A1(), const A2& arg2val = A2(), const A3& arg3val = A3())
{
struct args_t
{
R (*func_ptr)(A1, A2, A3);
A1 arg1val;
A2 arg2val;
A3 arg3val;
};
args_t* args = new args_t;
args->arg1val = arg1val;
args->arg2val = arg2val;
args->arg3val = arg3val;
args->func_ptr = func_ptr;
#ifdef WIN32
CreateThread(0, 0, &method_stub3
#else
pthread_t thread;
pthread_create(&thread, 0, &method_stub3
#endif
}
template
const A1& arg1val = A1(), const A2& arg2val = A2(), const A3& arg3val = A3(), const A4& arg4val = A4())
{
struct args_t
{
R (*func_ptr)(A1, A2, A3, A4);
A1 arg1val;
A2 arg2val;
A3 arg3val;
A4 arg4val;
};
args_t* args = new args_t;
args->arg1val = arg1val;
args->arg2val = arg2val;
args->arg3val = arg3val;
args->arg4val = arg4val;
args->func_ptr = func_ptr;
#ifdef WIN32
CreateThread(0, 0, &method_stub4
#else
pthread_t thread;
pthread_create(&thread, 0, &method_stub4
#endif
}
private:
template
static RT CALLING_CONVENTIONS class_method_stub(SA arg)
{
struct args_t
{
T* cptr;
R (T::*func_ptr)();
};
args_t args = *(args_t*)arg;
(*args.cptr.*args.func_ptr)();
return RT();
}
template
static RT CALLING_CONVENTIONS class_method_stub1(SA arg)
{
struct args_t
{
T* cptr;
R (T::*func_ptr)(A1);
A1 arg1val;
};
args_t args = *(args_t*)arg;
(*args.cptr.*args.func_ptr)(args.arg1val);
return RT();
}
template
static RT CALLING_CONVENTIONS class_method_stub2(SA arg)
{
struct args_t
{
T* cptr;
R (T::*func_ptr)(A1, A2);
A1 arg1val;
A2 arg2val;
};
args_t args = *(args_t*)arg;
(*args.cptr.*args.func_ptr)(args.arg1val, args.arg2val);
return RT();
}
template
static RT CALLING_CONVENTIONS class_method_stub3(SA arg)
{
struct args_t
{
T* cptr;
R (T::*func_ptr)(A1, A2, A3);
A1 arg1val;
A2 arg2val;
A3 arg3val;
};
args_t args = *(args_t*)arg;
(*args.cptr.*args.func_ptr)(args.arg1val, args.arg2val, args.arg3val);
return RT();
}
template
static RT CALLING_CONVENTIONS class_method_stub4(SA arg)
{
struct args_t
{
T* cptr;
R (T::*func_ptr)(A1, A2, A3, A4);
A1 arg1val;
A2 arg2val;
A3 arg3val;
A4 arg4val;
};
args_t args = *(args_t*)arg;
(*args.cptr.*args.func_ptr)(args.arg1val, args.arg2val, args.arg3val, args.arg4val);
return RT();
}
public:
template
R (T::*func_ptr)())
{
struct args_t
{
T* cptr;
R (T::*func_ptr)();
};
args_t* args = new args_t;
args->cptr = &class_instance;
args->func_ptr = func_ptr;
#ifdef WIN32
CreateThread(0, 0, &class_method_stub
#else
pthread_t thread;
pthread_create(&thread, 0, &class_method_stub
#endif
}
template
R (T::*func_ptr)(A1), const A1& arg1val = A1())
{
struct args_t
{
T* cptr;
R (T::*func_ptr)(A1);
A1 arg1val;
};
args_t* args = new args_t;
args->cptr = &class_instance;
args->func_ptr = func_ptr;
args->arg1val = arg1val;
#ifdef WIN32
CreateThread(0, 0, &class_method_stub1
#else
pthread_t thread;
pthread_create(&thread, 0, &class_method_stub1
#endif
}
template
R (T::*func_ptr)(A1, A2), const A1& arg1val = A1(), const A2& arg2val = A2())
{
struct args_t
{
T* cptr;
R (T::*func_ptr)(A1, A2);
A1 arg1val;
A2 arg2val;
};
args_t* args = new args_t;
args->cptr = &class_instance;
args->func_ptr = func_ptr;
args->arg1val = arg1val;
args->arg2val = arg2val;
#ifdef WIN32
CreateThread(0, 0, &class_method_stub2
#else
pthread_t thread;
pthread_create(&thread, 0, &class_method_stub2
#endif
}
template
R (T::*func_ptr)(A1, A2, A3), const A1& arg1val = A1(), const A2& arg2val = A2(), const A3& arg3val = A3())
{
struct args_t
{
T* cptr;
R (T::*func_ptr)(A1, A2, A3);
A1 arg1val;
A2 arg2val;
A3 arg3val;
};
args_t* args = new args_t;
args->cptr = &class_instance;
args->func_ptr = func_ptr;
args->arg1val = arg1val;
args->arg2val = arg2val;
args->arg3val = arg3val;
#ifdef WIN32
CreateThread(0, 0, &class_method_stub3
#else
pthread_t thread;
pthread_create(&thread, 0, &class_method_stub3
#endif
}
template
R (T::*func_ptr)(A1, A2, A3, A4), const A1& arg1val = A1(), const A2& arg2val = A2(), const A3& arg3val = A3(), const A4& arg4val = A4())
{
struct args_t
{
T* cptr;
R (T::*func_ptr)(A1, A2, A3, A4);
A1 arg1val;
A2 arg2val;
A3 arg3val;
A4 arg4val;
};
args_t* args = new args_t;
args->cptr = &class_instance;
args->func_ptr = func_ptr;
args->arg1val = arg1val;
args->arg2val = arg2val;
args->arg3val = arg3val;
args->arg4val = arg4val;
#ifdef WIN32
CreateThread(0, 0, &class_method_stub4
#else
pthread_t thread;
pthread_create(&thread, 0, &class_method_stub4
#endif
}
};
#endif
