Reputation: 2250
Well I'm trying to set a variable to use in a thread, it works fine if I call the pthread from the main function, but if I call it from a function or a function inside a class, the variable is lost and prints garbage instead, that's why I added the condition
if(this->pickup < 7)
so I minimized the code so I could post it here because it has all the examples I'm saying.
The output of this code below is:
Access by Class:
Hello, world! <
Access Directly:
Hello, world!, N: 6<
I would like to have the same result as in Access Directly in Access by Class, I want it to output the ", N: 6" because after all it was defined. what am I missing here?
I hope I was clear enough, thanks in advance.
(By the way, I'm using the pthread library that is available for windows) so here is the code:
#include <stdio.h>
#include <pthread.h>
#include <iostream>
#include <conio.h>
#include <windows.h>
class C {
public:
int pickup;
void *hello()
{
std::cout << "\nHello, world!";
if(this->pickup < 7)
std::cout << ", N: " << this->pickup;
std::cout << "<" << std::endl;
printf("HI");
return 0;
}
static void *hello_helper(void *context)
{
return ((C *)context)->hello();
}
void StartThread(){
C c;
c.pickup = 6;
pthread_t t;
pthread_create(&t, NULL, &C::hello_helper, &c);
}
};
int main () {
C c;
std::cout << "Access by Class: \n";
c.StartThread();
c.pickup = 6;
Sleep(2000);
std::cout << "\nAccess Directly: \n";
pthread_t t;
pthread_create(&t, NULL, &C::hello_helper, &c);
_getch();
return 0;
}
Upvotes: 2
Views: 1582
Reputation: 58578
Note that StartThread
creates a C
object which is produced neither from any argument material (StartThread
takes no arguments) nor from any member material of the classt of which StartThread
is a member. I.e you can have this:
void StartThread(){
pthread_t t;
pthread_create(&t, NULL, &C::hello_helper, NULL);
}
// The code is easily moved into the thread.
static void hello_helper(void *)
{
C c;
c.pickup = 6;
}
Furthermore, is it possible that you actually wanted this?
void StartThread(){
pthread_t t;
pickup = 6;
// use THIS object, not some new one, doh?
pthread_create(&t, NULL, &C::hello_helper, (void *) this);
}
I.e. maybe you actually want obj.StartThread()
to start a thread which works with obj
rather than creating some other object internally?
Upvotes: 0
Reputation: 121971
c
is destroyed when StartThread()
returns, meaning hello_helper()
is using a dangling pointer resulting in undefined behaviour.
Change to:
void StartThread(){
C* c = new C();
c->pickup = 6;
pthread_t t;
pthread_create(&t, NULL, &C::hello_helper, c);
}
Remember to delete
the argument passed into hello_helper()
:
static void *hello_helper(void *context)
{
C* c = static_cast<C*>(context);
c->hello();
delete c;
return 0;
}
EDIT:
Always delete
ing the argument passed into hello_helper()
would prevent passing stack allocated objects into hello_helper()
. A mechanism is required to instruct hello_helper()
whether it is responsible for destructing its argument.
Upvotes: 2
Reputation: 32510
The call to pthread_create()
returns instantly, therefore you exit from the C::StartThread
function before your spawned thread really has a chance to run. Thus the C
instance object represented by c
doesn't exist anymore since it was an automatic variable on the stack of StartThread
. You need to make sure the life-time of c
exists beyond the stack of StartThread
, which is typically done using dynamic memory, or possibly a static variable, etc.
Upvotes: 0
Reputation: 12287
The C
you're starting the thread with in StartThread()
goes out of scope and is destructed before the thread you are creating has a chance to use it.
If you know the class instance you're calling StartThread()
on will exist for the life of the thread, perhaps you want to pass this
as the context rather than a new stack object:
void StartThread() {
pthread_t t;
pthread_create(&t, NULL, &C::hello_helper, this);
}
Upvotes: 1