Reputation: 2241
It is my understanding that the function called when starting a thread inside an object should not be a class member. The best approach seems to be to launch a friend function, which gets you access back into your object.
In general, the member function (and therefore, the parent thread) that launched the daughter thread can continue or it can return. In every case where I use this technique, I let the launcher method just return to the app in the parent thread that called it; something like Qt threads.
When the daughter thread has finished its work, the final thing it does is return into the friend function which itself returns to something waiting to catch its return (pthread_koin or WaitForSingleEvent) or, if there is no catcher, I guess you'd say it returns to nowhere.
So, here is the question. If there is no catcher for the return from the friend function, that is, the parent thread is not in a member function, can I safely destroy the object that launched the child thread from the friend function?
EDIT --------------------------------------------------------------------------
Obvious from the responses, I need an example. We'll go for Windows. Not that different from Linux. I have left out lots of stuff, the class definition, etc.
delete that
<<<=== the subject of this question.//================================================================= int main( int argc, char** argv ) { SomeObject* so = new SomeObject(); so->run(); while(1) { DoOtherTasks(); // but don't exit! } return 0; //================================================================= void SomeObject::run(); ( volatile DWORD ThreadId; // Thread ID HANDLE threadHandle; try { threadHandle = CreateThread( NULL, // default security attributes 0, // set stack size: default = 0 (LPTHREAD_START_ROUTINE)(SomeFriend), (LPVOID*)this, // func args: this 0, // default creation flags (LPDWORD)(&ThreadId) // ptr to thread identifier ); } catch ( ... ) { throw; } } // launches the thread and returns. //================================================================= void* SomeFriend( void* thisPtr ) // is a friend of SomeObject { SomeObject* that ((SomeObject*)thisPtr); that->Worker(); // HERE IS WHERE THE QUESTION IS TALKING ABOUT // CAN I DO THIS SAFELY? delete that; return (void*)NULL; } //================================================================= void SomeObject::Worker() // remember, this is run in the daughter thread. { // whatever return (void*)NULL; }
Upvotes: 1
Views: 273
Reputation: 4439
To answer your edited question, yes you can delete that;
However, remember that main()
or any functions it calls might not have a valid so
at any point in its logic after so->run()
was called because of the way the thread scheduler may have scheduled the threads.
Think of the thread as "owning" so
after you've called so->run()
. main()
and its stack descendants should never touch so
again without guarded logic.
Upvotes: 1
Reputation: 76305
There's no inherent reason for not launching a member function as the top-level function in a thread. C++11 handles it just fine:
struct S {
void f();
};
S s;
int main() {
std::thread thr(&S::f, s);
thr.join();
return 0;
}
Upvotes: 0
Reputation: 7292
Yes.
Your memory management code should be thread-safe already (or threading would be dangerous to start with!) so the free() itself should be fine. The destruction is fine as well, as long as you keep in mind that nobody else may have a reference to this object as they will be pointing to a destructed object.
The reason that people say that it should not be a class member is that member functions have a typically hidden pointer that's also treated differently on a byte level from other parameters, so you can't just call it as a normal function with an extra parameter. This makes it typically incompatible with the pthread_create and CreateThreadEx functions that have a specific calling convention they want. That's why you have a bouncer static / global / friend function that does this calling convention conversion for you (and probably so transparently that you don't notice it yourself).
Upvotes: 0