std::jthread în C++

Fir de execuție care face join automat la distrugere și poate fi rugat să se oprească (stop_token).

Sintaxă
#include <thread>
std::jthread t(functie, argumente...);
std::jthread t([](std::stop_token st) { while (!st.stop_requested()) { ... } });
bool request_stop() noexcept;

Ce face std::jthread

std::jthread („joining thread”) se folosește la fel ca std::thread, cu două îmbunătățiri. Prima: destructorul lui apelează singur join(), deci nu mai riști std::terminate dacă uiți.

A doua: suportă oprirea cooperativă. Dacă funcția primește ca prim parametru un std::stop_token, poate verifica periodic st.stop_requested(). Din afară, t.request_stop() cere oprirea; destructorul o cere automat înainte de join.

Oprirea nu este forțată: firul trebuie să verifice tokenul și să se încheie singur. Este alegerea recomandată pentru fire noi în C++20.

Parametri

Parametru Descriere
functie Funcția rulată; opțional primește un std::stop_token ca prim parametru.
argumente Argumentele, copiate în firul nou.

Ce returnează

Un obiect fir de execuție. request_stop() returnează true dacă cererea de oprire a fost făcută acum.

Exemple

Exemplul 1: join automat la ieșirea din bloc

#include <print>
#include <thread>

int main() {
    int rezultat = 0;
    {
        std::jthread t([&rezultat] {
            for (int i = 1; i <= 100; ++i) rezultat += i;
        });
    }   // aici t face join automat
    std::println("Suma 1..100 = {}", rezultat);
}

Rezultat

Suma 1..100 = 5050

Exemplul 2: Oprire cerută din afară

Firul lucrează până i se cere oprirea. Numărul de pași făcuți diferă de la o rulare la alta, așa că exemplul afișează doar dacă firul s-a oprit corect.

#include <atomic>
#include <chrono>
#include <print>
#include <stop_token>
#include <thread>

int main() {
    std::atomic<bool> opritCorect{false};

    std::jthread lucrator([&opritCorect](std::stop_token st) {
        while (!st.stop_requested()) {
            std::this_thread::sleep_for(std::chrono::milliseconds(10));   // o bucată de lucru
        }
        opritCorect = true;
    });

    std::this_thread::sleep_for(std::chrono::milliseconds(50));
    lucrator.request_stop();
    lucrator.join();
    std::println("Firul s-a oprit singur: {}", opritCorect.load());
}

Rezultat

Firul s-a oprit singur: true

Greșeli frecvente

  • Te aștepți ca request_stop() să oprească firul imediat. Este doar o cerere; dacă funcția nu verifică stop_requested(), firul rulează până la capăt, iar destructorul așteaptă după el.

Comenzi înrudite

  • std::thread: Pornește o funcție pe un fir de execuție separat, care rulează în paralel cu restul programului.
  • std::this_thread::sleep_for: Oprește firul de execuție curent pentru (cel puțin) durata dată.
  • std::condition_variable: Permite unui fir să aștepte, fără să consume procesor, până când alt fir îl anunță că o condiție s-a îndeplinit.
  • std::atomic: Variabilă care poate fi citită și modificată sigur de mai multe fire, fără mutex.