PDA

View Full Version : _beginthread question


freezzo
11-02-2007, 06:58 AM
I'm trying to build a thread manager, which will basically figure out the number of processors available, and split work load up onto separate threads and im running into a problem of getting _beginthread to take the function i want:


#include <process.h>
#include <vector>
using namespace std;

class Threadable
{
public:
Threadable()
{
is_multithreaded = true;
}
virtual void run() = 0;

bool is_multithreaded;
};

class ThreadManager
{
public:
void Add(Threadable *obj)
{
list.push_back(obj);
}

void Execute()
{
std::vector<Threadable *>::const_iterator i;

for(i = list.begin(); i != list.end(); ++i)
{
(*i)->is_multithreaded = true;
(*i)->run();
_beginthread((*i)->run(), 0, 0);
}
}

vector<Threadable *> list;
};

class Test: public Threadable
{
public:
void run()
{
printf("hi\n");

if(is_multithreaded)
_endthread();
}
};

void main(void)
{
ThreadManager *thMan = new ThreadManager();
Test *test = new Test();
Test *test2 = new Test();

thMan->Add(test);
thMan->Add(test);

thMan->Execute();
}


The logic isnt in yet to split up workload, just trying to pass it to beginthread. Any ideas what I am doing wrong?

I added all the code here, its actually in separate class files. Here is my error:

c:\test\input_handler\thread_manager.h(33) : error C2664: '_beginthread' : cannot convert parameter 1 from 'void' to 'void (__cdecl *)(void *)'

I have used _beginthread before with normal functions, I Just cant figure out how to use it with a function referenced from a class stored in the vector.

Thanks

.oisyn
11-02-2007, 07:27 AM
_beginthread((*i)->run(), 0, 0);
You're calling the function run() on *i, and are using the result from that function to pass to _beginthread(). Compare:
int a()
{
return 123;
}

void b(int i)
{
std::cout << i << std::endl;
}

int main()
{
b(a());
}
Do you pass the function a to b? No, you pass the result from a() to b, so b gets called with the int 123.

What you need is a pointer to the appropriate function. Unfortunately, you will not be able to get the pointer as the run() method is an instance method and not static, so you can't get a pointer to it and just call it, because you don't know which object to call it on.

Fortunately, however, _beginthread() accepts an extra user parameter, which will be passed to the callable function in the other thread. If you pass the Threadable instance as user parameter, and use a global function to reroute the call to Run() on that instance, you'll be fine.

void CallRun(void * instance)
{
static_cast<Threadable*>(instance)->Run();
}

void StartThread(Threadable * t)
{
_beginthread(CallRun, 0, t);
}

freezzo
11-02-2007, 07:53 AM
Thanks!

I can't believe I overlooked that fact. Total brain dump there.