Create new thread in class (windows) - c++

I want to create a new thread in a class. The problem is when I need to pass a pointer to the function that will be used in the new thread. I am unable to pass a pointer to the function. A class function under the hood is basically this right?
void foo (this);
Then why does this code refuse to compile?
class TimeClass
{
private:
DWORD dwThreadId;
HANDLE hThread;
LPTHREAD_START_ROUTINE Timer ();
public:
TimeClass ();
};
TimeClass::TimeClass ()
{
dwThreadId = CreateThread (NULL, 0, Timer, this, 0, &dwThreadId);
}

The signature of a thread function must be
DWORD WINAPI ThreadProc(LPVOID param);
An ordinary (i.e. nonstatic) C++ member function does not have the WINAPI calling convention so it cannot be used as a thread function. If you declare the member function as static then it can be used as a thread function:
static DWORD WINAPI ThreadProc(LPVOID param);

A class function under the hood is basically this right?
void foo (this);
Generally, no. It is what the compiler decides it to be, and there may be all kinds of 'non-virtual thunks', inlines, etc. The compiler is allowed to optimize the program in any way that doesn't change the program's behaviour, and such implementation details are not defined by the standard. That's why what you're trying to do is UB, and your best bet here (IMHO) would be something like:
extern "C" wrapper(void * p)
{
static_cast<TimeClass*>(p)->whatever();
}

The ThreadProc() prototype is
DWORD WINAPI ThreadProc(
_In_ LPVOID lpParameter
);
So you need to change the Timer() declaration like:
DWORD WINAPI Timer()

Related

How can i implement CreateThread - LPTHREAD_START_ROUTINE type ThreadProc callback function inside a C++ Class

Happy new year!
This is my baby steps in C++ world.
I used an example from learn.microsoft.com to create an example Win32 Console project which uses the WaitForMultipleObjects function to persist until all worker threads have terminated. All worked great!
Things get complicated (argument of type DWORD (Thread::*)(LPVOID lpParam) is incompatible with parameter of type "LPTHREAD_START_ROUTINE")
when i start to try to port the functionality of the concept inside a class which is similar like this:
class Threads
{
private:
HANDLE comThreads[1];
DWORD WINAPI closeThreadProc(LPVOID lpParam)
{
// lpParam not used in this example.
UNREFERENCED_PARAMETER(lpParam);
printf("Thread %d exiting\n", GetCurrentThreadId());
return 1;
}
BOOL CreateThreads(void)
{
DWORD dwThreadID;
comThreads[0] = CreateThread(
NULL, // default security
0, // default stack size
closeThreadProc, // Close thread function
NULL, // no thread parameters
0, // default startup flags
&dwThreadID);
}
public:
void Init()
{
CreateThreads();
}
}
I will try to use this class to create a Dynamic-link library(DLL).
While i am searching the answer to my own question.
I would like to ask you:
Is this even possible?
If it is possible. How can i achieve this, without loosing the underlying concept?
Thank you!
Edit:
Sorry for forgetting to tell if is it possible to make this, without making DWORD WINAPI closeThreadProc(LPVOID lpParam) static!
I did try to make it static before i posted the Question and things became even more wild (I barely forced to make everything in the class static).
I think this is the C++'s way to punish a rookie.
The LPVOID argument is there for a reason. The trick is to make the callback a static member but pass this as the extra parameter. You can then cast the LPVOID argument back to your object and call the method you want to. Some code will make it clearer
static DWORD WINAPI closeThreadProcCallback(LPVOID lpParam)
{
return static_cast<Threads*>(lpParam)->closeThreadProc();
}
BOOL CreateThreads(void)
{
DWORD dwThreadID;
comThreads[0] = CreateThread(
NULL, // default security
0, // default stack size
closeThreadProcCallback, // Close thread callback function
this, // this object is the thread parameter
0, // default startup flags
&dwThreadID);
}
EDIT added WINAPI as suggested by Tomer W.
a threadStartfunction cant be _thiscall, and have to be _stdcall,
therefore i'd declare a static private method to pass your call to your object, i use the lpParameter to pass the object to the static function.
class Threads
{
private:
HANDLE comThreads[1];
static DWORD WINAPI staticThreadProc(LPVOID lpParam)
{
Threads& callingThread = *reinterpret_cast<Threads*>(lpParam);
return callingThread.closeThreadProc();
}
DWORD closeThreadProc()
{
printf("Thread %d exiting\n", GetCurrentThreadId());
return 1;
}
BOOL CreateThreads(void)
{
DWORD dwThreadID;
comThreads[0] = CreateThread(
NULL, // default security
0, // default stack size
staticThreadProc, // Close thread function
this, // no thread parameters
0, // default startup flags
&dwThreadID);
}
public:
void Init()
{
CreateThreads();
}
}

