Spec-Zone.ru › C++

std::jthread::jthread

jthread() noexcept;
(1) (с C++20)
jthread( jthread&& other ) noexcept;
(2) (с C++20)
template< class Function, class... Args > 
explicit jthread( Function&& 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<Function>(f)), get_stop_token(),
            decay-copy(std::forward<Args>(args))...)
(до C++23)

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

(с C++23)

если выражение выше корректно, в противном случае начинает выполнение:

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

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

(с C++23)
Вызовы decay-copy оцениваются(до C++23)Значения, производимые auto , материализуются(с C++23) в текущем потоке, так что любые исключения, сгенерированные во время оценки и копирования/перемещения аргументов, генерируются в текущем потоке без запуска нового потока. Программа некорректна, если любое создание или вызов std::invoke некорректны.
Этот конструктор не участвует в разрешении перегрузки, если std::remove_cvref_t<Function> имеет тот же тип, что и std::jthread.
Завершение вызова конструктора синхронизируется с (как определено в std::memory_order) началом вызова копии f в новом потоке выполнения.
4) Конструктор копирования удалён; потоки не копируются. Ни два объекта std::jthread не могут представлять один и тот же поток выполнения.

Параметры

other - другой объект std::jthread для создания этого объекта std::jthread
f - объект Callable для выполнения в новом потоке
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 (bar::n) is 0

См. также

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

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

Spec-Zone.ru

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