Thread::Join vs detach - c++

Why should I using std::thread::join and then wait until this thread has ended? I thougt the purpose of multithreading is, that I start more threads paralelly.
Instead of join(), I also could call the function "normally", like foo().
So why is their join()? Isn't the only thing I need detach()?

Consider what happens here:
int value = 0;
void myWorkerFunction(){value = 1;}
int main()
{
std::thread t(myWorkerFunction);
t.detach();
std::cout << value << std::endl;
}
You now have a race condition. Your thread may or may not complete all the work it needs to do before value needs to get printed.*
Consider join to be a form of synchronization like a mutex; you must wait for the executing thread to release the mutex (finish) before you can continue.
Sometimes it makes sense to detach a thread, if say, it can just "work in the background" performing tasks that may not be mission critical.
I thougt the purpose of multithreading is, that I start more threads paralelly [sic]
You are not forced to join a thread immediately after it is created. You can create N threads, and then go off and do some other work. Only when you want to guarantee that a thread has finished do you need to join.
*This example is way oversimplified for the sake of explanation. Often thread creation happens in some other object or function outside of main. Whether to detach or not is usually pretty obvious from your design. (however we must always detach or join a std::thread before it goes out of scope)

Related

c++ non blocking thread for sockets [duplicate]

Assume I'm starting a std::thread and then detach() it, so the thread continues executing even though the std::thread that once represented it, goes out of scope.
Assume further that the program does not have a reliable protocol for joining the detached thread1, so the detached thread still runs when main() exits.
I cannot find anything in the standard (more precisely, in the N3797 C++14 draft), which describes what should happen, neither 1.10 nor 30.3 contain pertinent wording.
1 Another, probably equivalent, question is: "can a detached thread ever be joined again", because whatever protocol you're inventing to join, the signalling part would have to be done while the thread was still running, and the OS scheduler might decide to put the thread to sleep for an hour just after signalling was performed with no way for the receiving end to reliably detect that the thread actually finished.
If running out of main() with detached threads running is undefined behaviour, then any use of std::thread::detach() is undefined behaviour unless the main thread never exits2.
Thus, running out of main() with detached threads running must have defined effects. The question is: where (in the C++ standard, not POSIX, not OS docs, ...) are those effects defined.
2 A detached thread cannot be joined (in the sense of std::thread::join()). You can wait for results from detached threads (e.g. via a future from std::packaged_task, or by a counting semaphore or a flag and a condition variable), but that doesn't guarantee that the thread has finished executing. Indeed, unless you put the signalling part into the destructor of the first automatic object of the thread, there will, in general, be code (destructors) that run after the signalling code. If the OS schedules the main thread to consume the result and exit before the detached thread finishes running said destructors, what will^Wis defined to happen?
The answer to the original question "what happens to a detached thread when main() exits" is:
It continues running (because the standard doesn't say it is stopped), and that's well-defined, as long as it touches neither (automatic|thread_local) variables of other threads nor static objects.
This appears to be allowed to allow thread managers as static objects (note in [basic.start.term]/4 says as much, thanks to #dyp for the pointer).
Problems arise when the destruction of static objects has finished, because then execution enters a regime where only code allowed in signal handlers may execute ([basic.start.term]/1, 1st sentence). Of the C++ standard library, that is only the <atomic> library ([support.runtime]/9, 2nd sentence). In particular, that—in general—excludes condition_variable (it's implementation-defined whether that is save to use in a signal handler, because it's not part of <atomic>).
Unless you've unwound your stack at this point, it's hard to see how to avoid undefined behaviour.
The answer to the second question "can detached threads ever be joined again" is:
Yes, with the *_at_thread_exit family of functions (notify_all_at_thread_exit(), std::promise::set_value_at_thread_exit(), ...).
As noted in footnote [2] of the question, signalling a condition variable or a semaphore or an atomic counter is not sufficient to join a detached thread (in the sense of ensuring that the end of its execution has-happened-before the receiving of said signalling by a waiting thread), because, in general, there will be more code executed after e.g. a notify_all() of a condition variable, in particular the destructors of automatic and thread-local objects.
Running the signalling as the last thing the thread does (after destructors of automatic and thread-local objects has-happened) is what the _at_thread_exit family of functions was designed for.
So, in order to avoid undefined behaviour in the absence of any implementation guarantees above what the standard requires, you need to (manually) join a detached thread with an _at_thread_exit function doing the signalling or make the detached thread execute only code that would be safe for a signal handler, too.
Detaching Threads
According to std::thread::detach:
Separates the thread of execution from the thread object, allowing
execution to continue independently. Any allocated resources will be
freed once the thread exits.
From pthread_detach:
The pthread_detach() function shall indicate to the implementation
that storage for the thread can be reclaimed when that thread
terminates. If thread has not terminated, pthread_detach() shall not
cause it to terminate. The effect of multiple pthread_detach() calls
on the same target thread is unspecified.
Detaching threads is mainly for saving resources, in case the application does not need to wait for a thread to finish (e.g. daemons, which must run until process termination):
To free the application side handle: One can let a std::thread object go out of scope without joining, what normally leads to a call to std::terminate() on destruction.
To allow the OS to cleanup the thread specific resources (TCB) automatically as soon as the thread exits, because we explicitly specified, that we aren't interested in joining the thread later on, thus, one cannot join an already detached thread.
Killing Threads
The behavior on process termination is the same as the one for the main thread, which could at least catch some signals. Whether or not other threads can handle signals is not that important, as one could join or terminate other threads within the main thread's signal handler invocation. (Related question)
As already stated, any thread, whether detached or not, will die with its process on most OSes. The process itself can be terminated by raising a signal, by calling exit() or by returning from the main function. However, C++11 cannot and does not try to define the exact behaviour of the underlying OS, whereas the developers of a Java VM can surely abstract such differences to some extent. AFAIK, exotic process and threading models are usually found on ancient platforms (to which C++11 probably won't be ported) and various embedded systems, which could have a special and/or limited language library implementation and also limited language support.
Thread Support
If threads aren't supported std::thread::get_id() should return an invalid id (default constructed std::thread::id) as there's a plain process, which does not need a thread object to run and the constructor of a std::thread should throw a std::system_error. This is how I understand C++11 in conjunction with today's OSes. If there's an OS with threading support, which doesn't spawn a main thread in its processes, let me know.
Controlling Threads
If one needs to keep control over a thread for proper shutdown, one can do that by using sync primitives and/or some sort of flags. However, In this case, setting a shutdown flag followed by a join is the way I prefer, since there's no point in increasing complexity by detaching threads, as the resources would be freed at the same time anyway, where the few bytes of the std::thread object vs. higher complexity and possibly more sync primitives should be acceptable.
Consider the following code:
#include <iostream>
#include <string>
#include <thread>
#include <chrono>
void thread_fn() {
std::this_thread::sleep_for (std::chrono::seconds(1));
std::cout << "Inside thread function\n";
}
int main()
{
std::thread t1(thread_fn);
t1.detach();
return 0;
}
Running it on a Linux system, the message from the thread_fn is never printed. The OS indeed cleans up thread_fn() as soon as main() exits. Replacing t1.detach() with t1.join() always prints the message as expected.
The fate of the thread after the program exits is undefined behavior. But a modern operating system will clean up all threads created by the process on closing it.
When detaching an std::thread, these three conditions will continue to hold:
*this no longer owns any thread
joinable() will always equal to false
get_id() will equal std::thread::id()
When the main thread (that is, the thread that runs the main() function) terminates, then the process terminates and all other threads stop.
Reference: https://stackoverflow.com/a/4667273/2194843
To allow other threads to continue execution, the main thread should terminate by calling pthread_exit() rather than exit(3).
It's fine to use pthread_exit in main. When pthread_exit is used, the main thread will stop executing and will remain in zombie(defunct) status until all other threads exit.
If you are using pthread_exit in main thread, cannot get return status of other threads and cannot do clean-up for other threads (could be done using pthread_join(3)). Also, it's better to detach threads(pthread_detach(3)) so that thread resources are automatically released on thread termination. The shared resources will not be released until all threads exit.
When the main process terminates all the worker threads created by that process are also killed. So, if the main() returns before a detached thread it created completes execution the detached thread will be killed by OS. Take this example:
void work(){
this_thread::sleep_for(chrono::seconds(2));
cout<<"Worker Thread Completed"<<endl;
}
int main(){
thread t(work);
t.detach();
cout<<"Main Returning..."<<endl;
return 0;
}
In the above program Worker Thread Completed will never be printed. Since main returns before the 2 second delay in the worker thread. Now if we change the code a little and add a delay greater than 2 seconds before main returns. Like:
void work(){
this_thread::sleep_for(chrono::seconds(2));
cout<<"Worker Thread Completed"<<endl;
}
int main(){
thread t(work);
t.detach();
cout<<"Main Returning..."<<endl;
this_thread::sleep_for(chrono::seconds(4));
return 0;
}
Output
Main Returning...
Worker Thread Completed
Now if a thread is created from any functions other than main the detached thread will stay alive until it's executions has completed even after the function returns. For example:
void child()
{
this_thread::sleep_for(chrono::seconds(2));
cout << "Worker Thread Completed" << endl;
}
void parent(){
thread t(child);
t.detach();
cout<<"Parent Returning...\n";
return;
}
int main()
{
parent();
cout<<"Main Waiting..."<<endl;
this_thread::sleep_for(chrono::seconds(5));
}
Output
Parent Returning...
Main Waiting...
Worker Thread Completed
A workaround to make main to wait for a detached worker thread before returning is to use condition_variable. For example:
#include <bits/stdc++.h>
using namespace std;
condition_variable cv;
mutex m;
void work(){
this_thread::sleep_for(chrono::seconds(2));
cout << "Worker Thread Completed" << endl;
cv.notify_all();
}
int main(){
thread t(work);
t.detach();
cout << "Main Returning..." << endl;
unique_lock<mutex>ul(m);
cv.wait(ul);
return 0;
}

STL thread detach, process hang [duplicate]

Assume I'm starting a std::thread and then detach() it, so the thread continues executing even though the std::thread that once represented it, goes out of scope.
Assume further that the program does not have a reliable protocol for joining the detached thread1, so the detached thread still runs when main() exits.
I cannot find anything in the standard (more precisely, in the N3797 C++14 draft), which describes what should happen, neither 1.10 nor 30.3 contain pertinent wording.
1 Another, probably equivalent, question is: "can a detached thread ever be joined again", because whatever protocol you're inventing to join, the signalling part would have to be done while the thread was still running, and the OS scheduler might decide to put the thread to sleep for an hour just after signalling was performed with no way for the receiving end to reliably detect that the thread actually finished.
If running out of main() with detached threads running is undefined behaviour, then any use of std::thread::detach() is undefined behaviour unless the main thread never exits2.
Thus, running out of main() with detached threads running must have defined effects. The question is: where (in the C++ standard, not POSIX, not OS docs, ...) are those effects defined.
2 A detached thread cannot be joined (in the sense of std::thread::join()). You can wait for results from detached threads (e.g. via a future from std::packaged_task, or by a counting semaphore or a flag and a condition variable), but that doesn't guarantee that the thread has finished executing. Indeed, unless you put the signalling part into the destructor of the first automatic object of the thread, there will, in general, be code (destructors) that run after the signalling code. If the OS schedules the main thread to consume the result and exit before the detached thread finishes running said destructors, what will^Wis defined to happen?
The answer to the original question "what happens to a detached thread when main() exits" is:
It continues running (because the standard doesn't say it is stopped), and that's well-defined, as long as it touches neither (automatic|thread_local) variables of other threads nor static objects.
This appears to be allowed to allow thread managers as static objects (note in [basic.start.term]/4 says as much, thanks to #dyp for the pointer).
Problems arise when the destruction of static objects has finished, because then execution enters a regime where only code allowed in signal handlers may execute ([basic.start.term]/1, 1st sentence). Of the C++ standard library, that is only the <atomic> library ([support.runtime]/9, 2nd sentence). In particular, that—in general—excludes condition_variable (it's implementation-defined whether that is save to use in a signal handler, because it's not part of <atomic>).
Unless you've unwound your stack at this point, it's hard to see how to avoid undefined behaviour.
The answer to the second question "can detached threads ever be joined again" is:
Yes, with the *_at_thread_exit family of functions (notify_all_at_thread_exit(), std::promise::set_value_at_thread_exit(), ...).
As noted in footnote [2] of the question, signalling a condition variable or a semaphore or an atomic counter is not sufficient to join a detached thread (in the sense of ensuring that the end of its execution has-happened-before the receiving of said signalling by a waiting thread), because, in general, there will be more code executed after e.g. a notify_all() of a condition variable, in particular the destructors of automatic and thread-local objects.
Running the signalling as the last thing the thread does (after destructors of automatic and thread-local objects has-happened) is what the _at_thread_exit family of functions was designed for.
So, in order to avoid undefined behaviour in the absence of any implementation guarantees above what the standard requires, you need to (manually) join a detached thread with an _at_thread_exit function doing the signalling or make the detached thread execute only code that would be safe for a signal handler, too.
Detaching Threads
According to std::thread::detach:
Separates the thread of execution from the thread object, allowing
execution to continue independently. Any allocated resources will be
freed once the thread exits.
From pthread_detach:
The pthread_detach() function shall indicate to the implementation
that storage for the thread can be reclaimed when that thread
terminates. If thread has not terminated, pthread_detach() shall not
cause it to terminate. The effect of multiple pthread_detach() calls
on the same target thread is unspecified.
Detaching threads is mainly for saving resources, in case the application does not need to wait for a thread to finish (e.g. daemons, which must run until process termination):
To free the application side handle: One can let a std::thread object go out of scope without joining, what normally leads to a call to std::terminate() on destruction.
To allow the OS to cleanup the thread specific resources (TCB) automatically as soon as the thread exits, because we explicitly specified, that we aren't interested in joining the thread later on, thus, one cannot join an already detached thread.
Killing Threads
The behavior on process termination is the same as the one for the main thread, which could at least catch some signals. Whether or not other threads can handle signals is not that important, as one could join or terminate other threads within the main thread's signal handler invocation. (Related question)
As already stated, any thread, whether detached or not, will die with its process on most OSes. The process itself can be terminated by raising a signal, by calling exit() or by returning from the main function. However, C++11 cannot and does not try to define the exact behaviour of the underlying OS, whereas the developers of a Java VM can surely abstract such differences to some extent. AFAIK, exotic process and threading models are usually found on ancient platforms (to which C++11 probably won't be ported) and various embedded systems, which could have a special and/or limited language library implementation and also limited language support.
Thread Support
If threads aren't supported std::thread::get_id() should return an invalid id (default constructed std::thread::id) as there's a plain process, which does not need a thread object to run and the constructor of a std::thread should throw a std::system_error. This is how I understand C++11 in conjunction with today's OSes. If there's an OS with threading support, which doesn't spawn a main thread in its processes, let me know.
Controlling Threads
If one needs to keep control over a thread for proper shutdown, one can do that by using sync primitives and/or some sort of flags. However, In this case, setting a shutdown flag followed by a join is the way I prefer, since there's no point in increasing complexity by detaching threads, as the resources would be freed at the same time anyway, where the few bytes of the std::thread object vs. higher complexity and possibly more sync primitives should be acceptable.
Consider the following code:
#include <iostream>
#include <string>
#include <thread>
#include <chrono>
void thread_fn() {
std::this_thread::sleep_for (std::chrono::seconds(1));
std::cout << "Inside thread function\n";
}
int main()
{
std::thread t1(thread_fn);
t1.detach();
return 0;
}
Running it on a Linux system, the message from the thread_fn is never printed. The OS indeed cleans up thread_fn() as soon as main() exits. Replacing t1.detach() with t1.join() always prints the message as expected.
The fate of the thread after the program exits is undefined behavior. But a modern operating system will clean up all threads created by the process on closing it.
When detaching an std::thread, these three conditions will continue to hold:
*this no longer owns any thread
joinable() will always equal to false
get_id() will equal std::thread::id()
When the main thread (that is, the thread that runs the main() function) terminates, then the process terminates and all other threads stop.
Reference: https://stackoverflow.com/a/4667273/2194843
To allow other threads to continue execution, the main thread should terminate by calling pthread_exit() rather than exit(3).
It's fine to use pthread_exit in main. When pthread_exit is used, the main thread will stop executing and will remain in zombie(defunct) status until all other threads exit.
If you are using pthread_exit in main thread, cannot get return status of other threads and cannot do clean-up for other threads (could be done using pthread_join(3)). Also, it's better to detach threads(pthread_detach(3)) so that thread resources are automatically released on thread termination. The shared resources will not be released until all threads exit.
When the main process terminates all the worker threads created by that process are also killed. So, if the main() returns before a detached thread it created completes execution the detached thread will be killed by OS. Take this example:
void work(){
this_thread::sleep_for(chrono::seconds(2));
cout<<"Worker Thread Completed"<<endl;
}
int main(){
thread t(work);
t.detach();
cout<<"Main Returning..."<<endl;
return 0;
}
In the above program Worker Thread Completed will never be printed. Since main returns before the 2 second delay in the worker thread. Now if we change the code a little and add a delay greater than 2 seconds before main returns. Like:
void work(){
this_thread::sleep_for(chrono::seconds(2));
cout<<"Worker Thread Completed"<<endl;
}
int main(){
thread t(work);
t.detach();
cout<<"Main Returning..."<<endl;
this_thread::sleep_for(chrono::seconds(4));
return 0;
}
Output
Main Returning...
Worker Thread Completed
Now if a thread is created from any functions other than main the detached thread will stay alive until it's executions has completed even after the function returns. For example:
void child()
{
this_thread::sleep_for(chrono::seconds(2));
cout << "Worker Thread Completed" << endl;
}
void parent(){
thread t(child);
t.detach();
cout<<"Parent Returning...\n";
return;
}
int main()
{
parent();
cout<<"Main Waiting..."<<endl;
this_thread::sleep_for(chrono::seconds(5));
}
Output
Parent Returning...
Main Waiting...
Worker Thread Completed
A workaround to make main to wait for a detached worker thread before returning is to use condition_variable. For example:
#include <bits/stdc++.h>
using namespace std;
condition_variable cv;
mutex m;
void work(){
this_thread::sleep_for(chrono::seconds(2));
cout << "Worker Thread Completed" << endl;
cv.notify_all();
}
int main(){
thread t(work);
t.detach();
cout << "Main Returning..." << endl;
unique_lock<mutex>ul(m);
cv.wait(ul);
return 0;
}

Amateur can't understand std::thread usage

I hereby pardon for such a general title.
I am writing a physical simulation application which displays data in 3D using OpenGL, and one of the functions which is responsible for some heavy calculations is appearing to hold the performance down a bit. I would like them to be done "on the background" without freezing the application for a few seconds. However, std::thread doesn't seem to work in my case.
The function I am trying to thread has a lot of computations in it, it allocates some memory here and there, calls other functions and uses classes, if that matters. I've created a wrapper function, from which I try to start a thread:
void WrapperFunction(void)
{
std::thread t(DoSomethingSerious);
t.join();
}
However, it appears that it has zero effect, just like if I called DoSomethingSerious directly.
What could be the problem?
join() waits for the thread to finish, before proceeding. That's what joining a thread means.
You have two options.
1) Instantiating a std::thread, and proceed to do whatever else needs to be done, and only join the thread once everything is done.
2) detach() the thread. The detached thread will continue to execute independently, and cannot be joined any more. In this case, you will have to make other arrangements for waiting until the thread stops.
However, it appears that it has zero effect.
Sure, your code in the main thread is just suspended until everything in the asynchronous thread is finished.
If you have intermediate actions between starting the thread and doing the join(), you should notice the effect:
void WrapperFunction(void) {
std::thread t(DoSomethingSerious);
// Do something else in parallel
t.join();
}
That is because you directly call t.join(). The std::thread::join function waits for the thread to finish before returning. As you yourself notice, the effect is that there is no difference from just calling the function.
More useful would be to do something else between the thread creration and where you wait for the thread. Something like the following pseudo-code:
void WrapperFunction(void)
{
// Create thread
std::thread t(DoSomethingSerious);
// Lots
// of
// code
// doing
// other
// things
// Wait for thread to finish
t.join();
}

Is there a reliable way to force a thread to stop in C++? (especially detached ones)

I am recently working with threads in C++11. now I am thinking about how to force stop a thread. I couldn't find it on stackoverflow, and also tried these.
One variable each thread : not so reliable
return in the main thread : I have to force quit only one not all
and I have no more ideas. I have heard about WinAPI, but I want a portable solution. (that also means I wont use fork())
Can you please give me a solution of this? I really want to do it.
One of the biggest problems with force closing a thread in C++ is the RAII violation.
When a function (and subsequently, a thread), gracefully finishes, everything it held is gracefully cleaned up by the destructors of the objects the functions/threads created.
Memory gets freed,
OS resources (handles, file descriptors etc.) are closed and returned to the OS
Locks are getting unlocked so other threads can use the shared resources they protect.
other important tasks are preformed (such as updating counters, logging, etc.).
If you brutally kill a thread (aka by TerminateThread on Windows, for example), non of these actually happen, and the program is left in a very dangerous state.
A (not-so) common pattern that can be used is to register a "cancellation token" on which you can monitor and gracefully shut the thread if other thread asks so (a la TPL/PPL). something like
auto cancellationToken = std::make_shared<std::atomic_bool>();
cancellationToken->store(false);
class ThreadTerminator : public std::exception{/*...*/};
std::thread thread([cancellationToken]{
try{
//... do things
if (cancellationToken->load()){
//somone asked the thred to close
throw ThreadTerminator ();
}
//do other things...
if (cancellationToken->load()){
//somone asked the thred to close
throw ThreadTerminator ();
}
//...
}catch(ThreadTerminator){
return;
}
});
Usually, one doesn't even open a new thread for a small task, it's better to think of a multi threaded application as a collection of concurrent tasks and parallel algorithms. one opens a new thread for some long ongoing background task which is usually performed in some sort of a loop (such as, accepting incoming connections).
So, anyway, the cases for asking a small task to be cancelled are rare anyway.
tldr:
Is there a reliable way to force a thread to stop in C++?
No.
Here is my approach for most of my designs:
Think of 2 kinds of Threads:
1) primary - I call main.
2) subsequent - any thread launched by main or any subsequent thread
When I launch std::thread's in C++ (or posix threads in C++):
a) I provide all subsequent threads access to a boolean "done", initialized to false. This bool can be directly passed from main (or indirectly through other mechanisms).
b) All my threads have a regular 'heartbeat', typically with a posix semaphore or std::mutex, sometimes with just a timer, and sometimes simply during normal thread operation.
Note that a 'heartbeat' is not polling.
Also note that checking a boolean is really cheap.
Thus, whenever main wants to shut down, it merely sets done to true and 'join's with the subsequent threads.
On occasion main will also signal any semaphore (prior to join) that a subsequent thread might be waiting on.
And sometimes, a subsequent thread has to let its own subsequent thread know it is time to end.
Here is an example -
main launching a subsequent thread:
std::thread* thrd =
new std::thread(&MyClass_t::threadStart, this, id);
assert(nullptr != thrd);
Note that I pass the this pointer to this launch ... within this class instance is a boolean m_done.
Main Commanding shutdown:
In main thread, of course, all I do is
m_done = true;
In a subsequent thread (and in this design, all are using the same critical section):
void threadStart(uint id) {
std::cout << id << " " << std::flush; // thread announce
do {
doOnce(id); // the critical section is in this method
}while(!m_done); // exit when done
}
And finally, at an outer scope, main invokes the join.
Perhaps the take away is - when designing a threaded system, you should also design the system shut down, not just add it on.

