Reputation: 12126
To my surprise, a C++11 std::thread object that has finished executing, but has not yet been joined is still considered an active thread of execution. This is illustrated in the following code example (built on Xubuntu 13.03 with g++ 4.7.3). Does anyone know if the C++11 standard provides a means to detect if a std::thread object is still actively running code?
#include <thread>
#include <chrono>
#include <iostream>
#include <pthread.h>
#include <functional>
int main() {
auto lambdaThread = std::thread([](){std::cout<<"Excuting lambda thread"<<std::endl;});
std::this_thread::sleep_for(std::chrono::milliseconds(250));
if(lambdaThread.joinable()) {
std::cout<<"Lambda thread has exited but is still joinable"<<std::endl;
lambdaThread.join();
}
return 0;
}
Upvotes: 8
Views: 14123
Reputation: 9
I just had a breakthrough with this. I've been looking for a simple and general solution. Here it is.
Using the Boost C++ Libraries, create a signal that returns a boolean. Prior to its first use, connect the signal to a slot that returns false
. Create a boost::signals2::scoped_connection
within your thread that returns true
. This exploits the default behavior of boost::signals2::signal
return types that returns the value of the last slot called. By using the scoped_connection
at the beginning of your thread, this slot only remains connected while thread is running. Also, Boost signals2::signal
s contain internal mutexes that maintain thread safety.
#include <thread>
#include <boost/signals2.hpp>
int main(int argc, char* argv[])
{
//This can be in a class or someplace else
boost::signals2::signal<bool ()> ThreadRunning;
// Be sure to capture 'this' if used in a class
ThreadRunning.connect([]() {return false;});
auto t = std::thread([]()
{
// 'c' is an arbitrary variable name.
boost::signals2::scoped_connection c(ThreadRunning.connect[]() {return true;}));
// Do your stuff.
});
if (TreadRunning())
//Do stuff if the thread is still running
t.join();
return 0;
}
If the thread hasn't joined, but you want to see if it's completed running, you can insert an additional scope to your thread.
auto t = std::thread([]()
{
{
boost::signals2::scoped_connection c(ThreadRunning.connect[]() {return true;}));
// Do your stuff.
}
});
With this method, calling ThreadRunning()
will return false
even through the thread isn't joined.
While this method is threadsafe, there is the possibility that the thread will complete between when you call your signal and completing whatever you use this logic for.
Upvotes: 0
Reputation: 34638
No, I don't think that this is possible. I would also try to think about your design and if such a check is really necessary, maybe you are looking for something like the interruptible threads from boost.
However, you can use std::async
- which I would do anyway - and then rely on the features std::future
provides you.
Namely, you can call std::future::wait_for
with something like std::chrono::seconds(0)
. This gives you a zero-cost check and enables you to compare the std::future_status
returned by wait_for
.
auto f = std::async(foo);
...
auto status = f.wait_for(std::chrono::seconds(0));
if(status == std::future_status::timeout) {
// still computing
}
else if(status == std::future_status::ready) {
// finished computing
}
else {
// There is still std::future_status::defered
}
Upvotes: 8
Reputation:
for what definition of "actively running code"? not that I know of, I'm not sure what state the thread is left in after it becomes joinable, in most cases I can think of you'd actually want fine grain control, like a flag set by the code running in that thread, anyway
for a platform specific solution, you could use GetThreadTimes
Upvotes: 2