Namespaces
Variants

std:: async

From cppreference.net
Concurrency support library
Threads
(C++11)
(C++20)
this_thread namespace
(C++11)
(C++11)
Cooperative cancellation
Mutual exclusion
Generic lock management
Condition variables
(C++11)
Semaphores
Latches and Barriers
(C++20)
(C++20)
Futures
(C++11)
(C++11)
async
(C++11)
Safe reclamation
Hazard pointers
Atomic types
(C++11)
(C++20)
Initialization of atomic types
(C++11) (deprecated in C++20)
(C++11) (deprecated in C++20)
Memory ordering
(C++11) (deprecated in C++26)
Free functions for atomic operations
Free functions for atomic flags
헤더 파일에 정의됨 <future>
template < class F, class ... Args >
std:: future < /* see below */ > async ( F && f, Args && ... args ) ;
(1) (C++11부터)
template < class F, class ... Args >

std:: future < /* see below */ > async ( std:: launch policy,

F && f, Args && ... args ) ;
(2) (C++11부터)

함수 템플릿 std::async 는 함수 f 를 비동기적으로 (별도의 스레드에서, 이는 스레드 풀의 일부일 수 있음) 실행하고, 해당 함수 호출의 결과를 최종적으로 담게 될 std::future 를 반환합니다.

1) 마치 (2) policy 인자로 std:: launch :: async | std:: launch :: deferred 가 지정된 상태로 호출된 것처럼 동작합니다.
2) 특정 실행 정책 policy (아래 참조 )에 따라 함수 f 를 인수 args 와 함께 호출합니다.

std::async 의 반환 타입은 std:: future < V > 입니다. 여기서 V 는:

typename std:: result_of < typename std:: decay < F > :: type (
typename std:: decay < Args > :: type ... ) > :: type .

(C++17 이전)

std:: invoke_result_t < std:: decay_t < F > , std:: decay_t < Args > ... > .

(C++17 이후)


다음 조건 중 하나라도 만족되면 프로그램은 ill-formed입니다:

(C++20 이전)

다음 중 하나라도 false 이면 프로그램은 ill-formed입니다:

(C++20 이후)

std::async 호출은 동기화됩니다 f 호출과, 그리고 f 의 완료는 순서가 지정됩니다 공유 상태를 준비하기 전에.

목차

매개변수

f - Callable 호출할 객체
args - f 에 전달할 매개변수
policy - 개별 비트들이 허용된 실행 방법들을 제어하는 비트마스크 값

반환값

std::future std::async 호출로 생성된 공유 상태를 참조합니다.

실행 정책

비동기 호출

async 플래그가 설정된 경우, 즉 ( policy & std:: launch :: async ) ! = 0 이면, std::async 는 호출합니다

INVOKE ( decay-copy ( std:: forward < F > ( f ) ) ,
decay-copy ( std:: forward < Args > ( args ) ) ... )

(C++23 이전)

std:: invoke ( auto ( std:: forward < F > ( f ) ) ,
auto ( std:: forward < Args > ( args ) ) ... )

(C++23 이후)

마치 std::thread 객체로 표현되는 새로운 실행 스레드에서처럼.

decay-copy 호출은 현재 스레드에서 평가됩니다.

(until C++23)

auto 에 의해 생성된 값들은 현재 스레드에서 구체화됩니다 .

(since C++23)

함수 f 가 값을 반환하거나 예외를 던지면, 이는 std::future 를 통해 접근 가능한 공유 상태에 저장되며, 이 std::async 는 호출자에게 반환됩니다.

지연된 호출

만약 deferred 플래그가 설정된 경우(즉, ( policy & std:: launch :: deferred ) ! = 0 ), 그러면 std::async 는 저장합니다

decay-copy ( std:: forward < F > ( f ) ) decay-copy ( std:: forward < Args > ( args ) ) ... 를 공유 상태에 저장합니다.

(C++23 이전)

auto ( std:: forward < F > ( f ) ) auto ( std:: forward < Args > ( args ) ) ... 를 공유 상태에 저장합니다.

(C++23 이후)

지연 평가 가 수행됩니다:

  • 호출자에게 반환된 std::async std::future 에 대한 첫 번째 비시간 대기 함수 호출은 INVOKE ( std :: move ( g ) , std :: move ( xyz ) ) 를 대기 함수를 호출한 스레드에서 평가합니다(이는 원래 std::async 를 호출한 스레드일 필요는 없습니다).
(C++23 이전)
  • g auto ( std:: forward < F > ( f ) ) 의 저장된 값이고
  • xyz auto ( std:: forward < Args > ( args ) ) ... 의 저장된 복사본입니다.
(C++23 이후)
  • 결과나 예외는 반환된 std::future 와 연관된 공유 상태에 배치되며, 그 후에야 준비 상태가 됩니다. 동일한 std::future 에 대한 모든 추가 접근은 즉시 결과를 반환합니다.

기타 정책

만약 std::launch::async std::launch::deferred 도, 그리고 구현에서 정의된 정책 플래그도 policy 에 설정되지 않은 경우, 동작은 정의되지 않습니다.

정책 선택

둘 이상의 플래그가 설정된 경우, 어떤 정책이 선택될지는 구현에 따라 정의됩니다. 기본값( std::launch::async std::launch::deferred 플래그가 모두 policy 에 설정된 경우)에 대해서는 표준에서 사용 가능한 동시성을 활용하고 추가 작업을 지연시키는 것을 권장(하지만 요구하지는 않음)합니다.

