std::async în C++

Rulează o funcție (de obicei pe alt fir) și îți dă un std::future din care iei rezultatul mai târziu.

Sintaxă
#include <future>
std::future<R> f = std::async(std::launch::async, functie, argumente...);
R rezultat = f.get();

Ce face std::async

std::async este cel mai simplu mod de a rula ceva în paralel și de a primi înapoi un rezultat. Returnează un std::future; când ai nevoie de rezultat, apelezi get(), care așteaptă dacă funcția nu a terminat încă.

Primul parametru alege modul: std::launch::async pornește un fir nou imediat; std::launch::deferred amână execuția până la get(), pe firul care cere rezultatul. Fără acest parametru, implementarea alege singură; pentru paralelism real, scrie explicit std::launch::async.

Dacă funcția aruncă o excepție, aceasta este păstrată și aruncată din nou la get().

Parametri

Parametru Descriere
std::launch::async / deferred Opțional: modul de lansare.
functie, argumente Ce se rulează; argumentele sunt copiate.

Ce returnează

Un std::future<R>, unde R este tipul returnat de funcție.

Exemple

Exemplul 1: Două calcule în paralel

#include <functional>
#include <future>
#include <numeric>
#include <print>
#include <vector>

long long suma(const std::vector<int>& v, std::size_t de, std::size_t pana) {
    return std::accumulate(v.begin() + de, v.begin() + pana, 0LL);
}

int main() {
    std::vector<int> vanzari(10'000, 3);

    auto prima = std::async(std::launch::async, suma, std::cref(vanzari), 0, 5'000);
    auto aDoua = std::async(std::launch::async, suma, std::cref(vanzari), 5'000, 10'000);

    std::println("Total: {}", prima.get() + aDoua.get());
}

Rezultat

Total: 30000

Exemplul 2: Excepția ajunge la get()

#include <future>
#include <print>
#include <stdexcept>
#include <string>

std::string descarca(const std::string& adresa) {
    if (adresa.empty()) throw std::invalid_argument("adresă goală");
    return "conținutul de la " + adresa;
}

int main() {
    auto bun = std::async(std::launch::async, descarca, "dexblog.ro");
    auto rau = std::async(std::launch::async, descarca, "");

    std::println("{}", bun.get());
    try {
        std::println("{}", rau.get());
    } catch (const std::exception& e) {
        std::println("Eroare: {}", e.what());
    }
}

Rezultat

conținutul de la dexblog.ro
Eroare: adresă goală

Greșeli frecvente

  • Ignori valoarea returnată: std::async(std::launch::async, f);. Destructorul future-ului temporar așteaptă imediat terminarea, deci nu rulează nimic în paralel (iar compilatorul avertizează, pentru că rezultatul este [[nodiscard]]).
  • Apelezi get() de două ori pe același std::future. După primul apel, future-ul devine invalid; pentru mai mulți cititori folosește std::shared_future.

Comenzi înrudite

  • std::future: Un rezultat care va fi disponibil în viitor (de la std::async sau std::promise); get() îl așteaptă și îl returnează.
  • std::promise: Capătul de scriere al unui std::future: un fir promite o valoare și o trimite cu set_value.
  • std::thread: Pornește o funcție pe un fir de execuție separat, care rulează în paralel cu restul programului.
  • std::ref: Împachetează o referință ca să poată fi transmisă prin funcții care copiază argumentele (thread, bind).