Jump to content

  • Log In with Google      Sign In   
  • Create Account

c++ A problem when create a thread in a class


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
10 replies to this topic

#1 Maple Wan   Members   -  Reputation: 214

Like
0Likes
Like

Posted 16 September 2013 - 11:54 PM

Dear everyone, I am writing a singleton class to manage a thread, here's the code:

#include <windows.h>

typedef class MsgListener
{
private:
    HANDLE _threadHandle;
    DWORD _threadId;
    static MsgListener *_instance;
    MsgListener();
    DWORD WINAPI Listen(LPVOID param);
public:
    static MsgListener *GetInstance();
    void StartListen();
    void StopListen();
} MSGLISTENER, *LPMSGLISTENER;

MsgListener *MsgListener::_instance = new MsgListener();
MsgListener::MsgListener() 
{ 
    _threadHandle = 0;
    _threadId = 0;
}
DWORD WINAPI MsgListener::Listen(LPVOID param) 
{ 
    // The method to run in a new thread....
}
MsgListener *MsgListener::GetInstance()
{
    if (!_instance)
        _instance = new MsgListener();
    return _instance;
}
void MsgListener::StartListen()
{
    // Here, the compiler give the error:
    // cannot convert 'MsgListener::Listen' from type 'DWORD (MsgListener::)(LPVOID) { aka long unsigned int (MsgListener::)(void*) }' to type 'LPTHREAD_START_ROUTINE { aka long unsigned int (__attribute__((__stdcall__)) *)(void*) }'
    this->_threadHandle = CreateThread(NULL, 0, Listen, 0, &_threadId);
}
void MsgListener::StopListen()
{
    CloseHandle(_threadHandle);
}

The ide I use is Code::Blocks and the compiler is GNU GCC COMPILER.

How to convert the function pointer in a class to the normal function pointer in C? And I really don't know the difference between these two kind of function pointers. Where does each kind of function pointer save in the memory?


Do my best to improve myself, to learn more and more...


Sponsor:

#2 frob   Moderators   -  Reputation: 21060

Like
3Likes
Like

Posted 17 September 2013 - 12:33 AM

Just about everything you wrote in the post fits in the "probably doing it wrong" category. Singletons should generally be avoided. Threading is not a beginner's topic and is a frequent source of nightmares to engine developers, unguarded shared access is another source of nightmares. Member function pointers require a good understanding of how pointers and classes work in c++. Tagging everything as 'WINAPI' calling convention. And all of that while thinking about conserving memory.

Every one of those has an occasional use, but usually as exceptions that don't fit the usual rules of good design.

What is the actual problem you are trying to solve? What are you trying to build? Just based on the names it looks like something to do with passing messages. There are many excellent existing solutions for that which are much less complex than what you are asking.
Check out my personal indie blog at bryanwagstaff.com.

#3 Maple Wan   Members   -  Reputation: 214

Like
0Likes
Like

Posted 17 September 2013 - 01:09 AM

Just about everything you wrote in the post fits in the "probably doing it wrong" category. Singletons should generally be avoided. Threading is not a beginner's topic and is a frequent source of nightmares to engine developers, unguarded shared access is another source of nightmares. Member function pointers require a good understanding of how pointers and classes work in c++. Tagging everything as 'WINAPI' calling convention. And all of that while thinking about conserving memory.

Every one of those has an occasional use, but usually as exceptions that don't fit the usual rules of good design.

What is the actual problem you are trying to solve? What are you trying to build? Just based on the names it looks like something to do with passing messages. There are many excellent existing solutions for that which are much less complex than what you are asking.

Thanks very much. Could you recommand some articles or books about c++ lower mechanisms and theory of c++ class. I always feel confused about some concepts in c++ class.


Do my best to improve myself, to learn more and more...


#4 cdoubleplusgood   Members   -  Reputation: 835

Like
1Likes
Like

Posted 17 September 2013 - 01:31 AM

How to convert the function pointer in a class to the normal function pointer in C?

You cannot directly specify an instance method as method / callback parameter in Windows API in general, and not in CreateThread in particular. This is because internally instance methods have an additional parameter pointing to the class instance, so the method signature does not match the signature required by CreateThread.
The usual workaround is to have a static method, pass a pointer to the instance as lpParameter, and dispatch the call in the static method to an instance method, using that parameter.

class MsgListener
{
private:
    HANDLE _threadHandle;
    DWORD _threadId;
    static MsgListener *_instance;
    MsgListener();
    DWORD Listen();
    static DWORD WINAPI StaticListen(LPVOID param);
public:
    static MsgListener *GetInstance();
    void StartListen();
    void StopListen();
};

MsgListener *MsgListener::_instance = new MsgListener();
MsgListener::MsgListener() 
{ 
    _threadHandle = 0;
    _threadId = 0;
}
DWORD WINAPI MsgListener::StaticListen(LPVOID param) 
{
	MsgListener* listener = reinterpret_cast<MsgListener*>(param);
	return listener->Listen();
}
DWORD MsgListener::Listen() 
{ 
    // The method to run in a new thread....
	return 0;
}
MsgListener *MsgListener::GetInstance()
{
    if (!_instance)
        _instance = new MsgListener();
    return _instance;
}
void MsgListener::StartListen()
{
    this->_threadHandle = CreateThread(NULL, 0, &MsgListener::StaticListen, this, 0, &_threadId);
}
void MsgListener::StopListen()
{
    CloseHandle(_threadHandle);
}

However, I'd use the threading support in C++11 instead. It is so much easier to specify an arbitrary worker method, even an instance method, using the std::thread ctor:

http://en.cppreference.com/w/cpp/thread/thread/thread


