Поведение std :: async (std :: launch :: deferred) + std :: future :: then

Идея отложенного будущего (достигается только путем вызова std::async с флагом std::launch::deferred) заключается в том, что обратный вызов вызывается только тогда, когда кто-то пытается подождать или вытащить футуристическое значение или исключение будущего. к тому времени обратный вызов не выполняется.

Что произойдет, если я прикреплю продолжение к отложенному будущему с std::future::then? отложенное будущее теряется (then аннулирует будущее), и вместо него возвращается новое будущее.

В таком случае по стандарту что должно произойти? новое будущее - это тоже отложенное будущее? это просто тупик? этот вопрос не рассматривается в последней версии документации.

В более ранней версии проекта спецификации (open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3721.pdf) упоминается: Если у родителя есть политика launch :: deferred, а у продолжения нет указанной политики запуска или планировщика, то родительский элемент заполняется немедленным вызовом .wait (), а политика предшествующего элемента - launch :: deferred.

Matthias247 22.07.2018 07:44

Однако я больше не могу найти это в более новой версии open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0159r0.html

Matthias247 22.07.2018 07:45
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
21
2
626
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

На мой взгляд, это ошибка в ТС. Или, по крайней мере, недокументированная ловушка.

Вот текст из TS:

2.3 [futures.unique_future] / 6-10

template <class F>
see below then(F&& func);

Requires:

INVOKE(DECAY_COPY (std::forward<F>(func)), std::move(*this)) shall be a valid expression.

Effects:

The function creates a shared state that is associated with the returned future object. Additionally,

When the object's shared state is ready, the continuation INVOKE(DECAY_COPY(std::forward<F>(func)), std::move(*this)) is called on an unspecified thread of execution with the call to DECAY_COPY() being evaluated in the thread that called then.

Any value returned from the continuation is stored as the result in the shared state of the resulting future. Any exception propagated from the execution of the continuation is stored as the exceptional result in the shared state of the resulting future.

Returns:

When result_of_t<decay_t<F>(future<R>)> is future<R2>, for some type R2, the function returns future<R2>. Otherwise, the function returns future<result_of_t<decay_t<F>(future<R>)>>. [ Note: The rule above is referred to as implicit unwrapping. Without this rule, the return type of then taking a callable returning a future<R> would have been future<future<R>>. This rule avoids such nested future objects. The type of f2 below is future<int> and not future<future<int>>:

[ Example:

future<int> f1 = g();
future<int> f2 = f1.then([](future<int> f) {
                    future<int> f3 = h();
                    return f3;
                 });

— end example ]

— end note ]

Postconditions:

valid() == false on the original future. valid() == true on the future returned from then. [ Note: In case of implicit unwrapping, the validity of the future returned from thenfunc cannot be established until after the completion of the continuation. If it is not valid, the resulting future becomes ready with an exception of type std::future_error, with an error condition of std::future_errc::broken_promise. — end note ]

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

Текст для shared_future аналогичен; там, однако, вы все равно можете заставить shared_future подготовиться к работе после вызова .then.

Если это предусмотрено; что .then в неготовом отложенном уникальном будущем приведет к возвращаемому значению future, которое никогда не может быть подготовлено - это должно быть явно указано в TS / стандарте. Если это не предусмотрено, стандартный текст необходимо изменить.

Обратите внимание, что эти изменения не отражены в N4762 проект стандарта, опубликованном в 2018 году.

Я не уверен, как стандарт должен это исправить; семантика .then разумна для shared_future, но не для future, и различие семантики было бы неожиданным.

Другие вопросы по теме