Является ли вызов wait() в std:: будущем несколько раз и из нескольких потоков безопасным?

Я пытаюсь определить, когда я могу безопасно называть wait() на std::future и std::shared_future. Я никогда не называю get() на future, а future готов к вызову с помощью соответствующего метода set_value().

Я хочу ждать этого future (используя wait(), wait_for(), wait_until()) из нескольких потоков. Мне также нужны вызовы wait() после того, как promise::set_value() был вызван для немедленного возврата.

Из http://www.cplusplus.com/reference/future/future/wait/

Вызов этой функции-члена для недопустимого будущего объекта вызывает поведение undefined

Получение future из promise начинается с valid()==true. Насколько я вижу только future::get() устанавливает valid() обратно на false. Правильно ли это предположение? Могу ли я назвать семейство функций wait() так часто, как я хочу? Будет ли звонить на wait() после того, как значение обещания будет установлено сразу же? Могу ли я вызвать их из нескольких потоков?

Ответ 1

Получение будущего от обещания начинает его с valid() == true. Насколько я вижу, только future:: get() устанавливает valid() обратно на false. Правильно ли это предположение?

Он также может стать недействительным, переместив ему недопустимое будущее или переместив будущее, чтобы его совместное состояние передавалось другому объекту. Он не может стать недействительным только путем ожидания.

Можно ли вызвать семейство функций wait() так часто, как я хочу?

Да.

Будет ли ждать wait() после немедленного возврата значения обещания?

Да (это может быть связано с блокировкой мьютекса или спин-блокировки для проверки готовности состояния, а затем возврата, поэтому может потребоваться небольшое ожидание для блокировки)

Можно ли их вызвать из нескольких потоков?

Да.

wait() - это функция-член const, поэтому библиотека должна гарантировать, что она может быть вызвана в одном будущем объекте из нескольких потоков без какой-либо пользовательской синхронизации.

Ответ 2

Доступ к одному future из нескольких потоков может привести к гонке данных и undefined, если хотя бы один из них может выполнить get(), и никакая правильная синхронизация не позволит избежать такой ситуации.

Следовательно, если вам нужно получить доступ к future из нескольких потоков, лучше рассмотреть shared_future: "Они также позволяют использовать значение в общей папке состояние, которое будет извлекаться несколько раз после его готовности" . Они потокобезопасны, пока каждый поток обращается к совместному будущему, используя свой собственный объект shared_future.

Примечание: В моем ответе предполагается, что в какой-то момент может произойти get(), поскольку в обещании явно не указано promise<void>