Есть ли способ проверить, готово ли состояние std :: future гарантированно без ожидания?

Я знаю, что могу проверить состояние std::future следующим образом:

my_future.wait_for(std::chrono::seconds(0)) == std::future_status::ready

Но согласно cppreference.com std::future::wait_for может блокировать в некоторых случаях:

Эта функция может блокироваться дольше, чем timeout_duration, из-за задержек планирования или конфликта ресурсов.

Это все еще тот случай, когда timeout_duration это 0? Если это так, есть ли другой способ запросить состояние гарантированно без ожидания?

3

Решение

цитата из cppreference просто напомнить вам, что планировщик ОС является здесь фактором, и что другие задачи, требующие ресурсов платформы, могли бы использовать процессорное время, необходимое вашему потоку для возврата из wait_for() — независимо от того, указана ли длительность таймаута, равная нулю или нет. Это все. Технически вы не можете получить больше, чем на платформе не в реальном времени. Таким образом, стандарт C ++ ничего не говорит об этом, но вы можете увидеть другие интересные вещи — см. Параграф wait_for() под [Futures.unique_future¶21]:

Эффекты: Нет, если в общем состоянии содержится отложенная функция
([futures.async]), в противном случае блокирует, пока общее состояние не будет готово или
до относительного времени ожидания ([thread.req.timing]), указанного
rel_­time истек

Нет такого упоминания о дополнительной задержке здесь, но это говорит о том, что вы являются заблокирован, и это зависит от реализации wait_for() является yield()нить1 первым делом при такой блокировке или немедленном возврате, если продолжительность тайм-аута равна нулю. Кроме того, может также потребоваться, чтобы реализация синхронизировала доступ к будущему статусу блокирующим образом, который должен быть применен перед проверкой на предмет возможного немедленного возврата. Следовательно, у вас даже нет гарантии на Блокировка свободы здесь, не говоря уже о выжидательную свобода.

Обратите внимание, что то же самое относится к звонкам wait_until со временем в прошлом.

Это все еще тот случай, когда timeout_duration равен 0? Если так, есть ли
другой способ запросить состояние гарантированно без ожидания?

Так что да, реализация wait_free() несмотря на это все еще дело. Таким образом, это наиболее близко к выжидательную бесплатно вы собираетесь получить для проверки состояния.


1 Говоря простым языком, это означает «освобождение» ЦП и помещение вашего потока в конец очереди планировщика, что дает другим потокам некоторое время ЦП.

4

Другие решения

Чтобы ответить на ваш второй вопрос, в настоящее время нет способа проверить, готово ли будущее, кроме ожидания. Мы, вероятно, получим это в какой-то момент: https://en.cppreference.com/w/cpp/experimental/future/is_ready. Если ваша библиотека времени выполнения поддерживает расширения параллелизма, и вы не против использовать experimental в вашем коде, то вы можете использовать is_ready() сейчас. При этом я знаю несколько случаев, когда вы должны проверить состояние будущего. Вы уверены, что это необходимо?

1

Это все еще тот случай, когда timeout_duration равен 0?

Да. Это верно для любой операция. Планировщик ОС может приостановить поток (или весь процесс), чтобы позволить другому потоку работать на том же процессоре.

Если это так, есть ли другой способ запросить состояние гарантированно без ожидания?

Нет. Использование нулевого таймаута — правильный путь.

Нет даже гарантии, что общее состояние std::future не блокирует мьютекс, чтобы проверить, готов ли он, поэтому было бы невозможно гарантировать, что он был без ожидания.

Для реализации GCC флаг готовности является атомарным, поэтому нет необходимости в блокировке мьютекса, и если она готова, wait_for возвращается немедленно. Если это не готово, тогда есть еще несколько атомарных операций и затем проверка, чтобы видеть, истекло ли уже время ожидания, тогда системный вызов. Так что для нулевого тайм-аута есть только некоторые атомарные нагрузки и вызовы функций (без системного вызова).

1
По вопросам рекламы [email protected]