How to pass in the 'this' pointer to a C++ WinAPI thread? - c++

I am trying to run a C++ thread but also pass in the instance to the class itself. I cannot seem to figure it out.
I have a struct for parameters to the thread:
struct CLASS_PARAMS {
SomeClass* ptr;
};
I then call my setup method:
void SomeClass::setup() {
CLASS_PARAMS params;
params.ptr = this;
CreateThread(NULL, 0, SetupThread, &params, 0, NULL);
}
and right above SomeClass::setup(), I define SetupThread:
DWORD WINAPI SetupThread(LPVOID lpParam) {
CLASS_PARAMS* params = (CLASS_PARAMS *) lpParam;
SomeClass* inst = params->ptr;
....
....
}
However, I get read-access violations on using inst. I have other methods in SomeClass that I need to access via the thread:
inst->getSomeValue();
...
inst->setSomeValue(someValue);
...
but it will not allow me. Any suggestions on what I'm doing wrong?

You allocate CLASS_PARAMS on stack, so it is destroyed before used.
Allocate it dynamically, pass pointer and free it in the thread.
Alternatively, if you need to pass only this, pass it without wrapping structure, just cast to LPVOID and back (but be sure to use the same class pointer type to avoid pointer adjustment bugs)

Related

How to deal with multiple parameters of different types in C++98?

In order to implement a thread class(In C++98 and Windows.h). I have something like this:
Thread::Thread(_beginthreadex_proc_type fn)
{
m_raw = fn;
m_args = 0;
m_handle = 0;
m_id = 0;
}
The code above works fine it takes a function that not receive parameters, and with the next code it function is called by a new thread:
void Thread::Join()
{
m_handle = (HANDLE)_beginthreadex(0, 0, m_raw, (m_args ? m_args : 0), 0, 0);
if (m_handle) WaitForSingleObject(m_handle, INFINITE);
}
This code also works fine with functions that don't take any parameter.
Now my question is about how can i in C++98 receive variadic parameters in my constructor and save them.
And NO i can't use modern c++ if that was the case I din't need help. So plz don't give me solutions implemented with c++11 or higher.
Update
Now I'm trying a Java style solution in that every Thread is a IRunnable that have a pure virtual function named Run. And thread is almost the that this implementetation with the diff that is an abstract class. In this way can i avoid parameters because I don't pass the function instead of that I write another class that inherits from Thread and implements Run.
The code look like:
The interface
struct IRunnable
{
virtual void Run() = 0;
};
Thread class
class Thread : public IRunnable
{
HANDLE m_handle;
DWORD m_id;
typedef unsigned (__stdcall *Function)(void*);
_beginthreadex_proc_type m_raw;
void* m_args;
public:
Thread();
~Thread();
Thread(_beginthreadex_proc_type, void*);
Thread(_beginthreadex_proc_type);
unsigned GetId();
virtual void Run() = 0;
void Join();
unsigned int __stdcall call(void*);
};
Call only is a wrapper to call Run function member
unsigned int __stdcall Thread::call(void* data)
{
Run();
return 0;
}
My problem is here:
void Thread::Join()
{
m_handle = (HANDLE)_beginthreadex(0, 0, &this->call, 0, 0, 0);
if (m_handle) WaitForSingleObject(m_handle, INFINITE);
}
When i compiling in vs2019 the code above produce the next error:
error C2276: '&': illegal operation on bound member function expression
error C2660: '_beginthreadex': function does not take 5 arguments
For your edited question, the reason you're getting a compile error is because you're trying to send the address to a member function of your Thread object. You can't take pointers to member functions and use them without also keeping the object pointer around. Instead, you should make a global function that takes a Thread* as its argument, send a pointer to that function, and let it call your runnable.
unsigned thread_entry(void* thread_ptr)
{
Thread* thread = (Thread*) thread_ptr;
return thread->call();
}
void Thread::Join()
{
m_handle = (HANDLE)_beginthreadex(0, 0, thread_entry, this, 0, 0);
if (m_handle) WaitForSingleObject(m_handle, INFINITE);
}
P.S. It's usually best to ask new questions instead of editing old ones if the question is significantly different, which yours is.
If you look at pretty much any thread library, they very rarely support sending multiple arguments; you usually send a pointer to something, and if you want many things, you make a struct containing many things and send a pointer to it.
However, if you really want this, you could use the C varargs functions to iterate over all variadic arguments, and allocate a linked list with them, or allocate an array of them, or whatever other data structure you want. Then, send a pointer to that to your thread entry function. Your function would still be taking just one pointer, though.
In C, there is no easy way to construct a va_list, which is how variadic arguments are sent around. You can't just send the va_list you have on your main thread, because that memory won't be alive by the time it reaches your new thread. There is also no good way to expand a va_list to fill function arguments.
Btw, I realize you're using C++, but as far as C++98 goes, its varargs support is basically the same as in C, which is why I'm mentioning C in my answer.