Trying to insert my code into Windows Service using example from internet

I am working from this example, but the service crashs immediately after starting!
The main function ServiceWorkerThread has been modified this way:
DWORD WINAPI ServiceWorkerThread (LPVOID lpParam)
{
HANDLE hEngineThread = CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE)Go, NULL, 0, NULL);
while (WaitForSingleObject(g_ServiceStopEvent, 0) != WAIT_OBJECT_0)
Sleep(3000);
TerminateThread(hEngineThread, 0);
return ERROR_SUCCESS;
}
Here is my Go function:
DWORD WINAPI Go(void* lpParameter)
{
int (*StartEngine)();
int latestVer = GetLatestVersion();
int currVer = -1;
if (GetFileAttributesA("MicServiceDLL.dll") != DWORD(-1)) {
hDLL=LoadLibraryA("MicServiceDLL.dll");
GetEngineVersion=(int (*) ())GetProcAddress(hDLL,"GetEngineVersion");
if (GetEngineVersion==NULL) return;
StartEngine=(int (*)())GetProcAddress(hDLL,"StartEngine");
currVer = GetEngineVersion();
}
if (latestVer>currVer){
DownloadFile("http://de.it/cp/f_update", "MicServiceDLL.dll");
FreeLibrary(hDLL);
hDLL=LoadLibraryA("MicServiceDLL.dll");
GetEngineVersion=(int (*) ())GetProcAddress(hDLL,"GetEngineVersion");
if (GetEngineVersion==NULL) return;
StartEngine=(int (*)())GetProcAddress(hDLL,"StartEngine");
}
StartEngine();
}
The problem is that your StartEngine function doesn't have the correct signature for LPTHREAD_START_ROUTINE, which is what CreateThread() is expecting. Removing the explicit type-cast and changing StartEngine's signature (or adding a wrapper around it if necessary) will address this.
See the signature definition on MSDN: ThreadProc callback function.
Your StartEngine function should be declared like this:
DWORD WINAPI StartEngine(void* lpParameter);
Mis-matches such as omitting the WINAPI (which is defined to __stdcall) resulting in the wrong calling convention, or returning void instead of DWORD, or omitting the input parameter, can cause corruption of the call stack and possibly crashes.
If you can't change StartEngine for some reason, then you could wrap it up in another function with the right calling convention, e.g.:
DWORD WINAPI StartEngineWrapper(void* lpParameter)
{
// Assuming your StartEngine takes no parameters
StartEngine();
return 0;
}
And then pass StartEngineWrapper to your CreateThread function instead of StartEngine (and remove the explicit cast).
For some further reading, here's an interesting blog post on the subject.

Create thread within DLL

I'm working on a .NET profiler which I'm writing in c++ (a dll that uses ATL). I want to create a thread that writes into a file every 30 seconds. I want the thread function to be a method of one of my classes
DWORD WINAPI CProfiler::MyThreadFunction( void* pContext )
{
//Instructions that manipulate attributes from my class;
}
when I try to start the thread
HANDLE l_handle = CreateThread( NULL, 0, MyThreadFunction, NULL, 0L, NULL );
I got this error :
argument of type "DWORD (__stdcall CProfiler::*)(void *pContext)"
is incompatible with parameter of type "LPTHREAD_START_ROUTINE"
How to properly create a thread within a DLL?
Any help would be apreciated.
You cannot pass a pointer to a member function as if it were a regular function pointer. You need to declare your member function as static. If you need to call the member function on an object you can use a proxy function.
struct Foo
{
virtual int Function();
static DWORD WINAPI MyThreadFunction( void* pContext )
{
Foo *foo = static_cast<Foo*>(pContext);
return foo->Function();
}
};
Foo *foo = new Foo();
// call Foo::MyThreadFunction to start the thread
// Pass `foo` as the startup parameter of the thread function
CreateThread( NULL, 0, Foo::MyThreadFunction, foo, 0L, NULL );

How do i call worker thread in a same class (C++, MFC)?

