Uzyskaj status std :: future

83

Czy można sprawdzić, czy std::futureskończył się, czy nie? O ile wiem, jedynym sposobem byłoby zadzwonić wait_forz zerowym czasem trwania i sprawdzić, czy status jest, readyczy nie, ale czy jest lepszy sposób?

David Brown
źródło
10
@CatPlusPlus O ile się nie mylę, validsprawdza tylko, czy przyszłość ma stan współdzielony (tj. Powraca, truedopóki nie getzostanie wywołana w przyszłości).
David Brown
Więc jeśli getzostał wywołany i zwraca przechowywaną wartość, czy nadal chcesz true? (Nie jestem pewien, dlaczego miałoby to być przydatne, ponieważ wartość można uzyskać tylko raz.)
James McNellis,
@JamesMcNellis być może nie rozumiem lub niewłaściwie wykorzystuję przyszłość, ale chcę wiedzieć, czy wątek (lub cokolwiek wykonuje obliczenia) jest zakończony, czy nie. Zasadniczo odpowiednik Qt QFuture::isFinished.
David Brown
1
Oczekiwanie z zerowym limitem czasu to sposób, w jaki większość interfejsów API na wielu platformach radzi sobie z taką koncepcją… Do tego stopnia, że ​​uznałbym to za „standardowy” sposób podejścia do tej koncepcji. Trochę mnie to
zdziwiło
16
@asveikau Nie wiedziałem, że to standardowa praktyka. Po prostu dziwne jest wywoływanie funkcji oczekiwania, kiedy nie chcę czekać.
David Brown

Odpowiedzi:

85

Masz rację i oprócz dzwonienia wait_untilz czasem w przeszłości (co jest równoważne) nie ma lepszego sposobu.

Zawsze możesz napisać małe opakowanie, jeśli chcesz wygodniejszej składni:

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

Uwaga: jeśli funkcja jest odroczona, nigdy nie zwróci ona wartości true, więc prawdopodobnie lepiej sprawdzić wait_forbezpośrednio w przypadku, gdy chcesz uruchomić odroczone zadanie synchronicznie po upływie określonego czasu lub gdy obciążenie systemu jest niskie.

Jonathan Wakely
źródło
2
wait_for nie zmienia przyszłości, więc parametr może być zadeklarowany jako const.
Jens Åkerblom,
7
Rozważ najpierw sprawdzenie valid (), aby uniknąć błędów w czasie wykonywania, jeśli get zostało już wywołane lub przyszłość nigdy nie została zainicjowana.
Jeremy Sorensen
5
Czy wait_for (chrono :: seconds (0)) gwarantuje natychmiastowy powrót, czy też może zapewnić kontrolę nad wątkiem przez kilka milisekund w niektórych implementacjach? Byłoby to bardzo ważne, ponieważ kilka milisekund to dużo czasu podczas kodowania gry ...
kynnysmatto.
9
@kynnysmatto, w niektórych implementacjach uzyskuje blokadę mutex, aby bezpiecznie sprawdzić stan przyszłości, więc jeśli ta blokada jest brana pod uwagę (ponieważ inny wątek przygotowuje stan lub również sprawdza gotowość), to zostanie zablokowany, a kolejny wątek może działać, ale przy dobrej implementacji mutex nie powinien być przechowywany dłużej niż przez kilka instrukcji, a więc nawet przez jedną milisekundę. Obecna implementacja GCC w ogóle nie używa muteksu, ale poprzednia tak, a przygotowanie stanu odbywa się poprzez zamianę dwóch wskaźników, więc mutex jest blokowany tylko na bardzo krótko, kiedy to się dzieje.
Jonathan Wakely
@JonathanWakely testowanie za pomocą g ++ for(int i = 0; i < 1000; i++) f.wait_for(chrono::seconds(0));zajmuje 43 ms czasu zegara ściennego.
Daniel Kinsman
15

W pracach dla std :: future istnieje funkcja składowa is_ready . W międzyczasie implementacja VC ma element członkowski _Is_ready ().

Rick Yorgason
źródło
Zauważ, że funkcja składowa _Is_ready () NIE jest bezpieczna wątkowo. Uzyskuje dostęp do flagi _Ready skojarzonego stanu w sposób niestrzeżony. Tak jest przynajmniej w przypadku VS2019 16.2.
Mattias De Charleroy
10

Mój pierwszy zakład byłoby zadzwonić wait_forz 0 trwania, i sprawdzić kod wynik, który może być jednym z future_status::ready, future_status::deferredlub future_status::timeout.

W cppreference twierdzą, że valid() sprawdza, czy wynik jest dostępny , ale standard mówi, że valid()zwróci, truejeśli *thisodnosi się do wspólnego stanu, niezależnie od tego, czy ten stan jest gotowy, czy nie.

David Rodríguez - dribeas
źródło
7
cppreference zostało zaktualizowane i stwierdza, że ​​„sprawdza, czy przyszłość ma wspólny stan”. (Nie jestem pewien, czy chcesz usunąć drugi akapit, czy go edytować, więc sam go nie zmodyfikuję).
Domyślnie