Timeout for thread.join()
Instead of using threads explicitly you can use std::async()
to provide you with a std::future<>
and you can do timed waits on the std::future
:
http://en.cppreference.com/w/cpp/thread/future/wait_for
For Boost, timed_join() is now deprecated. Use try_join_for() instead:
myThread.try_join_for(boost::chrono::milliseconds(8000))
There is no timeout for std::thread::join()
. However you can view std::thread::join()
as merely a convenience function. Using condition_variable
s you can create very rich communication and cooperation between your threads, including timed waits. For example:
#include <chrono>
#include <thread>
#include <iostream>
int thread_count = 0;
bool time_to_quit = false;
std::mutex m;
std::condition_variable cv;
void f(int id)
{
{
std::lock_guard<std::mutex> _(m);
++thread_count;
}
while (true)
{
{
std::lock_guard<std::mutex> _(m);
std::cout << "thread " << id << " working\n";
}
std::this_thread::sleep_for(std::chrono::milliseconds(250));
std::lock_guard<std::mutex> _(m);
if (time_to_quit)
break;
}
std::lock_guard<std::mutex> _(m);
std::cout << "thread ended\n";
--thread_count;
cv.notify_all();
}
int main()
{
typedef std::chrono::steady_clock Clock;
std::thread(f, 1).detach();
std::thread(f, 2).detach();
std::thread(f, 3).detach();
std::thread(f, 4).detach();
std::thread(f, 5).detach();
auto t0 = Clock::now();
auto t1 = t0 + std::chrono::seconds(5);
std::unique_lock<std::mutex> lk(m);
while (!time_to_quit && Clock::now() < t1)
cv.wait_until(lk, t1);
time_to_quit = true;
std::cout << "main ending\n";
while (thread_count > 0)
cv.wait(lk);
std::cout << "main ended\n";
}
In this example main
launches several threads to do work, all of which occasionally check if it is time to quit under a mutex (this could also be an atomic). The main thread also monitors if it is time to quit (if the threads get all their work done). If main runs out of patience, he just declares it to be time to quit, then waits for all threads to perform any necessary clean up before exiting.
Yes, it is possible. The solution that has been suggested by Galik looks like this:
#include <thread>
#include <future>
...
// Launch the thread.
std::thread thread(ThreadFnc, ...);
...
// Terminate the thread.
auto future = std::async(std::launch::async, &std::thread::join, &thread);
if (future.wait_for(std::chrono::seconds(5))
== std::future_status::timeout) {
/* --- Do something, if thread has not terminated within 5 s. --- */
}
However, this essentially launches a third thread that performs the thread.join()
.
(Note: The destructor of future
will block until thread
has joined and the auxiliary thread has terminated.)
Maybe launching a thread just to bring another thread down is not what you want. There is another, portable solution without an auxiliary thread:
#include <thread>
#include <future>
...
// Launch the thread.
std::future<T_return>* hThread
= new std::future<T_return>(std::async(std::launch::async, ThreadFnc, ...));
...
// Terminate the thread.
if (hThread->wait_for(std::chrono::seconds(5))
== std::future_status::timeout) {
/* --- Do something, if thread has not terminated within 5 s. --- */
} else
delete hThread;
where T_return
is the return type of your thread procedure. This scenario uses an std::future
/ std::async
combination instead of an std::thread
.
Note that hThread
is a pointer. When you call the delete
operator on it, it will invoke the destructor of *hThread
and block until the thread has terminated.
I have tested both versions with gcc 4.9.3 on Cygwin.