Skip to main content
gamedev.net
🔒 Locked

Thread inside a class

Started by cherryhouse Apr 10, 2006 at 10:17 PM 8 replies 1k views
Original Post
cherryhouse
cherryhouse
I need to create a thread inside a class that allows the programmer to access the member functions. The way I declare my thread, though, I don't think it's possible to create a "member thread", or whatever, how I want to. Here's how I initialize the thread

DWORD WINAPI RecvThread(LPVOID lpParameter);

Whenever I try to use an access member scopre like so:

DWORD WINAPI Client::RecvThread(LPVOID lpParameter) { //do stuff }

I'm told I can't do that. Does anyone have a clue how I would create a class thread? The only other solution I've had was to create the class object globally so that the thread could receive while another function was sending messages, which everyone knows, declaring globally is wrong.
Hello?
jflanglois
jflanglois
Pointers to functions are not the same as pointers to member-functions.

Take a look at this article. It should give you a few ideas.

Can you elaborate on what you are trying to do, I'm not sure threads are what you are looking for.


jfl.

[Edited by - jflanglois on April 10, 2006 10:20:34 PM]
cherryhouse
cherryhouse
I am trying to get user input then send the message to the server in a loop, and in a thread I am trying to receive then print to the screen, the buffer. Threads are simple to implement and are easy to control, that's why I'm trying to use them.

PS> I'm not trying to create a thread class, I'm just trying to create a thread that is able to use the classes member functions like so:

DWORD WINAPI RecvThread(LPVOID lpParameter){   for(;;){      RecvData(); // This is a member function. I need to be able to access this member function within the thread   }}
Hello?
yadango
yadango
you can also make the thread function a friend function and pass the object into the parameter list.
Agony
Agony
I tend to have two functions. One is a static function (so it is able to be used by the thread creation function), and the other is a member function. I pass the this pointer as the parameter to the thread. Then in the static function, I cast the void pointer to the type of the class, and call the member function.
class CWithAThread{  public:    void Start();  private:    static DWORD WINAPI ThreadFunc_Static(LPVOID lpParameter);    DWORD ThreadFunc();    HANDLE mhThread;};void CWithAThread::Start(){  mhThread = CreateThread(NULL, 0, CWithAThread::ThreadFunc_Static, reinterpret_cast<LPVOID>(this), 0, NULL);}DWORD WINAPI CWithAThread::ThreadFunc_Static(LPVOID lpParameter){  if (lpParameter != NULL)  {    return reinterpret_cast<CWithAThread*>(lpParameter)->ThreadFunc();  }  else  {    return 1;  }}DWORD CWithAThread::ThreadFunc(){  //Do stuff  //...  //At end:  CloseHandle(mhThread);  return 0;}

Now there are a lot of other steps one can take to make that a whole lot safer, but that should provide you with a foundation to work with.
"We should have a great fewer disputes in the world if words were taken for what they are, the signs of our ideas nly, and not for things themselves." - John Locke o
cherryhouse
cherryhouse
I don't quite think I'm explaining myself clearly enough.
I'm not trying to create a thread class. I already know how to create a thread class. What I'm trying to do is pass an object to a thread. If I could get it to work, this is what it would look like:

DWORD WINAPI RecvThread(LPVOID lpParameter, Client obj) { //do stuff }


Using a friend function doesn't work because The RecvThread still has no access scope to the class.
Hello?
Oluseyi
Oluseyi
Quote:
Original post by cherryhouse
I don't quite think I'm explaining myself clearly enough.
I'm not trying to create a thread class. I already know how to create a thread class. What I'm trying to do is pass an object to a thread.

CreateThread( blah, blah, SomeFunction);...DWORD SomeFunction(LPVOID arg){  SomeClass * sc = reinterpret_cast<SomeClass *>(arg);  // blah}

If you had actually read Agony's post and his included code, you would have seen exactly that structure in his static "routing" function.
jflanglois
jflanglois
Indeed, that is also the technique used in the article I linked to.


jfl.
Adam Hamilton
Adam Hamilton
You can still make the thread function a friend. Do you notice the lpParameter argument... Use this as a pointer to your object and then your thread function will have access to your object and it's private/protected data.

What could be more simpler :)
pcxmac
pcxmac
I hope thats what you wanted, also, Threads call to an external function not placeable in side a class, at least as far as i know, I use a wrapper class for the thread, and point its offset through the LPVOID variable which gets passed off to the Thread function (DWORD WINAPI). I also have an initializer function for the thread incase of thread context create issues (like OpenGL), and i use "main" in the thread class, called by the WINAPI ThreadFunc, as my main entry point.




signaling helps stave off collisions.

Use a signal after you are done "SIG_AWAITING_PROCESSING"
If the input buffer is ready for input, it will be signaled to "SIG_READY_4_INPUT"

class input

class input::input_data(data_structure )
{
if (this.signal == "..READY..") this.buffer = data_structure
else return false; // function returns stating that no input was passed

return true;
}

class RecvThread : public input; // (input class)

/*

In you're main loop for RecvThread class, you can check for input, after a successfull read, you can signal you're buffer "SIG_READY_4_INPUT", the
RecvThread class will know if there is input by seeing "SIG_AWAITING_PROCESSING"

*/

ARBITRARY_CONTEXT::function() // SAY YOU're INPUT HANDLER
{
RecvThread MyRecvThread;
...
MyRecvThread.input_data(&data_structure); // will return false if "SIG_AWA.."

};



class thread
{
private :
bool enabled; // is thread enabled == true? or disabled == false
HINSTANCE hInst; // Instance Handle
DWORD dwThreadId; // Thread ID in DWORD
HANDLE thisThread; // Handle to this thread
HANDLE synchro;
public :
void start (); // user controll for thread start
void stop (); // user controll for thread stop
void unsignal (); // SetEvent(Handle), allows main thread to resume execution
void signal ();
virtual void initialize ()=0; // virtual abc used for initial non looping parameters
virtual void main (void* _reference)=0; // user entry point for thread code
thread (); // constructor -- almost needed
~thread ();
};





DWORD WINAPI ThreadFunc( LPVOID lpParam )
{
thread* thisThread = (thread*)lpParam;
thisThread->initialize();
thisThread->unsignal();
thisThread->main(lpParam);
};

void thread::start()
{
if (enabled == false)
{
hInst = GetModuleHandle(0);
thisThread = CreateThread(0,0,ThreadFunc,this,0,&dwThreadId);
enabled = true;
signal();
};
};

thread::thread()
{
enabled = false;
synchro = CreateEvent (NULL,FALSE,FALSE,NULL);
ResetEvent (synchro);
};

thread::~thread()
{
CloseHandle(synchro);
};
sig

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.