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.
std::jthread, который не представляет поток выполнения.std::jthread, представляющий поток выполнения, который представлял other. После этого вызова other больше не представляет поток выполнения.std::jthread и связывает его с потоком выполнения. Новый поток выполнения начинает выполнять:
std::invoke(decay-copy(std::forward<F>(f)),get_stop_token(), | (до C++23) |
|
| (начиная с C++23) |
если приведённое выше выражение корректно, иначе начинает выполнять:
std::invoke(decay-copy(std::forward<F>(f)),. | (до C++23) |
|
| (начиная с C++23) |
decay-copy вычисляются(до C++23)Значения, полученные с помощью auto, материализуются(начиная с C++23) в текущем потоке, поэтому любые исключения, выброшенные во время вычисления и копирования/перемещения аргументов, выбрасываются в текущем потоке без запуска нового потока.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 в новом потоке выполнения.std::jthread не могут представлять один и тот же поток выполнения.Параметры
| other | - | другой объект std::jthread, с помощью которого создаётся этот объект std::jthread |
| f | - | вызываемый объект, который будет выполняться в новом потоке |
| args | - | аргументы, передаваемые новой функции |
Постусловия
get_id() равен std::jthread::id() (то есть joinable() возвращает false), а get_stop_source().stop_possible() равен false.other.get_id() равен std::jthread::id(), а get_id() возвращает значение other.get_id() до начала выполнения конструктора.get_id() не равен std::jthread::id() (то есть joinable() возвращает true), а get_stop_source().stop_possible() равен true.Исключения
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] |
- Возможность конструирования перемещением уже косвенно требуется
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