Multithreaded program thread join issues

I am currently writing a multithreaded program where a thread may sometimes be created depending on certain circumstances. If this thread is created it needs to run independently of all other threads and I cannot afford to block any other threads to wait for it to join. The length of time the spawned thread runs for varies; sometimes it can take up to a few hours.
I have tried spawning the thread and putting a join in the destructor of the class which works fine, however if the code within the spawned thread finishes a long time before the destructor is called (which will be around 99% of the time) I would like the thread to kill itself freeing all its resources etc.
I looked into using detach for this, but you can't rejoin a detached thread and on the off chance the destructor is called before this thread finishes then the spawned thread will not finish and could have disastrous consequences.
Is there any possible solution that ensures the thread finishes before the class is destructed as well as allowing it to join as soon as the thread finishes its work?
I am using boost/c++11 for threading. Any help at all would be greatly appreciated.
Thanks
The thread may detach itself, releasing its resources. If the destructor sees that the thread is joinable, i.e. still running, let it join. If the thread reaches its end, self-detach. Possible race condition: is_joinable() returns true in destructor - thread detaches itself - destructor joins and fails miserably. So use a mutex guarding the thread's decease:
struct ThreadContainer
{
std::mutex threadEndMutex;
std::thread theThread;
ThreadContainer()
: theThread([=]()
{
/* do stuff */
// if the mutex is locked, the destructor is just
// about to join, so we let him.
if (threadEndMutex.try_lock())
theThread.detach();
})
{}
~ThreadContainer()
{
// if the mutex is locked, the thread is just about
// to detach itself, so no need to join.
// if we got the mutex but the thread is not joinable,
// it has detached itself already.
if (threadEndMutex.try_lock() && theThread.is_joinable())
theThread.join();
}
};
PS:
you might not even need the call to is_joinable, because if the thread detached itself, it never unlocked the mutex and try_lock fails.
PPS:
instead of the mutex, you may use std::atomic_flag:
struct ThreadContainer
{
std::atmoic_flag threadEnded;
std::thread theThread;
ThreadContainer()
: threadEnded(ATOMIC_FLAG_INIT)
, theThread([=]()
{
/* do stuff */
if (!threadEnded.test_and_set())
theThread.detach();
})
{}
~ThreadContainer()
{
if (!threadEnded.test_and_set())
theThread.join();
}
};
You could define pauses/steps in your "independent" thread algorithm, and at each step you look at a global variable that helps you decide to cancel calculation and auto destroy, or to continue the calculation in your thread.
If global variable is not sufficient, i.e. if a more precise granularity is needed you should define a functor object for your thread function, this functor having a method kill(). You keep references of the functors after you have launched them as threads. And when you call the MyThreadFunctor::kill() it's sets a boolean field and this field is checked at each steps of your calculation in the functor thread-function itself..