Spec-Zone.ru › C++

std::jthread::jthread

jthread() noexcept;
(1) (начиная с C++20)
jthread( jthread&& other ) noexcept;
(2) (начиная с C++20)
template< class F, class... Args > 
explicit jthread( F&& f, Args&&... args );
(3) (начиная с C++20)
jthread( const jthread& ) = delete;
(4) (начиная с C++20)

Создаёт новый объект std::jthread.

1) Создаёт новый объект std::jthread, который не представляет поток выполнения.
2) Конструктор перемещения. Создаёт объект std::jthread, представляющий поток выполнения, который представлял other. После этого вызова other больше не представляет поток выполнения.
3) Создаёт новый объект std::jthread и связывает его с потоком выполнения.

Новый поток выполнения начинает выполнять:

std::invoke(decay-copy(std::forward<F>(f)),get_stop_token(),
            decay-copy(std::forward<Args>(args))...)
(до C++23)

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

(начиная с C++23)

если приведённое выше выражение корректно, иначе начинает выполнять:

std::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)
Вызовы decay-copy вычисляются(до C++23)Значения, полученные с помощью auto, материализуются(начиная с C++23) в текущем потоке, поэтому любые исключения, выброшенные во время вычисления и копирования/перемещения аргументов, выбрасываются в текущем потоке без запуска нового потока.
Эти перегрузки участвуют в разрешении перегрузки только в том случае, если std::remove_cvref_t<F> не является тем же типом, что и std::jthread.
Если любое из следующих условий false, программа некорректна:
  • std::is_constructible_v<std::decay_t<F>, F>
  • (std::is_constructible_v<std::decay_t<Args>, Args> && ...)
  • std::is_invocable_v<std::decay_t<F>, std::decay_t<Args>...> ||std::is_invocable_v<std::decay_t<F>, std::stop_token, std::decay_t<Args>...>
Завершение вызова конструктора синхронизируется с началом вызова копии f в новом потоке выполнения.
4) Конструктор копирования удалён; потоки нельзя копировать. Никакие два объекта std::jthread не могут представлять один и тот же поток выполнения.

Параметры

other - другой объект std::jthread, с помощью которого создаётся этот объект std::jthread
f - вызываемый объект, который будет выполняться в новом потоке
args - аргументы, передаваемые новой функции

Постусловия

1) get_id() равен std::jthread::id() (то есть joinable() возвращает false), а get_stop_source().stop_possible() равен false.
2) other.get_id() равен std::jthread::id(), а get_id() возвращает значение other.get_id() до начала выполнения конструктора.
3) get_id() не равен std::jthread::id() (то есть joinable() возвращает true), а get_stop_source().stop_possible() равен true.

Исключения

3) std::system_error, если поток не удалось запустить. Исключение может представлять состояние ошибки std::errc::resource_unavailable_try_again или другое зависящее от реализации состояние ошибки.

Примечания

Аргументы функции потока перемещаются или копируются по значению. Если функции потока необходимо передать аргумент-ссылку, его нужно обернуть (например, с помощью std::ref или std::cref).

Любое возвращаемое функцией значение игнорируется. Если функция выбрасывает исключение, вызывается std::terminate. Для передачи возвращаемых значений или исключений обратно в вызывающий поток можно использовать std::promise или std::async.

Пример

#include <chrono>
#include <iostream>
#include <thread>
#include <utility>

using namespace std::literals;

void f1(int n)
{
    for (int i = 0; i < 5; ++i)
    {
        std::cout << "Thread 1 executing\n";
        ++n;
        std::this_thread::sleep_for(10ms);
    }
}
 
void f2(int& n)
{
    for (int i = 0; i < 5; ++i)
    {
        std::cout << "Thread 2 executing\n";
        ++n;
        std::this_thread::sleep_for(10ms);
    }
}
 
class foo
{
public:
    void bar()
    {
        for (int i = 0; i < 5; ++i)
        {
            std::cout << "Thread 3 executing\n";
            ++n;
            std::this_thread::sleep_for(10ms);
        }
    }
    int n = 0;
};

class baz
{
public:
    void operator()()
    {
        for (int i = 0; i < 5; ++i)
        {
            std::cout << "Thread 4 executing\n";
            ++n;
            std::this_thread::sleep_for(10ms);
        }
    }
    int n = 0;
};
 
int main()
{
    int n = 0;
    foo f;
    baz b;
    std::jthread t0; // t0 is not a thread
    std::jthread t1(f1, n + 1); // pass by value
    std::jthread t2a(f2, std::ref(n)); // pass by reference
    std::jthread t2b(std::move(t2a)); // t2b is now running f2(). t2a is no longer a thread
    std::jthread t3(&foo::bar, &f); // t3 runs foo::bar() on object f
    std::jthread t4(b); // t4 runs baz::operator() on a copy of object b
    t1.join();
    t2b.join();
    t3.join();
    std::cout << "Final value of n is " << n << '\n';
    std::cout << "Final value of f.n (foo::n) is " << f.n << '\n';
    std::cout << "Final value of b.n (baz::n) is " << b.n << '\n';
    // t4 joins on destruction
}

Возможный вывод:

Thread 2 executing
Thread 1 executing
Thread 4 executing
Thread 3 executing
Thread 3 executing
Thread 4 executing
Thread 2 executing
Thread 1 executing
Thread 3 executing
Thread 1 executing
Thread 4 executing
Thread 2 executing
Thread 3 executing
Thread 1 executing
Thread 4 executing
Thread 2 executing
Thread 3 executing
Thread 1 executing
Thread 4 executing
Thread 2 executing
Final value of n is 5
Final value of f.n (foo::n) is 5
Final value of b.n (baz::n) is 0

Отчёты об ошибках

Следующие отчёты об ошибках, изменяющие поведение, были ретроактивно применены к ранее опубликованным стандартам C++.

Отчёт об ошибке Применён к Опубликованное поведение Корректное поведение
LWG 3476 C++20 перегрузка (3) непосредственно требовала, чтобы (декадированные типы)
F и типы аргументов поддерживали конструирование перемещением
эти требования
удалены[1]
  1. Возможность конструирования перемещением уже косвенно требуется std::is_constructible_v.

См. также

(конструктор)
создаёт новый объект thread
(открытая функция-член класса std::thread)
Документация C для thrd_create

© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/thread/jthread/jthread

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API