What is the safest way to pass a unique_ptr through a function requiring a void* param?

I am creating a thread under Windows which requires a parameter block to be passed as a void* (LPVOID).
The calling function heap-allocates the parameter block, since the spawned thread may outlive the calling function. The calling function does not need to share ownership of the parameter block.
Here is my thinking so far:
...
using Functor = std::function<void()>
class SpawnData
{
public:
SpawnData(Functor func) : func(func) {}
Functor func;
};
DWORD WINAPI MyTaskLauncher(LPVOID ppRawData)
{
assert(ppRawData != nullptr);
//auto pData = *static_cast<std::unique_ptr<SpawnData>*>(ppRawData); //not permitted (A)
auto ppData = static_cast<std::unique_ptr<SpawnData>*>(ppRawData); //Feels safe, but...
assert(*ppRawData != nullptr);
(*ppRawData)->func(); //could dereference invalid memory?
}
ThreadId MyThreadSpawner(Functor func)
{
auto pData = std::make_unique<SpawnData>(func);
//CreateThread() is Windows API with a void* signature for the data param
... = CreateThread(..., static_cast<LPTHREAD_START_ROUTINE>(MyTaskLauncher),
static_cast<LPVOID>(&(pData.get())), ...); //Ugh... :(
threadId = ...;
return threadId;
}
My questions:
1) Would you agree that there is a race condition starting at the call to CreateThread() for MyTaskLauncher to re-wrap the raw pointer before MyThreadSpawner() exits?
2) Would you agree that Q1) is essentially moot because MyThreadSpawner()'s pData will be destroyed when it goes out of scope regardless of whether MyTaskLauncher had already "wrapped" its memory or not?
3) What's the safest way to strip, pass and re-wrap on the other side my smart pointer through the CreateThread() API?
Consider the following:
DWORD WINAPI MyTaskLauncher(LPVOID pRawData)
{
assert(pRawData != null)
auto pData = std::make_unique<SpawnData>(*static_cast<SpawnData*>(pRawData));
//signal MyThreadSpawner() that SpawnData is safely wrapped
//...do work...
return result;
}
ThreadId MyThreadSpawner(Functor func)
{
auto pData = std::make_unique<SpawnData>(func);
//CreateThread() is Windows API with a void* signature for the data param
... = CreateThread(..., static_cast<LPTHREAD_START_ROUTINE>(MyTaskLauncher),
static_cast<LPVOID>(pData.get()), ...); //Hmm...
threadId = ...;
//Wait for MyTaskLauncher to signal SpawnData is safely wrapped
return threadId;
}
4) Is this legal? For a time, there will be two, er, unique_ptrs pointing to the very same memory...
If I update this to use shared_ptr as follows:
//MyTaskLauncher:
...
auto pData = *static_cast<std::shared_ptr<SpawnData>*>(pRawData)); // (B)
...
//MyThreadSpawner:
auto pData = std::make_shared<SpawnData>(func);
...
5) The line marked (B), above is legal, whereas (A) far above (which does the same to a std::unique_ptr<SpawnData>*), is not. Can anyone shed some light on as to why?
6) And finally, any suggestions on simpler and/or safer techniques for passing safe data through a function signature requiring a void*?
Thanks in advance for your thoughts.
2) Would you agree that Q1) is essentially moot because MyThreadSpawner()'s pData will be destroyed when it goes out of scope regardless of whether MyTaskLauncher had already "wrapped" its memory or not?
Yes. That's what a unique_ptr is; it represents unique ownership. You're trying to break that.
3) What's the safest way to strip, pass and re-wrap on the other side my smart pointer through the CreateThread() API?
Define "safest". It's not clear why MyThreadSpawner is using a unique_ptr at all.
You are trying to transfer ownership of a unique_ptr. So you need to actually do that; the sender must lose ownership and the receiver must acquire it. That's pretty trivial:
DWORD WINAPI MyTaskLauncher(LPVOID pData)
{
assert(pData!= nullptr);
//Gain ownership of memory.
unique_ptr<SpawnData> pSpawnData(static_cast<SpawnData*>(pData));
pSpawnData->func();
}
ThreadId MyThreadSpawner(Functor func)
{
auto pData = std::make_unique<SpawnData>(func);
//CreateThread() is Windows API with a void* signature for the data param
... = CreateThread(..., static_cast<LPTHREAD_START_ROUTINE>(MyTaskLauncher),
//Lose ownership of memory.
static_cast<LPVOID>(pData.release()), ...);
threadId = ...;
return threadId;
}
5) The line marked (B), above is legal, whereas (A) far above (which does the same to a std::unique_ptr*), is not. Can anyone shed some light on as to why?
Legal in what sense? The void* does not point to a shared_ptr of any sort. Therefore casting it to a shared_ptr and then accessing it is not legal C++.
Just because your compiler just so happened to let you do it doesn't make it legal.
And finally, any suggestions on simpler and/or safer techniques for passing safe data through a function signature requiring a void*?
Yes: use std::thread. You can get a Win32 thread handle via thread::native_handle.

