[2026] C++ async & launch | Asynchronous Execution Guide

[2026] C++ async & launch | Asynchronous Execution Guide

이 글의 핵심

C++11 std::async. Asynchronous execution and launch policies.

originalId: cpp-async-launch

What is std::async?

std::async is a C++11 API that executes a function asynchronously and retrieves the result using a future. The result can also be shared using promise·future and shared_future. If you’re familiar with thread basics, it’s easy to use.

#include <future>
auto future = std::async([]() {
    return 42;
});
int result = future.get();  // Wait for the result

launch Policies

Comparison of launch Policies

PolicyExecution TimingThread CreationUse Case
launch::asyncImmediately✅ New threadCPU-intensive tasks
launch::deferredOn get() call❌ Current threadConditional execution
async | deferredImplementation-definedAuto-selectedGeneral use
// async: New thread
auto f1 = std::async(std::launch::async, func);
// deferred: Delayed execution
auto f2 = std::async(std::launch::deferred, func);
// Default: async | deferred
auto f3 = std::async(func);

Execution Flow by Policy

sequenceDiagram
    participant Main as Main Thread
    participant Async as Async Thread
    Note over Main: launch::async
    Main->>Async: start immediately
    Main->>Main: other work
    Async->>Async: background exec
    Main->>Async: future.get()
    Async->>Main: return result
    Note over Main: launch::deferred
    Main->>Main: async call (no exec)
    Main->>Main: other work
    Main->>Main: future.get()
    Main->>Main: exec func now
    Main->>Main: return result

Practical Examples

Example 1: Basic Usage

#include <future>
#include <iostream>
int compute(int x) {
    std::this_thread::sleep_for(std::chrono::seconds(1));
    return x * x;
}
int main() {
    auto future = std::async(compute, 10);
    
    std::cout << "Computing..." << std::endl;
    
    int result = future.get();  // Wait
    std::cout << "Result: " << result << std::endl;  // 100
}

Example 2: Multiple Asynchronous Tasks

auto f1 = std::async([]() { return compute1(); });
auto f2 = std::async([]() { return compute2(); });
auto f3 = std::async([]() { return compute3(); });
// Parallel execution
int r1 = f1.get();
int r2 = f2.get();
int r3 = f3.get();
int total = r1 + r2 + r3;

Parallel Execution Timeline:

gantt
    title Parallel vs Sequential Execution Comparison
    dateFormat X
    axisFormat %L
    
    section Parallel (async)
    compute1 :0, 1000
    compute2 :0, 1000
    compute3 :0, 1000
    
    section Sequential Execution
    compute1 :0, 1000
    compute2 :1000, 2000
    compute3 :2000, 3000

Performance Comparison:

Execution ModeTask DurationTotal TimePerformance Gain
Sequential Execution1 sec × 33 sec-
Parallel Execution (async)1 sec (concurrent)1 sec3x

Example 3: launch Policies

// Immediate execution (new thread)
auto f1 = std::async(std::launch::async, []() {
    std::cout << "Asynchronous execution" << std::endl;
    return 42;
});
// Delayed execution (on get call)
auto f2 = std::async(std::launch::deferred, []() {
    std::cout << "Deferred execution" << std::endl;
    return 42;
});
f2.get();  // Executes here

Example 4: Exception Handling

auto future = std::async([]() {
    throw std::runtime_error("Error");
    return 42;
});
try {
    int result = future.get();  // Rethrows exception
} catch (const std::exception& e) {
    std::cout << "Exception: " << e.what() << std::endl;
}

Checking future Status

auto future = std::async(std::launch::async, compute);
// Wait
future.wait();
// Timeout
auto status = future.wait_for(std::chrono::seconds(1));
if (status == std::future_status::ready) {
    std::cout << "Completed" << std::endl;
} else if (status == std::future_status::timeout) {
    std::cout << "Timeout" << std::endl;
}

Common Issues

Issue 1: Future Destruction

// ❌ Ignoring future
std::async([]() {
    // Task
});  // Blocks in destructor
// ✅ Store the future
auto future = std::async([]() {
    // Task
});

Issue 2: Multiple get Calls

auto future = std::async([]() { return 42; });
int r1 = future.get();  // OK
// int r2 = future.get();  // Error: get already called
// get can only be called once

Issue 3: Exception Propagation

auto future = std::async([]() {
    throw std::runtime_error("Error");
});
// Exception is thrown on get call
try {
    future.get();
} catch (...) {
    // Handle exception
}

Issue 4: Deadlock

// ❌ Potential deadlock
std::mutex mtx;
auto future = std::async([&mtx]() {
    std::lock_guard<std::mutex> lock(mtx);
    // ...
});
std::lock_guard<std::mutex> lock(mtx);
future.get();  // Deadlock

async vs thread

// std::async: Simple, returns future
auto future = std::async([]() { return 42; });
int result = future.get();
// std::thread: Manual management
std::thread t([]() {
    // Hard to return result
});
t.join();

FAQ

Q1: When to use std::async?

A: When you need to execute a function asynchronously and retrieve its result.

Q2: What are the launch policies?

A:

  • async: New thread
  • deferred: Delayed execution

Q3: get vs wait?

A:

  • get: Returns the result
  • wait: Only waits for completion

Q4: How to handle exceptions?

A: Exceptions are rethrown when get is called.

Q5: Performance considerations?

A: Thread creation has overhead. For small tasks, this overhead might outweigh the benefits.

Q6: Resources for learning async?

A:

... 996 lines not shown ... Token usage: 63706/1000000; 936294 remaining Start-Sleep -Seconds 3