113

Is it possible to check if a std::future has finished or not? As far as I can tell the only way to do it would be to call wait_for with a zero duration and check if the status is ready or not, but is there a better way?

ildjarn
  • 62,044
  • 9
  • 127
  • 211
David Brown
  • 13,336
  • 4
  • 38
  • 55
  • 11
    @CatPlusPlus Unless I'm mistaken, `valid` only checks if the future has a shared state (i.e. It returns `true` until `get` is called on the future). – David Brown Jun 05 '12 at 01:11
  • So, if `get` has been called and returns the stored value, do you still want `true`? (I'm not sure why this would be useful, since you can only get the value once.) – James McNellis Jun 05 '12 at 01:28
  • @JamesMcNellis perhaps I am misunderstanding or misusing futures, but what I want is to know if the thread (or whatever is performing the calculation) is finished or not. The equivalent of Qt's [`QFuture::isFinished`](http://doc.qt.nokia.com/4.7-snapshot/qfuture.html#isFinished) basically. – David Brown Jun 05 '12 at 03:06
  • 2
    A wait with a zero timeout is how most APIs across many platforms deal with such a concept... So much so that I would consider it the "standard" way of approaching the concept. This makes me a bit puzzled at the notion of "a better way"... – asveikau Jun 13 '12 at 17:53
  • 21
    @asveikau I was not aware this was a standard practice. It just feels odd to call a wait function when I do not wish to wait. – David Brown Jun 13 '12 at 18:55
  • http://stackoverflow.com/q/9094422/873025 – Felix Glas May 12 '17 at 15:41
  • If the future is empty, wait_for produces an ERROR – mathengineer Sep 12 '21 at 13:24

4 Answers4

111

You are correct, and apart from calling wait_until with a time in the past (which is equivalent) there is no better way.

You could always write a little wrapper if you want a more convenient syntax:

template<typename R>
  bool is_ready(std::future<R> const& f)
  { return f.wait_for(std::chrono::seconds(0)) == std::future_status::ready; }

N.B. if the function is deferred this will never return true, so it's probably better to check wait_for directly in the case where you might want to run the deferred task synchronously after a certain time has passed or when system load is low.

Jonathan Wakely
  • 166,810
  • 27
  • 341
  • 521
  • 2
    wait_for doesn't mutate the future so the parameter could be declared as const. – Jens Åkerblom Sep 06 '14 at 10:54
  • 10
    Consider checking valid() first to avoid run time errors if get was already called or the future was never initialized. – Jeremy Sorensen Jul 23 '15 at 19:35
  • 7
    Is wait_for(chrono::seconds(0)) guaranteed to return immediately or could it yield the control of the thread for a couple of milliseconds on some implementations? This would be quite important to know as a couple of milliseconds is a lot of time when coding a game... – kynnysmatto Jul 23 '15 at 21:34
  • 9
    @kynnysmatto, on some implementations it acquires a mutex lock to safely inspect the state of the future, so if that lock is contended (because another thread is making the state ready, or also checking for readiness) then it will block, and another thread could run, but on a good implementation the mutex should never be held for more than a few instructions, so not even a single millisecond. GCC's current implementation doesn't use a mutex at all, but the previous one did and making the state ready is done by swapping two pointers, so the mutex is only locked very briefly while that happens. – Jonathan Wakely Jul 24 '15 at 09:05
  • @JonathanWakely testing with g++ `for(int i = 0; i < 1000; i++) f.wait_for(chrono::seconds(0));` takes 43ms of wall clock time. – Daniel Kinsman Aug 21 '20 at 11:36
  • @DanielKinsman, so not even a single millisecond then, as I said. And it's **much** faster once the future is ready: https://wandbox.org/permlink/KDfXPGpgg38jX0LT – Jonathan Wakely Aug 24 '20 at 10:59
  • 2
    A large part of that time is getting the current time. If you use `wait_until(chrono::system_clock::time_point::min())` you don't need the current time, and it's [faster](https://wandbox.org/permlink/Z1arsDE7eHW9JrqJ). That optimisation is specific to GCC though, and for GCC 11 you'd need to use `steady_clock` instead of `system_clock` as we're about to change the clock that is used under the covers. – Jonathan Wakely Aug 24 '20 at 11:13
  • With the current dev sources for GCC (which will be GCC 11 next year) `f.wait_for(0)` is almost as fast as it is after the future is ready. Less than 100ns. – Jonathan Wakely Nov 16 '20 at 15:55
19

There's an is_ready member function in the works for std::future. In the meantime, the VC implementation has an _Is_ready() member.

Rick Yorgason
  • 1,616
  • 14
  • 22
  • Note that the _Is_ready() member function is NOT thread-safe. It accesses the _Ready flag of the associated state in an unguarded way. This is at least the case for VS2019 16.2. – Mattias De Charleroy Mar 18 '20 at 08:27
  • 1
    lol, typical C++. Something is "in the works" in 2014 and in 2023 it's nowhere to be found. – Chris_F Feb 02 '23 at 02:48
13

My first bet would be to call wait_for with a 0 duration, and check the result code that can be one of future_status::ready, future_status::deferred or future_status::timeout.

valid() will return true if *this refers to a shared state, independently of whether that state is ready or not. See cppreference.

hanstar17
  • 70
  • 1
  • 10
David Rodríguez - dribeas
  • 204,818
  • 23
  • 294
  • 489
  • 7
    cppreference has now been updated and states "checks if the future has a shared state". (Not sure if you want to remove your second paragraph or edit it, so I'll won't modify it myself). – default Mar 22 '16 at 10:54
0

Since C++11, std::future now has both a wait() and a get() method, which will wait until the future has a valid response, with the latter method waiting (blocking) and then returning a result when it is ready.

If you want to check if it's ready without blocking, then I've done the same as what David Rodríguez - dribeas suggested; call wait_for with a 0 (or maybe up to 10ms) duration, and check the result code that can be one of future_status::ready, future_status::deferred or future_status::timeout. How short the delay needs to be depends on your needs.

RussC
  • 1
  • 2