So, I have been trying to figure out how c++ multi-threading works and how to apply it to the project I am working on. I am trying to accomplish creating a new thread and running a function on that thread. The function I am trying to run is called SetupInfo and takes an Individual as a single parameter. I have seen examples of this and have tried to implement them, but after multiple attempts I cannot successfully pass the parameter I need into the thread I want the function to run on. Here is what I have come up with:
Here I create a struct to store the pointer to the Individual that I need later on.
struct ThreadData
{
Individual *m_pInd;
ThreadData(Individual pInd) : m_pInd(*pInd) {}
};
Here I create a function that I can call in my program that creates the thread that runs the function SetupThreadFunction which takes a void pointer as a parameter. I am trying to pass the variable data into this function and then cast it back to ThreadData to be able to access the items of the struct.
void SetupThread(Individual input)
{
ThreadData *data = new ThreadData(input);
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) SetupThreadFunction, data , 0, 0);
delete data;
}
Here I create the function that is passed into the CreateThread function which takes a void pointer and casts it to ThreadData which can then theoretically access the threadData->m_pInd. The same pointer for data above is passed correctly into the SetupThreadFunction. However, m_pInd contains null data and not the pointer to the information that is expected. Why is that?
DWORD WINAPI SetupThreadFunction(LPVOID lpParameter)
{
ThreadData* threadData = (ThreadData*)lpParameter;
SetupInfo(threadData->m_pInd);
return 0;
}
Is there a more correct way to pass a parameter into the new win32 thread I am creating?
The correct pattern is to allocate the object with new, fill in the data (if not done through parameters to new), pass the pointer to the newly-created thread, and let the thread delete the object when it's done with it. You delete the object before you know the thread has even started!
This isn't a multithreading problem; it's a pointer problem.
This line doesn't make sense to me:
ThreadData(Individual pInd) : m_pInd(*pInd) {}
m_pInd is a pointer and yet you're initializing it with *pInd which means you want to dereference pInd, but pInd is not a pointer, let alone a pointer to a pointer. I don't see how this would even compile.
Assuming you actually meant & instead of *, as in:
ThreadData(Individual ind) : m_pInd(&ind) {}
The problem here is that you're creating a pointer to a copy of an Individual on the stack, and that copy goes away upon return from the constructor, so you have a dangling pointer.
Use std::thread.
void ThreadProc(Individual individual);
int main()
{
Individual individual;
std::thread thread(ThreadProc, individual);
thread.join();
return 0;
}
Here's a simple code example to demonstrate the points already discussed.
#include "stdafx.h" // includes <windows.h>, <string> and <iostream>
using std::string;
using std::cout;
class Individual
{
public:
string s;
};
struct ThreadData
{
Individual *m_pInd;
ThreadData(Individual* pInd) : m_pInd(pInd) {}
};
DWORD WINAPI SetupThreadFunction(LPVOID lpParameter)
{
cout << "Hi From Thread\n";
ThreadData* threadData = static_cast<ThreadData*>(lpParameter);
//SetupInfo(threadData->m_pInd);
// do delete here, once its finished with.
delete threadData;
return 0;
}
HANDLE SetupThread(Individual* input)
{
ThreadData *data = new ThreadData(input);
return CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) SetupThreadFunction, data , 0, 0);
}
int _tmain(int argc, _TCHAR* argv[])
{
cout << "Hi\n";
Individual* i = new Individual;
HANDLE h = SetupThread(i);
if(h)
{
WaitForSingleObject(h, INFINITE);
cout << "Done\n";
} else
{
cout << "Couldnt create thread\n";
}
getchar();
delete i;
return 0;
}
Bear in mind also you can use _beginthread as a simpler interface to launch a thread on Win32.
Related
Sometimes my application crash when executing pthread_join and sometime it is OK. Can someone please advise what could be the problem with my code below?
functionA will pass some arguments and create a thread that do some calculation and store the result into ResultPool (global) for later use. The functionA will be called few times and each time it passes different arguments and create a new thread. All the thread_id will be store in global variable and at the end of the execution, the thread_id will be retrieved from the ThreadIdPool and check the completion of the thread, and then output the result from the ResultPool. The thread status checking and output the result are at different class and the ThreadIdPool is a global variable.
The threadCnt will be initialized to -1 before start of functionA and it is defined somewhere in my code.
int threadCnt;
struct ThreadData
{
int td_tnum;
float td_Freq;
bool td_enablePlots;
int td_ifBin;
int td_RAT;
};
typedef struct ThreadData structThreadDt;
void *thread_A(void *td);
map<int, float> ResultPool;
map<int, pthread_t> ThreadIdPool;
pthread_mutex_t mutex2 = PTHREAD_MUTEX_INITIALIZER;
pthread_t thread_id[10];
void FunctionA(int tnum, float msrFrequency, bool enablePlots)
{
//Pass the value to the variables.
int ifBin;
int RAT;
/*
Some calculation here and the results are assigned to ifBin and RAT
*/
structThreadDt *td;
td =(structThreadDt *)malloc(sizeof(structThreadDt));
td->td_tnum = tnum;
td->td_Freq = msrFrequency;
td->td_enablePlots = enablePlots;
td->td_ifBin = ifBin;
td->td_RAT = RAT;
threadCnt = threadCnt+1;
pthread_create(&thread_id[threadCnt], NULL, thread_A, (void*) td);
//Store the thread id to be check for the status later.
ThreadIdPool[tnum]=thread_id[threadCnt];
}
void* thread_A(void* td)
{
int ifBin;
int RAT;
bool enablePlots;
float msrFrequency;
int tnum;
structThreadDt *tds;
tds=(structThreadDt*)td;
enablePlots = tds->td_enablePlots;
msrFrequency = tds->td_Freq;
tnum = tds->td_tnum;
ifBin = tds->td_ifBin ;
RAT = tds->td_RAT;
/*
Do some calculation here with those ifBIN, RAT, TNUM and frequency.
*/
//Store the result to shared variable with mutex lock
pthread_mutex_lock( &mutex2 );
ResultPool[tnum] = results;
pthread_mutex_unlock( &mutex2 );
free(tds);
return NULL;
}
And here is the threadId status checking. It will first iterate the ThreadIdPool to retrieve the threadID and check the completion of the thread. If the thread is completed, it will output the result. The pthread_join execution will sometimes crash my application.
void StatusCheck()
{
int tnum;
pthread_t threadiD;
map<int, pthread_t>::iterator itr;
float res;
int ret;
//Just to make sure it has been done
for (itr = ThreadIdPool.begin(); itr != ThreadIdPool.end(); ++itr) {
tnum = itr->first;
threadiD = itr->second;
//Check if the thread is completed before get the results.
ret=pthread_join(threadiD, NULL);
if (ret!=0)
{
cout<<"Tnum="<<tnum<<":Error in joining thread."<<endl;
}
res = ResultPool[tnum];
cout<<"Results="<<res<<endl;
}
}
This will be a global answer :
First of all, your code is 99% C and 1% C++. I don't know why, but if you want to write C++ write C++, not C like code. Or do C, that can be what you need.
For example, you are using ton of global function, static array, raw pointers etc. Replace them with classes and methods, std::array, smart_pointers etc. The STL is here to be used. You can write a class to wrap your pthread object and, instead of having free functions, use a constructor. If smart pointers are not available, replace your mallocs / free with (at least) new and delete. By the way, NULL as its equivalent in nullptr in C++.
Secondly, DO NOT USE GLOBAL VARIABLES. It is not necessary in 99.99% of the case as it can be variable declared then passed as pointers / references to functions.
For what can crash your program there are several things to test :
Are you variables correctly initialized ?
You said that threadCount is initialized with -1. Why ? Since it is a count it should has start at 0, or maybe it is an index and not a count.
If you can, give use more informations :
Where are these functions used, and how, by who ?
What is you compiler and which version are you using ?
What is the C++ version you are using ?
What is the goal of this projet ? Maybe there are better ways of doing it.
One problem I see is that when you collect the data there is an access to result_pool without a lock. One of the threads that is still running could be accessing result_pool adding more keys to it at the same time you're accessing it to collect the data.
I'm trying to send data from my application to the GLFW keyCallback where I then access and modify that data. However, nothing I pass in can be accessed or changed without an app crash. What am I doing wrong?
//main.cpp
typedef struct
{
string type, name;
} DebugUsrPtr;
//hot loop
{
DebugUsrPtr myPtr;
myPtr.type = "aaa";
myPtr.name = "bbb";
void *testPtr = &myPtr;
glfwSetWindowUserPointer(myWin, testPtr);
glfwSetKeyCallback(myWin, keyCallback0);
glfwSetWindowUserPointer(myWin, myWin);
}
//input.cpp
void keyCallback0(GLFWwindow *window, int key, int scancode, int action, int mods)
{
auto *myTest = static_cast<DebugUsrPtr*>(glfwGetWindowUserPointer(window));
cout << "name test = " << myTest->name << endl; // ""
myTest->name = "zzzz"; //prints "zzzz" for one frame then appcrash
}
On this line:
glfwSetWindowUserPointer(myWin, myWin);
When you set that, the user pointer will now point to the window structure, not your struct. So when the callback is called (it is called later), it no longer points to your debug structure, but to the windows pointer.
You need to send the pointer to your structure and let it there as long as you think you will need it.
You have another error, the debug structure is destroyed before the callback is called:
{
DebugUsrPtr myPtr;
myPtr.type = "aaa";
myPtr.name = "bbb";
void *testPtr = &myPtr;
glfwSetWindowUserPointer(myWin, testPtr);
glfwSetKeyCallback(myWin, keyCallback0);
glfwSetWindowUserPointer(myWin, myWin);
} // debug structure destroyed here!
So when the callback is called later, it the debugs structure will be freed, and that will lead to undefined behaviour!
For that, I think you should declare your struct in the parent scope of your event loop. Just like this:
DebugUsrPtr myPtr;
// ...
{
glfwSetWindowUserPointer(myWin, &myPtr);
glfwPollEvents(); // the callback will be called here if user press keys!
}
If you're really doing C++, declare your struct like this instead:
struct DebugUsrPtr {
std::string type, name;
};
If you want a different type or a different pointer for each callback, hold them all in a bigger struct:
struct AllPointers {
DebugUsrPtr dbg;
MouseUsrPtr mouse;
// more...
};
I want to pass a class object into a method of other class through a thread call, I tried but got the error can any one help me on this.please.
struct sample{
int status;
std::vector <std::string> a_row;
size_t column_count;
std::vector <std::string> column;
};
class sess {
public:
int a;
sess(int);
sess();
};
class Gen {
private:
static Gen* gen_obj;
public:
static bool Gen_InstanceFlag;
static Gen* GetInstance();
sample addition(sess);
};
/* End of Header File */
/* Beginning of cpp File */
include"Class_thread_mixing.h"
bool Gen::Gen_InstanceFlag=false;
Gen* Gen::GetInstance(){
if(!Gen::Gen_InstanceFlag){
Gen::gen_obj = new Gen();
Gen::Gen_InstanceFlag= true;
return gen_obj;
}
else {
return gen_obj;
}
}
sample addition(sess ses_obj){
sample sam;
sam.a_row.push_back("success");
sam.column.push_back("result");
sam.column_count=1;
sam.status=ses_obj.a;
return sam;
}
int main(int argc, char* argv[])
{
HANDLE myhandleA;
Gen* gen=Gen::GetInstance();
sess ses_obj(10);
myhandleA=(HANDLE)_beginthreadex(0, 0, gen->addition(ses_obj),(void*)0, 0, 0);
WaitForSingleObject(myhandleA, INFINITE);
CloseHandle(myhandleA);
getchar();
return 0;
}
This is my code and I am getting an error like "error C2665: '_beginthreadex' : none of the 2 overloads could convert all the argument types"
Can any one suggest me who can I pass the object of sess to a function in a thread call and how can I get the results from the thread.
Thanks for your answers..
s there any option such that I can call the function directly in the thread without calling a standalone thread function, like I mentioned in my code [(HANDLE)_beginthreadex(0, 0, gen->addition(ses_obj),(void*)0, 0, 0) ]
I need to call addition method in the thread can any body help me on this.
The problem here is that instead of passing a function to the called by _beginthreadex, you are actually calling that function with an argument, causing the _beginthreadex function to be called with the return value from Gen::addition. This structure is if course not a function, and so the compiler complains.
The solution to this is not straightforward though. First of all because a stand-alone function (as required by _beginthreadex is not the same as a class member function. The reason being that all class member functions actually have a "zeroeth" hidden argument, and that is an instance of the class that becomes the this pointer that can be used inside member functions.
The best solution is probably to create a stand-alone function, which takes as argument a pointer to a structure, and the structure contains the object instance, and the argument to the actual member function.
Something like this:
struct call_data
{
sess sess_obj;
Gen* gen_obj;
};
static void thread_function(void* data)
{
call_data *call = reinterpret_cast<call_data*>(data);
// Do the actual member function call
call->gen_obj->addition(call->sess_obj);
}
int main()
{
...
call_data call = { ses_obj, gen };
myhandleA=(HANDLE)_beginthreadex(0, 0, thread_function, &call, 0, 0);
...
}
Entry point for thread can't be a class method. it has to be static or at global scope.
You need to define a static method like this
static unsigned ThreadEntry(void* arg)
{
sess *p = (sess*)arg;
Gen::GetInstance()->addition(*p);
}
and run the thread like this:
sess ses_obj(10);
myhandleA=(HANDLE)_beginthreadex(0, 0, ThreadEntry,(void*)&ses_obj, 0, 0);
I have this code:
typedef struct {
string fName;
string str;
}t;
//-------Other functions------//
void BeginTh()
{
string arg = "yes";
t *arglist;
arglist = (t*)malloc(sizeof(t));
arglist->fName = "comBomber";
arglist->str = arg;
_beginthread(startOver, 0, (void*)arglist);
free(arglist);
}
And at 'arglist->fName = "comBomber";' i get this error:
An unhandled exception of type 'System.AccessViolationException' occurred in <appname>
Additional information: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
Anyone can help me ? How solve this problem ?
Thanks.
I suggest modern C++ style:
#include <future>
#include <string>
struct arg_t {
std::string fName;
std::string str;
};
int startOver(int i, arg_t args)
{
return args.fName.size() + args.str.size() + 42;
}
int main()
{
const std::string arg = "yes";
arg_t args = { "comBomber", arg };
auto worker = std::async(startOver, 0, args);
return worker.get();
}
See it on http://ideone.com/zrXcwH (it doesn't run because ideone doesn't support the pthread library). I tested this with MS Visual C++.
If arg_t would be very expensive to copy, you can simply move it to the other thread:
auto worker = std::async(startOver, 0, std::move(args));
One problem is that your t instance is not properly initialized. You can fix that by it by using new instead of malloc Your struct holds a string, whose constructor needs to be called. Calling new ensures that the t object gets constructed properly.
t* arglist = new t;
then "free" the memory by calling delete:
delete arglist;
This points to the second problem, which is that your t instance must be guaranteed to be alive during the whole execution of the thread. You should not de-allocate its memory until the thread is finished. This is a C++ example where the t object is guaranteed to outlive the thread:
#include <thread>
int main()
{
t arglist = whatever;
std::thread t(startover, &whatever); // launches thread which runs startover(&arglist)
// do other stuff
t.join(); // wait for thread execution to finish
}
In general, Instead of using raw pointers to dynamically allocated objects, you should use a smart pointer.
As an aside, the typedef syntax for declaring a struct looks pretty strange in C++. Normally, you would do this:
struct t {
string fName;
string str;
};
malloc will only allocate memory for object but will not call its constructor
you need change to new
t *arglist = new t;
Also, do not release arglist memory block before the startOver thread gets its content. you can release it inside the thread or somewhere else.
void startOver(void* param)
{
Param* param_ = (Param*)param; // get hold of param pointer
while(true){
// do something
}
delete param_; // release param when thread finishes
}
void BeginTh()
{
Param *param = new Param();
param->fName = "abcd";
param->str = "yes";
_beginthread(startOver, 0, (void*)param);
}
// compile with: g++ 1.cc -o test -Wall `pkg-config --cflags --libs glib-2.0` -lgthread-2.0
// or g++ 1.cc -o testq -lglib-2.0 -I/usr/include/glib-2.0 -I/usr/lib64/glib-2.0/include/ -lgthread-2.0c
#include <glib.h>
#include <iostream>
#include <string.h>
int counter;
GAsyncQueue *q;
typedef struct MyStruct {
int foo;
char *data;
} *MyStructPtr;
gpointer looper(gpointer data) {
g_thread_init(NULL);
while (1) {
while (g_async_queue_length(q) > 0) {
MyStructPtr xtransport;
xtransport = new struct MyStruct;
xtransport = (MyStructPtr)g_async_queue_try_pop(q);
// The actual code is acting as weird, as if we have here, xtransport->data = last_text_value_ever_received;
std::cout << "str # " << xtransport->foo << ":" << xtransport->data << ":str\n";
}
}
}
void adder(char *data) {
char *processedData;
// someExternalAPICallToprocessData(data, &processeddata);
processedData = (char *)data;
MyStructPtr dtransport;
dtransport = new struct MyStruct;
dtransport->data = processedData;//processeddata;
dtransport->foo = ++counter;
g_async_queue_push(q, (gpointer*) dtransport);
}
int main() {
GThread *l;
g_thread_init(NULL);
q = g_async_queue_new();
l = g_thread_create(looper, NULL, FALSE, NULL);
sleep(2);
char *t;
t = strdupa("1111");
adder(t);
t = strdupa("222");
adder(t);
sleep (5);
}
This is a working lab mockup of some larger project. On the project, a strange behavior is noticed;
instead of main(), we're sitting in a callback function, that gets some data from a system component. Trying to print (e.g. cout) that data before putting to queues, can get something like:
N1 (in Callback): aaaabbbbcccc
N2 (in Callback): bbbbaaaacccc.
Same, if the access to (newly set pointer ) dtransport->data is made in a same code where it was created (mainloop/callback function)t; that's fine.
But can't get the correct value of the first elements in the queue! Data fields is always the same - accessing the collected data via queue, can get only the value that was set in last callback; evil pointer hell supposed!
str #1: bbbbaaaacccc.
str #2: bbbbaaaacccc.
Callback function is defined as:
int someExternalAPICallToprocessData(...., unsigned char ** data);
It returns data's length, and ** - returns pointer to pointer? So it is address problem.
The question is, would that
someExternalAPICallTOprocessData() fill &processeddata with a pointer to a fixed address storing only the data of last call?
How to get a copy of char* being returned and safely put it into MyStruct ?Note, that a next function uses offsets...
process(dequeued->data);
void process(char *data) {
my *ptr = NULL;
ptr = data + SOME_SIZE_CONST
...
}
And somehow, memcpy'ng the content of processedData seems to segfault the .so library which contains someExternalAPICallTOprocessData(). In the mockup context, it is the end of adder(); in the real context it is end of callback function to kernel networking stuff; so funny.
does that
someExternalAPICallTOprocessData()
would fill &processeddata with a fixed
address of data per each call
This is a little difficult to parse, but were it "could someexternalApi(&data) set data to be the same address on each call", then yes, it could. I have no idea what the "someExternalApi..." is, however, you have to consult its documentation.
You can handle this by using strdup on the returned processedData, or by changing MyStruct::data to a std::string (which would take the burden of correctly deleting the string off you).
looks like your push/pop stack is not thread safe. Imagine, when you push the struct onto the queue, it copies the foo first (and increments the # of items on the stack), that causes the while loop to pop the data from the stack, and then the data gets copied. oops.
The answer in this case, is to make sure that all reads and writes to the stack are atomic - stick a mutex or critical section around all calls to it.