Я немного запутался в требованиях с точки зрения безопасности потоков, размещенных в std::promise::set_value()
.
Эффекты: атомарно сохраняет значение r в общем состоянии и делает это состояние готовым
Тем не менее, он также говорит, что promise::set_value()
может использоваться только для установки значения один раз. Если он вызывается несколько раз, std::future_error
. Таким образом, вы можете установить значение обещания только один раз.
И действительно, почти каждый учебник, пример кода в сети или фактический вариант использования для std::promise
включает канал связи между двумя потоками, где один поток вызывает std::future::get()
, а другой поток вызывает std::promise::set_value()
.
Я никогда не видел случая использования, когда несколько потоков могли бы вызывать std::promise::set_value()
, и даже если бы они это делали, все, кроме одного, вызывали бы исключение std::future_error
.
Так почему же стандартный мандат, который вызывает std::promise::set_value()
является атомарным? Каков вариант использования для одновременного вызова std::promise::set_value()
из нескольких потоков?
РЕДАКТИРОВАТЬ:
Так как ответ с наибольшим количеством голосов здесь на самом деле не отвечает на мой вопрос, я предполагаю, что то, что я спрашиваю, неясно. Итак, чтобы уточнить: я в курсе, что такое будущее и обещания и как они работают. У меня вопрос, почему, в частности, стандарт настаивает на том, что std::promise::set_value()
должен быть атомарным? Это более тонкий вопрос, чем "почему не должно быть гонки между вызовами promise::set_value()
и вызовами future::get()
"?
На самом деле, многие ответы здесь (неправильно) отвечают, что причина в том, что если std::promise::set_value()
не является атомарным, то std::future::get()
потенциально может вызвать состояние гонки. Но это не так.
Единственное требование избегать условия гонки - это то, что std::promise::set_value()
должна иметь отношение " происходит до" с std::future::get()
- другими словами, должно быть гарантировано, что когда std::future::wait()
возвращает, std::promise::set_value()
завершено.
Это полностью ортогонально тому, что std::promise::set_value()
сам по себе является атомарным или нет. В типичной реализации, использующей условные переменные, std::future::get()/wait()
будет ожидать условную переменную. Затем std::promise::set_value()
может std::promise::set_value()
выполнять любые произвольно сложные вычисления, чтобы установить фактическое значение. Затем он уведомил бы переменную общего условия (подразумевающую ограничение памяти с семантикой выпуска), и std::future::get()
проснулся бы и безопасно прочитал результат.
Таким образом, std::promise::set_value()
само по себе не обязательно должно быть атомарным, чтобы избежать здесь условия гонки - оно просто должно удовлетворять отношению "происходит до" с std::future::get()
.
Итак, еще раз, мой вопрос: почему стандарт C++ настаивает на том, что std::promise::set_value()
должна быть атомарной операцией, как если бы вызов std::promise::set_value()
был выполнен полностью в блокировка мьютекса? Я не вижу причин, по которым это требование должно существовать, если только не существует какой-либо причины или std::promise::set_value()
использования для нескольких потоков, вызывающих std::promise::set_value()
одновременно. И я не могу придумать такой вариант использования, отсюда и этот вопрос.