만약 std::launch::async 정책이 선택되면,

  • std::async 호출에 의해 생성된 공유 상태를 공유하는 비동기 반환 객체의 대기 함수 호출은, 연결(joined)된 것처럼 관련 스레드가 완료되거나 타임아웃될 때까지 블록됩니다; 그리고
  • 관련 스레드 완료는 공유 상태를 대기하는 첫 번째 함수의 성공적 반환과, 또는 공유 상태를 해제하는 마지막 함수의 반환과 동기화됩니다(synchronizes-with) (둘 중 먼저 발생하는 것에 대해).

예외

Throws

참고 사항

구현체는 기본 실행 정책에 추가적인 (구현 정의) 비트를 활성화함으로써 std::async 의 첫 번째 오버로드 동작을 확장할 수 있습니다.

구현 정의된 실행 정책의 예로는 동기 정책(즉시 실행, std::async 호출 내에서)과 태스크 정책( std::async 와 유사하지만 스레드 로컬 변수가 초기화되지 않음)이 있습니다.

만약 std::future 에서 얻어진 std::async 가 이동되지 않거나 참조에 바인딩되지 않으면, std::future 의 소멸자는 전체 표현식의 끝에서 비동기 연산이 완료될 때까지 블록하게 되어, 결과적으로 다음과 같은 코드는 본질적으로 동기적으로 동작합니다:

std::async(std::launch::async, []{ f(); }); // 임시 객체의 소멸자가 f()의 완료를 대기함
std::async(std::launch::async, []{ g(); }); // f()가 완료될 때까지 시작되지 않음

std::future std::async 호출 이외의 방법으로 획득한 경우, 해당 소멸자들은 절대 블록(block)하지 않습니다.

예제

#include <algorithm>
#include <future>
#include <iostream>
#include <mutex>
#include <numeric>
#include <string>
#include <vector>
std::mutex m;
struct X
{
    void foo(int i, const std::string& str)
    {
        std::lock_guard<std::mutex> lk(m);
        std::cout << str << ' ' << i << '\n';
    }
    void bar(const std::string& str)
    {
        std::lock_guard<std::mutex> lk(m);
        std::cout << str << '\n';
    }
    int operator()(int i)
    {
        std::lock_guard<std::mutex> lk(m);
        std::cout << i << '\n';
        return i + 10;
    }
};
template<typename RandomIt>
int parallel_sum(RandomIt beg, RandomIt end)
{
    auto len = end - beg;
    if (len < 1000)
        return std::accumulate(beg, end, 0);
    RandomIt mid = beg + len / 2;
    auto handle = std::async(std::launch::async,
                             parallel_sum<RandomIt>, mid, end);
    int sum = parallel_sum(beg, mid);
    return sum + handle.get();
}
int main()
{
    std::vector<int> v(10000, 1);
    std::cout << "The sum is " << parallel_sum(v.begin(), v.end()) << '\n';
    X x;
    // 기본 정책으로 (&x)->foo(42, "Hello") 호출:
    // "Hello 42"를 동시에 출력하거나 실행을 지연시킬 수 있음
    auto a1 = std::async(&X::foo, &x, 42, "Hello");
    // 지연 정책으로 x.bar("world!") 호출
    // a2.get() 또는 a2.wait()이 호출될 때 "world!" 출력
    auto a2 = std::async(std::launch::deferred, &X::bar, x, "world!");
    // 비동기 정책으로 X()(43) 호출
    // "43"을 동시에 출력
    auto a3 = std::async(std::launch::async, X(), 43);
    a2.wait();                     // "world!" 출력
    std::cout << a3.get() << '\n'; // "53" 출력
} // 이 시점에서 a1이 완료되지 않았다면, a1의 소멸자가 여기서 "Hello 42"를 출력함

가능한 출력:

The sum is 10000
43
world!
53
Hello 42

결함 보고서

다음 동작 변경 결함 보고서들은 이전에 발표된 C++ 표준에 소급 적용되었습니다.

DR 적용 대상 게시된 동작 수정된 동작
LWG 2021 C++11 지연된 경우 반환 타입이 잘못되었고
인수의 값 카테고리가 불명확함
반환 타입 수정 및
rvalue가 사용됨을 명확히 함
LWG 2078 C++11 std::system_error 예외가 policy std::launch::async 이외의
다른 launch 정책이 지정된 경우에도 발생할 수 있는지 불명확함
policy == std:: launch :: async 인 경우에만
발생할 수 있음
LWG 2100 C++11 시간 제한 대기 함수들이 std::launch::async 정책이
사용된 경우 시간 초과할 수 없었음
허용됨
LWG 2120 C++11 표준 또는 구현 정의 정책이 설정되지 않은
경우의 동작이 불명확했음
이 경우 동작은
정의되지 않음
LWG 2186 C++11 지연 평가에서 반환된 값과 발생한 예외를
어떻게 처리하는지 불명확했음
공유 상태에
저장됨
LWG 2752 C++11 std::async 가 내부 데이터 구조를 위한 메모리를
할당할 수 없는 경우 std::bad_alloc 를 발생시키지 않을 수 있었음
발생시킴
LWG 3476 C++20 (decay된 타입의) F 와 인수 타입들이 직접적으로
이동 생성 가능해야 했음
이러한 요구사항 제거 [1]
  1. 이동 생성 가능성은 이미 간접적으로 std::is_constructible_v 에 의해 요구됩니다.

참고 항목

(C++11)
비동기적으로 설정되는 값을 기다림
(클래스 템플릿)
C++ documentation for Execution support library