Get the status of a std::future
Asked Answered
P

4

114

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?

Purism answered 5/6, 2012 at 0:46 Comment(7)
@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).Purism
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.)Spoofery
@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 basically.Purism
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"...Peavey
@Peavey 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.Purism
https://mcmap.net/q/179807/-how-to-check-if-a-std-thread-is-still-running/873025Viewpoint
If the future is empty, wait_for produces an ERRORBurny
R
113

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.

Retire answered 6/6, 2012 at 16:6 Comment(8)
wait_for doesn't mutate the future so the parameter could be declared as const.Helldiver
Consider checking valid() first to avoid run time errors if get was already called or the future was never initialized.Neurogenic
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...Maundy
@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.Retire
@JonathanWakely testing with g++ for(int i = 0; i < 1000; i++) f.wait_for(chrono::seconds(0)); takes 43ms of wall clock time.Libbie
@DanielKinsman, so not even a single millisecond then, as I said. And it's much faster once the future is ready: wandbox.org/permlink/KDfXPGpgg38jX0LTRetire
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. 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.Retire
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.Retire
M
20

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

Margaret answered 4/5, 2014 at 23:56 Comment(2)
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.Aldarcie
lol, typical C++. Something is "in the works" in 2014 and in 2023 it's nowhere to be found.Sales
F
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.

Feldt answered 5/6, 2012 at 3:7 Comment(1)
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).Melmon
T
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.

Tiliaceous answered 11/8, 2023 at 20:34 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.