Language
日本語
English

Caution

JavaScript is disabled in your browser.
This site uses JavaScript for features such as search.
For the best experience, please enable JavaScript before browsing this site.

  1. Home
  2. C++ Dictionary
  3. std::async / std::future

std::async / std::future

The <future> header in C++ provides std::async and std::future for writing asynchronous code without directly managing thread creation and joining. std::async launches a function asynchronously and returns a std::future through which you retrieve the result later. Because thread lifetime is managed automatically, this is generally safer than using std::thread directly.

Syntax

#include <future>
#include <iostream>

int compute() { return 42; }

// std::launch::async  -> start a new thread immediately
// std::launch::deferred -> execute lazily on the calling thread when get() is called
// Omitting the policy is implementation-defined (explicitly specifying async is common)
std::future<int> fut = std::async(std::launch::async, compute);

// Retrieve the result (blocks until ready)
// get() can be called only once (calling it a second time is undefined behavior)
int result = fut.get();

// wait() blocks until the result is ready without retrieving it
fut.wait();

// wait_for() waits for a specified duration
std::future_status status = fut.wait_for(std::chrono::seconds(1));
if (status == std::future_status::ready) {
    // result is available
} else if (status == std::future_status::timeout) {
    // timed out
} else {
    // deferred (not yet executed)
}

// std::promise: set a value manually
std::promise<int> prom;
std::future<int> fut2 = prom.get_future();
prom.set_value(100);       // sets the value returned by fut2.get()
// prom.set_exception(...)  // can also propagate exceptions

Syntax Reference

Syntax / ClassDescription
std::async(policy, f, args...)Launches function f asynchronously and returns a std::future. Specifying std::launch::async starts a new thread immediately.
std::future<T>An object representing the future result of an asynchronous operation. Calling get() blocks until the result is ready.
future.get()Retrieves the result of the asynchronous operation. Blocks if not yet complete. Can be called only once.
future.wait()Blocks until the result is ready without retrieving it.
future.wait_for(duration)Waits for a given duration and returns a std::future_status. Useful for timeout detection.
future.valid()Returns whether the future has a valid shared state. Becomes false after get() is called.
std::promise<T>An object for manually setting a value or exception on a future. Use get_future() to obtain the associated future.
promise.set_value(v)Sets the value that the associated future will return.
promise.set_exception(e)Propagates an exception to the associated future. The exception is rethrown when get() is called.
std::shared_future<T>A future that can be get()-ed multiple times and shared between threads. Obtained via future::share().

Sample Code

eva_async.cpp
#include <iostream>
#include <future>
#include <chrono>
#include <string>
#include <stdexcept>

// Ikari Shinji: analyzes the A.T. Field strength of an Angel
int analyzeShinji(const std::string& angelName) {
    std::cout << "[Ikari Shinji] Starting A.T. Field analysis for "
              << angelName << "..." << std::endl;
    std::this_thread::sleep_for(std::chrono::milliseconds(300));
    std::cout << "[Ikari Shinji] Analysis complete." << std::endl;
    return 8750;
}

// Ayanami Rei: determines the core position of an Angel
std::string analyzeRei(const std::string& angelName) {
    std::cout << "[Ayanami Rei] Starting core position identification for "
              << angelName << "." << std::endl;
    std::this_thread::sleep_for(std::chrono::milliseconds(200));
    std::cout << "[Ayanami Rei] Identification complete." << std::endl;
    return "Central chest, depth 12.5m";
}

// Asuka Langley: calculates Unit-02 maximum output
// Simulates failure with an exception
double calcAsuka(bool syncRateOk) {
    std::cout << "[Asuka Langley] Starting max output calculation!" << std::endl;
    std::this_thread::sleep_for(std::chrono::milliseconds(150));
    if (!syncRateOk) {
        throw std::runtime_error("Sync rate too low!");
    }
    std::cout << "[Asuka Langley] Calculation complete. Of course, I am a genius." << std::endl;
    return 14.5;
}

// Nagisa Kaworu: passes an Angel identification code via std::promise
void kaworu(std::promise<std::string>& prom) {
    std::cout << "[Nagisa Kaworu] Generating Angel identification code." << std::endl;
    std::this_thread::sleep_for(std::chrono::milliseconds(250));
    prom.set_value("TABRIS-17-OMEGA");
    std::cout << "[Nagisa Kaworu] Generation complete." << std::endl;
}

