Invoke a method with a timeout
Because you have no predicate in the cv->wait_for
call, the thread might be unblocked spuriously. However, it is strange that no FINISH/TIMEOUT is printed. So we might need more information here: What does happen with the program? Does it hang, does it throw, does it just exit, does it print in the line after cv->wait_for
?
You could try using std::async
and see if the same behavior appears (furthermore, it would greatly simplify your code):
std::future<int> res = std::async(foo);
std::future_status stat = res.wait_for(std::chrono::seconds(60));
if (stat != std::future_status::ready) {
std::cout << "Timed out..." << "\n";
} else {
try {
int result = res.get();
std::cout << "Result = " << result << std::endl;
} catch (const FooException& e) {
std::cerr << e.what() << '\n';
}
}
EDIT As pointed out in the comments by CuriouslyRecurringThoughts
the future of std::async
blocks in the destructor. If that is not an option, the following code uses a std::promise
and a detached thread instead:
std::promise<int> prom;
std::future<int> res = prom.get_future();
std::thread([p = std::move(prom)]() mutable {
try {
p.set_value(foo());
} catch (const std::exception& e) {
p.set_exception(std::current_exception());
}
}).detach();
Waiting for the std::future
is done as shown before.
It seems that despite the timed wait your main thread deadlocks because even when cv->wait_for
returns with timeout it still tries to lk.lock()
on the mutex which is currently locked by the second thread.
As mentioned on cppreference about wait_for
:
When unblocked, regardless of the reason, lock is reacquired and wait_for() exits.
I'm not sure why the promise/future solution didn't work for you since you didn't post that example here, but I've tried a simple version of it which seems to work even when the second thread "hangs":
using namespace std::chrono_literals;
std::cout << "START" << std::endl;
std::promise<void> p;
auto f = p.get_future();
std::thread t([p = std::move(p)]() mutable {
std::cout << "PROCESS" << std::endl;
std::this_thread::sleep_for(5min);
p.set_value();
});
auto status = f.wait_for(5s);
std::cout << (status == std::future_status::ready ? "FINISH" : "TIMEOUT") << std::endl;
t.join();
The output is as expected:
START
PROCESS
TIMEOUT