33 Thread support library [thread]

33.6 Futures [futures]

33.6.9 Function template async [futures.async]

Шаблон функции async предоставляет механизм для запуска функции потенциально в новом потоке и предоставляет результат функции в future объекте, с которым он разделяет общее состояние.

template <class F, class... Args> future<invoke_result_t<decay_t<F>, decay_t<Args>...>> async(F&& f, Args&&... args); template <class F, class... Args> future<invoke_result_t<decay_t<F>, decay_t<Args>...>> async(launch policy, F&& f, Args&&... args);

Requires: F и каждый Ti в Args должен удовлетворять MoveConstructible требованиям, и

INVOKE(DECAY_COPY(std::forward<F>(f)),
       DECAY_COPY(std::forward<Args>(args))...)     // see [func.require], [thread.thread.constr]

должно быть допустимым выражением.

Effects: Первая функция ведет себя так же, как вызов второй функции с policy аргументом launch​::​async | launch​::​deferred и теми же аргументами для F и Args. Вторая функция создает общее состояние, связанное с возвращаемым future объектом. Дальнейшее поведение второй функции зависит от policy аргумента следующим образом (если применяется более одного из этих условий, реализация может выбрать любую из соответствующих политик):

  • Если launch​::​async установлено policy, вызывает INVOKE(DECAY_­COPY(std​::​forward<F>(f)), DECAY_­COPY(std​::​forward<Args>(args))...) ([func.require], [thread.thread.constr]), как если бы в новом потоке выполнения, представленном thread объектом, с вызовами DECAY_­COPY() , оцениваемыми в вызвавшем потоке async. Любое возвращаемое значение сохраняется как результат в общем состоянии. Любое исключение, возникшее в результате выполнения, INVOKE(DECAY_­COPY(std​::​forward<F>(f)), DECAY_­COPY(std​::​forward<Args>(args))...) сохраняется как исключительный результат в общем состоянии. thread Объект хранится в совместно используемом состоянии и влияет на поведение любого асинхронного возврата объекты , которые ссылаются , что состояния.

  • Если launch​::​deferred установлено policy, хранит DECAY_­COPY(std​::​forward<F>(f)) и DECAY_­COPY(std​::​forward<Args>(args))... в общем состоянии. Эти копии f и args составляют deferred function. Вызов отложенной функции оценивает, INVOKE(std​::​move(g), std​::​move(xyz)) где g находится сохраненное значение, DECAY_­COPY(std​::​forward<F>(f)) а где xyz - сохраненная копия DECAY_­COPY(std​::​forward<Args>(args)).... Любое возвращаемое значение сохраняется как результат в общем состоянии. Любое исключение, возникшее в результате выполнения отложенной функции, сохраняется как исключительный результат в общем состоянии. Общее состояние не становится готовым, пока функция не завершится. Первый вызов функции ожидания без времени ([futures.state]) для асинхронного возвращаемого объекта, ссылающегося на это совместно используемое состояние, должен вызывать отложенную функцию в потоке, который вызвал функцию ожидания. После начала оценки INVOKE(std​::​move(g), std​::​move(xyz)) функция больше не считается отложенной. [ Note: Если эта политика указана вместе с другими политиками, например, при использовании policy значения launch​::​async | launch​::​deferred, реализации должны отложить вызов или выбор политики, когда параллелизм больше не может быть эффективно использован. ] end note

  • Если в политике запуска не задано значение или установлено значение, которое не указано ни в этом международном стандарте, ни в реализации, поведение не определено.

Returns: Объект типа, future<invoke_­result_­t<decay_­t<F>, decay_­t<Args>...>> который ссылается на общее состояние, созданное этим вызовом async. [ Note: Если будущее, полученное из async , перемещается за пределы локальной области видимости, другой код, который использует будущее, должен знать, что деструктор будущего может заблокироваться, чтобы общее состояние стало готовым. ] end note

Synchronization: Независимо от приведенного policy аргумента,

  • призыв async synchronizes with призывания f. [ Note: Это утверждение применяется, даже когда соответствующий future объект перемещается в другой поток. ]; а также end note

  • завершение функции f происходит до ([intro.multithread]) готовности общего состояния. [ Note: f может вообще не вызываться, поэтому его завершение может никогда не произойти. ] end note

Если реализация выбирает launch​::​async политику,

  • вызов функции ожидания на асинхронном возвращаемом объекте, который разделяет общее состояние, созданное этим async вызовом, должен блокироваться до тех пор, пока связанный поток не завершится, как если бы он был присоединен, или иначе истечет время ожидания ([thread.thread.member]);

  • связанный поток завершает synchronizes with возврат из первой функции, которая успешно определяет состояние готовности совместно используемого состояния, или возвратом из последней функции, которая освобождает совместно используемое состояние, в зависимости от того, что произойдет раньше.

Throws: system_­error если policy == launch​::​async и реализация не может запустить новый поток, или std​::​bad_­alloc если память для внутренних структур данных не может быть выделена.

Error conditions:

  • resource_­unavailable_­try_­again - если policy == launch​::​async и система не может начать новый поток.

[Example:

int work1(int value);
int work2(int value);
int work(int value) {
  auto handle = std::async([=]{ return work2(value); });
  int tmp = work1(value);
  return tmp + handle.get();    // #1
}

[ Note: Строка №1 может не привести к параллелизму, потому что async вызов использует политику по умолчанию, которая может использовать launch​::​deferred, и в этом случае лямбда может не вызываться до get() вызова; в этом случае work1 и work2 вызываются в одном потоке, и параллелизма нет. ] ]end noteend example