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

Tags:

C++

C++17

C++14