Threads Question

Started by
14 comments, last by WebsiteWill 20 years, 8 months ago
I have a class that when started will spawn a certain number of threads (depending on input at object istantiation). The class has a function called StartThreads. Inside of there I am calling the CreateThread method. I am having trouble getting CreateThread() to recognize the thread procedure I am passing to it. Here is the function call. cBaseServer::threadProc is of course a member of the class and the function I need the thread to use.

hThreadHandle = CreateThread(NULL, NULL,				        (LPTHREAD_START_ROUTINE)                       
                 &cBaseServer::threadProc, 		         sSharedThreadMemory,NULL, dwThreadID);
threadProc is defined as such

void* Recv(void* vp);
The void* parameter passed to threadProc is just temporary. I have a struct member in the class that I will pass in as a parameter, but I seem to get even more errors when I do not pass a void* to the actual function. I have read that because C++ is so strongly typed that it is difficult (but possible) to create a thread within an object. I know it can be done, I have just not found a snipet of code showing the exact method of casting. Any help on this one? Thanks, Webby
Advertisement
That won''t work unless threadProc is static, and perhaps not even then... It will have issues if there is a this pointer being passed implicitly to the threadproc If you''re doing this to make some kind of server that has to receive from multiple clients, have you looked at the select() function? It''s a no-threads way to do it.

--------------------


You are not a real programmer until you end all your sentences with semicolons; (c) 2000 ROAD Programming

You are unique. Just like everybody else.

"Mechanical engineers design weapons; civil engineers design targets."
"Sensitivity is adjustable, so you can set it to detect elephants and other small creatures." -- Product Description for a vibration sensor

Yanroy@usa.com

--------------------

You are not a real programmer until you end all your sentences with semicolons; (c) 2000 ROAD Programming
You are unique. Just like everybody else.
"Mechanical engineers design weapons; civil engineers design targets."
"Sensitivity is adjustable, so you can set it to detect elephants and other small creatures." -- Product Description for a vibration sensor

Yanroy@usa.com


class foo
{
public:
foo();
int EventLoop();
static void ThreadLauncher( void* a_foo );
};

foo::foo()
{
// Hypothetical threading library...
CreateThread( foo::ThreadLauncher, (void*)this )
}

int foo::EventLoop()
{
while( 1 ) { }
}

void foo::ThreadLauncher( void* a_foo )
{
((foo*)a_foo)->EventLoop();
}

The constructer here creates a thread. The two parameters are the initial function for the thread to start in, and a parameter to pass to that function. The constructor chooses to pass a pointer to the object being constructed (this). ThreadLauncher knows that the void* passed is really a foo, so it casts it and then calls EventLoop.

For safety, you could add a dynamic_cast<> to ThreadLauncher() to make sure you''re really looking at a foo*.

Tony
I''ve looked at select and it won''t work for what I am trying to do. There has to be a way to do this. Makes no real sense why it wouldn''t be allowed by the language. It''s just a matter of casting correctly.

I''m going to attempt the recommendation above.
Thanks,
Webby
The way to do this is to use the lpParameter parameter in the CreateThread function to get back to your object. A little klunky but it works just fine:

Foo* pfoo1, pfoo2;
// ...
CreateThread( ..., ThreadDispatch, reinterpret_cast< LPVOID >(pfoo1), ...);
CreateThread( ..., ThreadDispatch, reinterpret_cast< LPVOID >(pfoo2), ...);

DWORD WINAPI ThreadDipatch( LPVOID lpParameter ) {
Foo* pfoo = reinterpret_cast< Foo* >(lpParameter);

pfoo->YourFunction();
);

At ThreadDispatch(), just cast the parameter back to a Foo and then call the function in the class that you want.

Regards,
Jeff

Edit: Fixed my angle brackets in the cast so they're visible

[edited by - rypyr on August 7, 2003 11:29:40 AM]
I'm attempting what you suggested rypyr.
I have
DWORD WINAPI RecvDispatch(LPVOID lpParameter){cBaseServer* pcBaseServer = reinterpret_cast<cBaseServer*>(lpParameter);pcBaseServer->LocalRecv();}

and I'm calling CreateThread like this.
CreateThread(NULL, NULL,             RecvDispatch, reinterpret_cast<LPVOID>            (pcBaseServer), NULL, dwThreadID);

It is still giving me this casting error:
error C2664: 'CreateThread' : cannot convert parameter 3 from 'unsigned long (void *)' to 'unsigned long (__stdcall *)(void *)'

It's got to be something simple at this point.

Webby
[/source]

[edited by - websitewill on August 7, 2003 11:54:45 AM]
I know it''s ugly, but I bet a C-style cast would work like a charm reinterpret_cast always drives me nuts...

--------------------


You are not a real programmer until you end all your sentences with semicolons; (c) 2000 ROAD Programming

You are unique. Just like everybody else.

"Mechanical engineers design weapons; civil engineers design targets."
"Sensitivity is adjustable, so you can set it to detect elephants and other small creatures." -- Product Description for a vibration sensor

Yanroy@usa.com

--------------------

You are not a real programmer until you end all your sentences with semicolons; (c) 2000 ROAD Programming
You are unique. Just like everybody else.
"Mechanical engineers design weapons; civil engineers design targets."
"Sensitivity is adjustable, so you can set it to detect elephants and other small creatures." -- Product Description for a vibration sensor

Yanroy@usa.com

Still rather new to this casting everything-and-it''s-mother business. Can I get some simple syntax on what you mean by
C-style cast?

Webby
He means this:

Blah blah;

void* pVoid = reinterpret_cast< void* >( &blah ); // C++ style cast

is the same as:

void* pVoid = (void*)(&blah); // C-style cast

They do the same thing, but one looks less ugly...

I'm not sure why you're getting that casting error for your dispatch function. It seems to not pick up the WINAPI declaration...

[edited by - rypyr on August 7, 2003 12:32:07 PM]
Hmmm, you mention the WINAPI.
I seem to recall having to define something somewhere that is not done correctly in I think winbase.h
I''ll be darned is i can remember what it is.

I think it was this
#define WIN32_WINNT 0x0500#

Someone said tha WIN32_WINNT had to be defined as greater or equal to 0x0500

Maybe this has something to do with it? I remember not getting the hints on that page to work for me so I neglected to stick it in my favorites.

This familiar to anyone?

Webby

This topic is closed to new replies.

Advertisement