How to check if a std::thread is still running?
If you are willing to make use of C++11 std::async
and std::future
for running your tasks, then you can utilize the wait_for
function of std::future
to check if the thread is still running in a neat way like this:
#include <future>
#include <thread>
#include <chrono>
#include <iostream>
int main() {
using namespace std::chrono_literals;
/* Run some task on new thread. The launch policy std::launch::async
makes sure that the task is run asynchronously on a new thread. */
auto future = std::async(std::launch::async, [] {
std::this_thread::sleep_for(3s);
return 8;
});
// Use wait_for() with zero milliseconds to check thread status.
auto status = future.wait_for(0ms);
// Print status.
if (status == std::future_status::ready) {
std::cout << "Thread finished" << std::endl;
} else {
std::cout << "Thread still running" << std::endl;
}
auto result = future.get(); // Get result.
}
If you must use std::thread
then you can use std::promise
to get a future object:
#include <future>
#include <thread>
#include <chrono>
#include <iostream>
int main() {
using namespace std::chrono_literals;
// Create a promise and get its future.
std::promise<bool> p;
auto future = p.get_future();
// Run some task on a new thread.
std::thread t([&p] {
std::this_thread::sleep_for(3s);
p.set_value(true); // Is done atomically.
});
// Get thread status using wait_for as before.
auto status = future.wait_for(0ms);
// Print status.
if (status == std::future_status::ready) {
std::cout << "Thread finished" << std::endl;
} else {
std::cout << "Thread still running" << std::endl;
}
t.join(); // Join thread.
}
Both of these examples will output:
Thread still running
This is of course because the thread status is checked before the task is finished.
But then again, it might be simpler to just do it like others have already mentioned:
#include <thread>
#include <atomic>
#include <chrono>
#include <iostream>
int main() {
using namespace std::chrono_literals;
std::atomic<bool> done(false); // Use an atomic flag.
/* Run some task on a new thread.
Make sure to set the done flag to true when finished. */
std::thread t([&done] {
std::this_thread::sleep_for(3s);
done = true;
});
// Print status.
if (done) {
std::cout << "Thread finished" << std::endl;
} else {
std::cout << "Thread still running" << std::endl;
}
t.join(); // Join thread.
}
Edit:
There's also the std::packaged_task
for use with std::thread
for a cleaner solution than using std::promise
:
#include <future>
#include <thread>
#include <chrono>
#include <iostream>
int main() {
using namespace std::chrono_literals;
// Create a packaged_task using some task and get its future.
std::packaged_task<void()> task([] {
std::this_thread::sleep_for(3s);
});
auto future = task.get_future();
// Run task on new thread.
std::thread t(std::move(task));
// Get thread status using wait_for as before.
auto status = future.wait_for(0ms);
// Print status.
if (status == std::future_status::ready) {
// ...
}
t.join(); // Join thread.
}
Check if std::thread is still running
The closest you can get is std::thread::joinable()
. To cite from the reference:
Checks if the thread object identifies an active thread of execution. Specifically, returns
true
ifget_id() != std::thread::id()
. So a default constructedthread
is not joinable.
A thread that has finished executing code, but has not yet been joined is still considered an active thread of execution and is therefore joinable.
Is it possible to know if a std::thread finished given its std::thread::id?
I think I found out how:
struct logger {
enum level : int16_t { debug = 0, info = 1, warn = 2, error = 3, fatal = 4 };
~logger() {
write_all();
}
logger & operator()(level p_level) {
add(true)
<< "[" << get_level(p_level) << "]"
<< "[" << std::time(NULL) << "]"
<< "[" << std::this_thread::get_id() << "] ";
return *this;
}
template <typename T>
logger & operator << (const T & p_val) {
add() << p_val;
return *this;
}
private:
struct at_thread_end {
at_thread_end (std::function<void (std::thread::id)> p_callback
, std::thread::id p_id)
: m_callback(p_callback)
, m_id(p_id){}
at_thread_end(at_thread_end && p_at_thread_end)
: m_callback(std::move(p_at_thread_end.m_callback))
, m_id(std::move(p_at_thread_end.m_id)) {}
at_thread_end & operator=(at_thread_end && p_at_thread_end) {
m_callback = std::move(p_at_thread_end.m_callback);
m_id = std::move(p_at_thread_end.m_id);
return *this;
}
~at_thread_end() {
m_callback(m_id);
}
private:
std::function<void (std::thread::id)> m_callback;
std::thread::id m_id;
};
typedef std::map<std::thread::id, std::stringstream> streams;
void on_thread_end(std::thread::id p_id) {
std::cout << "thread " << p_id << " ended" << std::endl;
streams::iterator _ite = m_streams.find(p_id);
if (_ite != m_streams.end()) {
write(_ite->second.str());
std::lock_guard<std::mutex> _lock(m_mutex_streams);
m_streams.erase(_ite);
}
}
std::stringstream & add(bool p_clean = false) {
std::thread::id _id = std::this_thread::get_id();
streams::iterator _ite = m_streams.find(_id);
if (_ite != m_streams.end()) {
if (p_clean) {
write(_ite->second.str());
_ite->second.str("");
}
return _ite->second;
}
using std::placeholders::_1;
thread_local at_thread_end
_at_thread_end(std::bind(&logger::on_thread_end, this, _1)
,_id);
std::lock_guard<std::mutex> _lock(m_mutex_streams);
m_streams[_id] = std::stringstream();
return m_streams[_id];
}
std::string get_level(level p_level) {
switch (p_level) {
case level::debug:
return "DEB";
case level::info:
return "INF";
case level::warn:
return "WAR";
case level::error:
return "ERR";
case level::fatal:
return "FAT";
}
return "LEVEL UNKNOW";
}
void write(const std::string & p_str) {
std::lock_guard<std::mutex> _lock(m_mutex_write);
if (p_str.size()) {
std::cout << p_str << std::endl;
}
}
void write_all() {
std::lock_guard<std::mutex> _lock(m_mutex_streams);
streams::iterator _end = m_streams.end();
for (streams::iterator _ite = m_streams.begin(); _ite != _end; ++_ite) {
write(_ite->second.str());
}
}
streams m_streams;
std::mutex m_mutex_streams;
std::mutex m_mutex_write;
};
You can look at a full example at https://pastebin.com/z2HrF70U
Can C++11 tell if std::thread is active?
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
}
Related Topics
What Is the Logic Behind the "Using" Keyword in C++
Why Should Exceptions Be Used Conservatively
Difference Between Static, Auto, Global and Local Variable in the Context of C and C++
How to Properly Use Widechartomultibyte
Interacting With C++ Classes from Swift
Convert an Int to Ascii Character
Mixing Cout and Printf For Faster Output
Is There a _Class_ Macro in C++
Is This Key-Oriented Access-Protection Pattern a Known Idiom
Do I Have to Acquire Lock Before Calling Condition_Variable.Notify_One()
Template Member Function of Template Class Called from Template Function
Implicit Type Conversion With Template
What's the Right Way to Overload Operator== for a Class Hierarchy