это потокобезопасно?
Нет, но это не имеет значения.
std::future
предназначено для использования в одном потоке и не являетсяпоточно-ориентированный дизайн.Нет смысла делить его между несколькими потоками.Вы должны вызвать get()
только один раз, а затем выбросить его.
(Поток, который запускает присоединенную операцию и устанавливает значение, возвращаемое get()
, здесь не имеет значения. Реализация управляети скрывает необходимую для вас синхронизацию.)
(Конечно, вы можете передавать право собственности на std ::uture из одного потока в другой. Но в любой момент времени должен удерживаться только один потоки используйте std :: future.)
Может ли оно быть изменяемым?
Да.Фактически, std::future
не может быть const
, так как его состояние изменяется по определению, когда присоединенная операция завершается и когда вы вызываете get()
.
Однако mutable
не должно быть ключевым словом, которое нужно искать здесь.Конечно, вы можете обернуть std::future
в class
или struct
ключевым словом mutable
, а затем создать const
экземпляр этого класса, но вы скрываете важную часть информации (а именно, что вашаобертка совсем не const). (Это может иметь смысл в более сложном классе, но я бы сказал, что сложный класс с членом std :: future является признаком плохого дизайна.)
Вместо этого вы должны сделатьтакой класс-оболочка или структура также неконстантные:
template <typename T>
struct S {
void query() {
m_fut = doAsyncQuery();
}
template <typename L>
void get(L lambda) { // remove const here
lambda(m_f.get());
}
std::future<T> m_f; // remove mutable here
};
Пока вы знаете, что экземпляры S
не должны быть константными, вы можете вызывать get
только один раз, и этовы не должны делиться S
между потоками, вы должны быть в безопасности.