C++ - Passing an object to CreateThread() by ref

I'm not sure what the correct syntax is for this because it involves the winapi which i'm not familiar with. For example, i didnt know it won't let me xhangethe predefined thread function parameters from processClient(LPVOID) to processClient(LPVOID&).
I need to pass the "params" object by reference(just so theres no problems for now, even though im not going to change values in it) to the thread function "processClient()".
... struct(the object) declaration
struct ClientParams{
ClientParams::ClientParams():sock(INVALID_SOCKET), i(NULL){};
public:
SOCKET sock;
int i;
};
... in processClient(LPVOID lpParam){
SOCKET ClientSocket=(SOCKET)*lpParam->sock; ?? doesnt work
int i=*lpParam->i; ?? doesn't work
}
... in main{
ClientParams *params = new ClientParams();
params->i=some_value;
params->sock=ClientSocket;
CreateThread(
NULL, // don't inherit handle
0, // use default size for the executable
processClient,
(LPVOID)params, // thread data
0, // run right away
&i );
}
SOCKET ClientSocket=(SOCKET)*lpParam->sock; ?? doesnt work
lpParam has the same value it did when you passed it, in main, where it was 'params', of type 'ClientParams*', so you don't have any business dereferencing it with '*'. The rest of it is just a precedence problem. It should be
SOCKET ClientSocket=((ClientParams*)lpParam)->sock;
Access structure members must through the structure.
SOCKET ClientSocket=((ClientParams*)lpParam)->sock;

How can I begin thread in windows using functor as thread function without using C++11 thread?

I'm writing a simple thread lib for Windows. I want to pass this functor
struct callable
{
void operator()()
{
for(int i = 0; ;++i)
{
std::cout << i << std::endl;
}
}
};
In _beginthread() this way:
int main()
{
callable c;
_beginthread(c, 0, 0);
}
but it's not possible. The ability to pass functor in the thread is very necessary for my library. I know that boost::thread provides this ability, thus it is possible. How can I begin thread in windows using functor as thread function without using C++11 thread?
[upd] without using C++11 thread
The standard technique is as follows:
Define a struct to hold whatever information you need to pass to the thread. In your case that information is the callable functor. So, you already have a suitable struct at hand.
Allocate one of these structs on the heap. This happens in the calling thread, but the information is passed to the created thread which is why it cannot live on the stack.
Call CreateThread passing a suitable thread proc (more later), and the address of your struct in the lpParameter parameter.
In the thread proc, you are passed the address of the struct in lpParameter.
Cast that pointer to the appropriate type and call your functor.
Delete the heap allocated memory.
The thread proc looks like this:
DWORD WINAPI ThreadProc(void *lpParameter)
{
callable *c = (callable*)lpParameter;
(*c)();
delete c;
return 0;
}
And the call to CreateThread is along these lines:
callable *c = new callable;
// initialise c
CreateThread(NULL, 0, ThreadProc, (void*)c, 0, &threadID);
I apologise if there are syntax errors here, I'm not at all fluent in C++.

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.