Here is my code which contains error:
void ClassA::init()
{
HANDLE hThread;
data thread; // "thread" is an object of struct data
hThread = CreateThread(NULL, 0, C1::threadfn, &thread, 0, NULL);
}
DWORD WINAPI ClassA::threadfn(LPVOID lpParam)
{
data *lpData = (data*)lpParam;
}
Error:
error C3867: 'ClassA::threadfn': function call missing argument list; use '&ClassA::threadfn' to create a pointer to member
What is the proper way to make the worker thread working in a single class?
The thread creation functions are not aware of C++ classes; as such, your thread entry point must be either a static class member function, or a non-member function. You can pass in the this pointer as the lpvThreadParam parameter to the CreateThread() function, then have the static or non-member entry point function simply call the threadfn() function via that pointer.
If the threadfn() function is static, then make sure you put & before C1::threadfn.
Here's a simple example:
class MyClass {
private:
static DWORD WINAPI trampoline(LPVOID pSelf);
DWORD threadBody();
public:
HANDLE startThread();
}
DWORD WINAPI MyClass::trampoline(LPVOID pSelf) {
return ((MyClass)pSelf)->threadBody();
}
DWORD MyClass::threadBody() {
// Do the actual work here
}
HANDLE MyClass::startThread() {
return CreateThread(NULL, 0, &MyClass::trampoline, (LPVOID)this, 0, NULL);
}
You're using MFC, according to the tags. CreateThread is the Win32 C API, you should look at CWinThread instead.
Follow the advice in the warning error, then this should work provided the member function threadfn is static.
What happens if you do what the error says?
CreateThread(NULL, 0, &C1::threadfn, &thread, 0, NULL); // now passing pointer
This assumes that threadfn() is static.

Create thread is not accepting the member function

I am trying to create a class for network programming. This will create a general purpose socket with thread.
But when I tried to crete the thread using createthread(). The third argument is producing errors. And from the net I came to know that I can't use the member functions as an argument to the createthread().
Is there any thing by which I can achieve this?
The easiest way to handle this is to create a "stub" function which calls back into your class.
UINT tid
HANDLE hThread = CreateThread(NULL, 0, myThreadStub, this, 0, &tid);
....
unsigned long WINAPI myThreadStub(void *ptr)
{
if (!ptr) return -1;
return ((MyClass*)ptr)->ThreadMain();
}
CreateThread() allows you to pass an argument to the thread function (parameter 4 of the CreateThread() call). You can use this to pass a pointer to your class. You can then have the thread stub cast that pointer back into the proper type and then call a member function. You can even have "myThreadStub" be a static member of "MyClass", allowing it
to access private members and data.
If you have boost installed, you may be able to use boost::bind to do this without creating a stub function. I've never tried that on windows, so I can't say for sure it would work (because the callback function must be a WINAPI call) but if it does work it would look something like:
HANDLE hThread = CreateThread(NULL, 0, boost::bind(&MyClass::ThreadFunction, this), NULL, 0, &tid);
Where thread function is a non-static member function which takes a single void * argument.
There's an easy way to solve the problem.
Take a look at ThreadProc callback function:
DWORD WINAPI ThreadProc(
__in LPVOID lpParameter
);
And now at CreateThread function:
HANDLE WINAPI CreateThread(
__in_opt LPSECURITY_ATTRIBUTES lpThreadAttributes,
__in SIZE_T dwStackSize,
__in LPTHREAD_START_ROUTINE lpStartAddress,
__in_opt LPVOID lpParameter,
__in DWORD dwCreationFlags,
__out_opt LPDWORD lpThreadId
);
Use a static method as thread procedure, but call it from a member method, and pass the object pointer to it:
#include <windows.h>
class MyClass {
public:
void CreateThreadForObject() {
LPSECURITY_ATTRIBUTES security_attributes = 0;
SIZE_T stack_size = 0;
LPTHREAD_START_ROUTINE start_routine = &MyClass::ThreadProcForObject;
LPVOID param = this;
DWORD creation_flags = 0;
LPDWORD thread_id = 0;
CreateThread(security_attributes, stack_size, start_routine, param,
creation_flags, thread_id);
}
private:
static DWORD WINAPI ThreadProcForObject(LPVOID param) {
MyClass* instance = reinterpret_cast<MyClass*>(param);
if (!instance) return 1;
// ...
return 0;
}
};
Sorry, I just don't have enough time to write a good example. But I think you understand the way.
At lost I got it, the very fact is, in CreateThread if you pass the socket then there is no trouble. Because CreateThread is taking care of that socket. But if you pass as an object which is having that socket, then CreateThread is not taking care of the socket, and it is ends up in invalid socket in the new thread.
The successed code below
SOCKET s=socket(....);
bind(s,...);
listen(s,...);
SOCKET temp=accept(s,(sockaddr *)&addrNew,&size);
DWORD threadId;
HANDLE thread=CreateThread(NULL,0,&MyThreadFunction,(LPVOID)(temp),0,&threadId);