// Katsuragi Misato coordinates all analyses
int main() {
    std::cout << "=== NERV Angel Interception Data Integration System ===" << std::endl;
    std::cout << "[Katsuragi Misato] Requesting analyses from all pilots." << std::endl << std::endl;

    const std::string targetAngel = "Angel 17 Tabris";

    // Launch each pilot's task asynchronously
    std::future<int> futShinji =
        std::async(std::launch::async, analyzeShinji, targetAngel);
    std::future<std::string> futRei =
        std::async(std::launch::async, analyzeRei, targetAngel);
    std::future<double> futAsuka =
        std::async(std::launch::async, calcAsuka, true);

    // Kaworu sets the value via std::promise
    std::promise<std::string> kaworuPromise;
    std::future<std::string> futKaworu = kaworuPromise.get_future();
    std::future<void> kaworuThread =
        std::async(std::launch::async, kaworu, std::ref(kaworuPromise));

    std::cout << std::endl;
    std::cout << "[Katsuragi Misato] Waiting for all analyses..." << std::endl << std::endl;

    // wait_for with timeout
    std::future_status shinji_status = futShinji.wait_for(std::chrono::seconds(2));
    if (shinji_status == std::future_status::ready) {
        int atFieldStrength = futShinji.get();
        std::cout << "[Katsuragi Misato] Shinji's result: A.T. Field strength = "
                  << atFieldStrength << " cross-sections" << std::endl;
    } else {
        std::cout << "[Katsuragi Misato] Shinji's analysis timed out." << std::endl;
    }

    // Retrieve Rei's result (blocks if not yet complete)
    std::string corePosition = futRei.get();
    std::cout << "[Katsuragi Misato] Rei's result: Core position = " << corePosition << std::endl;

    // Retrieve Asuka's result with exception handling
    try {
        double maxOutput = futAsuka.get();
        std::cout << "[Katsuragi Misato] Asuka's result: Unit-02 max output = "
                  << maxOutput << " TW" << std::endl;
    } catch (const std::exception& e) {
        std::cout << "[Katsuragi Misato] Exception from Asuka's task: " << e.what() << std::endl;
    }

    // Retrieve Kaworu's promise-based result
    std::string angelId = futKaworu.get();
    kaworuThread.get();
    std::cout << "[Katsuragi Misato] Kaworu's identification code: " << angelId << std::endl;

    std::cout << std::endl;
    std::cout << "=== All analyses complete. Begin interception. Go! ===" << std::endl;

    return 0;
}
g++ -std=c++11 eva_async.cpp -o eva_async -lpthread
./eva_async
=== NERV Angel Interception Data Integration System ===
[Katsuragi Misato] Requesting analyses from all pilots.

[Ikari Shinji] Starting A.T. Field analysis for Angel 17 Tabris...
[Ayanami Rei] Starting core position identification for Angel 17 Tabris.
[Asuka Langley] Starting max output calculation!
[Nagisa Kaworu] Generating Angel identification code.
[Asuka Langley] Calculation complete. Of course, I am a genius.
[Ayanami Rei] Identification complete.
[Nagisa Kaworu] Generation complete.

[Katsuragi Misato] Waiting for all analyses...

[Ikari Shinji] Analysis complete.
[Katsuragi Misato] Shinji's result: A.T. Field strength = 8750 cross-sections
[Katsuragi Misato] Rei's result: Core position = Central chest, depth 12.5m
[Katsuragi Misato] Asuka's result: Unit-02 max output = 14.5 TW
[Katsuragi Misato] Kaworu's identification code: TABRIS-17-OMEGA

=== All analyses complete. Begin interception. Go! ===

Common Mistake 1: Calling future::get() more than once

std::future::get() can only be called once. Calling it a second time is undefined behavior. Use std::shared_future when multiple calls to get() are needed.

// NG: calling get() twice causes undefined behavior
std::future<int> fut = std::async(std::launch::async, []() { return 42; });
int r1 = fut.get();  // first call: OK
int r2 = fut.get();  // second call: undefined behavior

OK: Convert to std::shared_future for multiple get() calls.

// OK: shared_future allows multiple get() calls
std::shared_future<int> sfut = std::async(std::launch::async, []() { return 42; }).share();
int r1 = sfut.get();  // OK
int r2 = sfut.get();  // OK

Common Mistake 2: Omitting the launch policy

Omitting the launch policy makes the behavior implementation-defined; the task might be deferred rather than launched on a new thread. Specify std::launch::async explicitly when immediate execution on a new thread is required.

// Caution: policy omitted — may be deferred
auto fut = std::async(computeHeavyTask);

// OK: explicitly request a new thread
auto fut = std::async(std::launch::async, computeHeavyTask);

Overview

std::async is a higher-level asynchronous execution mechanism than std::thread. Specifying std::launch::async starts a new thread immediately and returns a std::future. Calling std::future::get() blocks until the operation completes and then retrieves the result; thread join management is automatic. Exceptions thrown inside the asynchronous operation are stored in the future and rethrown when get() is called, making them safe to handle with try-catch. std::promise is useful when you need to pass a value to a future from a callback or external event rather than a function return value. Once get() has been called, a std::future becomes invalid, but converting it to a std::shared_future via share() allows the same result to be accessed from multiple threads. On Linux, link with -lpthread for thread support.

If you find any errors or copyright issues, please .