Edited by cdoubleplusgood, 17 September 2013 - 01:35 AM.


#5 frob   Moderators   -  Reputation: 21060

Like
0Likes
Like

Posted 17 September 2013 - 01:40 AM

Thanks very much. Could you recommand some articles or books about c++ lower mechanisms and theory of c++ class. I always feel confused about some concepts in c++ class.

Accelerated C++ by Koenig and Moo, and C++ Primer by Lippmann, LaJoie and Moo, are both frequently recommended for beginners in C++.

Even so, what problem are you trying to solve? People can probably point you to excellent resources for whatever specific problem you are looking to solve that are less complex than the path you were traveling.
Check out my personal indie blog at bryanwagstaff.com.

#6 Hodgman   Moderators   -  Reputation: 30341

Like
0Likes
Like

Posted 17 September 2013 - 01:46 AM

Could you recommand some articles or books about c++ lower mechanisms and theory of c++ class. I always feel confused about some concepts in c++ class.

http://www.parashift.com/c++-faq/
 
http://www.parashift.com/c++-faq/memfnptr-vs-fnptr.html


Edited by Hodgman, 17 September 2013 - 01:46 AM.


#7 Maple Wan   Members   -  Reputation: 214

Like
0Likes
Like

Posted 17 September 2013 - 02:11 AM

 

Thanks very much. Could you recommand some articles or books about c++ lower mechanisms and theory of c++ class. I always feel confused about some concepts in c++ class.

Accelerated C++ by Koenig and Moo, and C++ Primer by Lippmann, LaJoie and Moo, are both frequently recommended for beginners in C++.

Even so, what problem are you trying to solve? People can probably point you to excellent resources for whatever specific problem you are looking to solve that are less complex than the path you were traveling.

 

Thanks, I want to create a new thread to watch the keyboard state and mouse state in DirectInput, I want to use a infinite loop to watch the message by using the GetDevice function in DirectInput. So I want to define a class which is to manage the listen thread.


Do my best to improve myself, to learn more and more...


#8 Maple Wan   Members   -  Reputation: 214

Like
0Likes
Like

Posted 17 September 2013 - 02:14 AM

 

Could you recommand some articles or books about c++ lower mechanisms and theory of c++ class. I always feel confused about some concepts in c++ class.

http://www.parashift.com/c++-faq/
 
http://www.parashift.com/c++-faq/memfnptr-vs-fnptr.html

 

Thanks, bro~

 

 

How to convert the function pointer in a class to the normal function pointer in C?

You cannot directly specify an instance method as method / callback parameter in Windows API in general, and not in CreateThread in particular. This is because internally instance methods have an additional parameter pointing to the class instance, so the method signature does not match the signature required by CreateThread.
The usual workaround is to have a static method, pass a pointer to the instance as lpParameter, and dispatch the call in the static method to an instance method, using that parameter.

class MsgListener
{
private:
    HANDLE _threadHandle;
    DWORD _threadId;
    static MsgListener *_instance;
    MsgListener();
    DWORD Listen();
    static DWORD WINAPI StaticListen(LPVOID param);
public:
    static MsgListener *GetInstance();
    void StartListen();
    void StopListen();
};

MsgListener *MsgListener::_instance = new MsgListener();
MsgListener::MsgListener() 
{ 
    _threadHandle = 0;
    _threadId = 0;
}
DWORD WINAPI MsgListener::StaticListen(LPVOID param) 
{
	MsgListener* listener = reinterpret_cast<MsgListener*>(param);
	return listener->Listen();
}
DWORD MsgListener::Listen() 
{ 
    // The method to run in a new thread....
	return 0;
}
MsgListener *MsgListener::GetInstance()
{
    if (!_instance)
        _instance = new MsgListener();
    return _instance;
}
void MsgListener::StartListen()
{
    this->_threadHandle = CreateThread(NULL, 0, &MsgListener::StaticListen, this, 0, &_threadId);
}
void MsgListener::StopListen()
{
    CloseHandle(_threadHandle);
}

However, I'd use the threading support in C++11 instead. It is so much easier to specify an arbitrary worker method, even an instance method, using the std::thread ctor:

http://en.cppreference.com/w/cpp/thread/thread/thread

 

Yeah, you are right. When I use a static method, the Singleton is meaningless, so I think I ought to change a design way to watch the device state. Thanks very much, bro.


Do my best to improve myself, to learn more and more...


#9 cdoubleplusgood   Members   -  Reputation: 835

Like
0Likes
Like

Posted 17 September 2013 - 02:21 AM


I want to create a new thread to watch the keyboard state and mouse state in DirectInput

Don't:

http://msdn.microsoft.com/en-us/library/windows/desktop/ee416842%28v=vs.85%29.aspx

"The use of DirectInput for keyboard and mouse input is not recommended. You should use Windows messages instead."


Edited by cdoubleplusgood, 17 September 2013 - 02:23 AM.


#10 cdoubleplusgood   Members   -  Reputation: 835

Like
0Likes
Like

Posted 17 September 2013 - 02:27 AM


When I use a static method, the Singleton is meaningless

You should avoid singletons, but not for this reason. The static thread method is just used to dispatch the call to the instance-specific handler. The "real" handler is not static.



#11 Maple Wan   Members   -  Reputation: 214

Like
0Likes
Like

Posted 17 September 2013 - 03:33 AM

 


When I use a static method, the Singleton is meaningless

You should avoid singletons, but not for this reason. The static thread method is just used to dispatch the call to the instance-specific handler. The "real" handler is not static.

 

Really thankful to you, I think I know what to do so. Thanks very very much.


Do my best to improve myself, to learn more and more...





Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS