Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to check if a std::thread is still running?

How can I check if a std::thread is still running (in a platform independent way)? It lacks a timed_join() method and joinable() is not meant for that.

I thought of locking a mutex with a std::lock_guard in the thread and using the try_lock() method of the mutex to determine if it is still locked (the thread is running), but it seems unnecessarily complex to me.

Do you know a more elegant method?

Update: To be clear: I want to check if the thread cleanly exited or not. A 'hanging' thread is considered running for this purpose.

like image 465
kispaljr Avatar asked Feb 01 '12 10:02

kispaljr


People also ask

How to check if thread is running in c++?

if (status == std::future_status::ready) { std::cout << "Thread finished" << std::endl; } else { std::cout << "Thread still running" << std::endl; } t. join(); // Join thread. } This is of course because the thread status is checked before the task is finished.

What happens when a thread finishes C++?

When you get to the end of your thread function, the thread ends. If the main thread exits while other threads are still running, bad things happen: it causes your program to crash. Always make sure your other threads exit before exiting the main thread.

When thread is joinable?

A thread object is said to be joinable if it identifies/represent an active thread of execution. A thread is not joinable if: It was default-constructed. If either of its member join or detach has been called.

What does std :: thread do?

std::thread Threads allow multiple functions to execute concurrently. std::thread objects may also be in the state that does not represent any thread (after default construction, move from, detach, or join), and a thread of execution may not be associated with any thread objects (after detach).


1 Answers

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. } 
like image 85
Felix Glas Avatar answered Sep 29 '22 22:09

Felix Glas