Отримайте статус std :: future


83

Чи можна перевірити std::future, закінчив чи ні? Наскільки я можу сказати, єдиним способом це буде зателефонувати wait_forз нульовою тривалістю і перевірити, чи є статус readyчи ні, але чи є кращий спосіб?


10
@CatPlusPlus Якщо я не помиляюся, validперевіряє лише, чи має майбутнє спільний стан (тобто воно повертається, trueдоки не getбуде викликано майбутнє).
Девід Браун

Отже, якщо getбуло викликано і повертає збережене значення, ви все ще хочете true? (Я не впевнений, чому це було б корисно, оскільки значення можна отримати лише один раз.)
Джеймс МакНелліс,

@JamesMcNellis, можливо, я не розумію або зловживаю ф'ючерсами, але те, що я хочу, - це знати, закінчилася нитка (або що інше, що виконує обчислення) чи ні. В QFuture::isFinishedосновному еквівалент Qt .
Девід Браун

1
Чекання з нульовим тайм-аутом - це те, як більшість API на багатьох платформах мають справу з такою концепцією ... Настільки, що я вважав би її "стандартним" способом підходу до концепції. Це змушує мене трохи спантеличити поняття "кращого шляху" ...
asveikau,

16
@asveikau Я не знав, що це стандартна практика. Просто дивно викликати функцію очікування, коли я не хочу чекати.
Девід Браун

Відповіді:


85

Ви маєте рацію, і окрім дзвінків wait_untilіз минулим часом (що еквівалентно), немає кращого способу.

Ви завжди можете написати невелику обгортку, якщо хочете більш зручний синтаксис:

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

Зверніть увагу, якщо функція відкладена, це ніколи не поверне істину, тому, мабуть, краще перевірити wait_forбезпосередньо у випадку, коли ви можете захотіти запустити відкладене завдання синхронно після того, як пройде певний час або коли завантаження системи буде низьким.


2
wait_for не мутує майбутнє, тому параметр може бути оголошений як const.
Jens Åkerblom

7
Подумайте про те, щоб спочатку перевірити valid (), щоб уникнути помилок під час виконання, якщо get вже було викликано або майбутнє ніколи не було ініціалізовано.
Джеремі Соренсен

5
Гарантовано повернення wait_for (chrono :: seconds (0)) негайно повернеться, чи це може дати контроль потоку протягом декількох мілісекунд на деяких реалізаціях? Це було б дуже важливо знати, оскільки пара мілісекунд - це багато часу при кодуванні гри ...
kynnysmatto

9
@kynnysmatto, у деяких реалізаціях він отримує блокування мьютексу для безпечного контролю стану майбутнього, тому, якщо цей замок оспорюється (оскільки інший потік робить стан готовим, або також перевіряє готовність), він заблокує, а інший потік може працювати, але при хорошій реалізації мьютекс ніколи не повинен триматися більше кількох інструкцій, тож навіть жодної мілісекунди. Поточна реалізація GCC взагалі не використовує мьютекс, але попередня використовувала, і підготовка стану здійснюється шляхом обміну двома покажчиками, тому мьютекс блокується дуже ненадовго, поки це відбувається.
Джонатан Уейклі

@JonathanWakely тестування за допомогою g ++ for(int i = 0; i < 1000; i++) f.wait_for(chrono::seconds(0));займає 43 мс часу настінного годинника.
Даніель Кінсман,

15

У роботах для std :: future є функція-член is_ready . Тим часом у реалізації VC є член _Is_ready ().


Зверніть увагу, що функція-член _Is_ready () НЕ є потокобезпечною. Він отримує доступ до прапора _Ready відповідного стану незахищеним способом. Це принаймні так для VS2019 16.2.
Маттіас де Шарлеруа

10

Моя перша ставка буде дзвонити wait_forз 0 тривалість і перевірити код результату , який може бути один з future_status::ready, future_status::deferredабо future_status::timeout.

У cppreference вони стверджують, що valid() перевіряє наявність результату , але стандарт говорить, що valid()повернеться, trueякщо *thisпосилається на загальний стан, незалежно від того, готовий цей стан чи ні.


7
cppreference тепер оновлено і вказує "перевіряє, чи має майбутнє спільний стан". (Не впевнений, що ви хочете видалити свій другий абзац або відредагувати його, тому я не буду його змінювати сам).
За замовчуванням
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.