std::jthread::jthread
De cppreference.com
<tbody>
</tbody>
jthread() noexcept; |
(1) | (desde C++20) |
jthread( jthread&& other ) noexcept; |
(2) | (desde C++20) |
template< class Function, class... Args > explicit jthread( Function&& f, Args&&... args ); |
(3) | (desde C++20) |
jthread( const jthread& ) = delete; |
(4) | (desde C++20) |
Construye un nuevo objeto jthread.
1) Crea un nuevo objeto
jthread que no representa un hilo.2) Constructor de movimiento. Construye el objeto
jthread para representar el hilo de ejecución que estaba representado por other. Después de esta llamada, other ya no representa un hilo.3) Crea un nuevo objeto
si la función f acepta un std::stop_token como su primer argumento; de lo contrario comienza a ejecutar
Excepto que las llamadas a
std::jthread y lo asocia con un hilo de ejecución. El nuevo hilo de ejecución comienza a ejecutar std::invoke(decay_copy(std::forward<Function>(f)),
get_stop_token(),
decay_copy(std::forward<Args>(args))...);
std::invoke(decay_copy(std::forward<Function>(f)),
decay_copy(std::forward<Args>(args))...);
En cualquier caso, decay_copy se define como
template <class T>
std::decay_t<T> decay_copy(T&& v) { return std::forward<T>(v); }
decay_copy se evalúan en el contexto del llamante, de modo que cualquier excepción lanzada durante la evaluación y copia/movimiento de los argumentos se lanza en el hilo actual, sin iniciar el nuevo hilo. La finalización de la invocación del constructor constructor se sincroniza con (como se define en std::memory_order) el inicio de la invocación de la copia de f en el nuevo hilo de ejecución.
Este constructor no participa en la resolución de sobrecarga si
std::remove_cvref_t<Function> es el mismo tipo que std::jthread.4) El constructor de copia está eliminado; los hilos no son copiables. No hay dos objetos
std::jthread que puedan representar el mismo hilo de ejecución.Parámetros
| other | - | Otro objeto jthread con el cual construir este jthread.
|
| f | - | Objeto invocable (Callable) a ejecutar en el nuevo hilo. |
| args... | - | Argumentos a pasar a la nueva función. |
Poscondiciones
1) get_id() es igual a std::jthread::id() (es decir, joinable es
false) y get_stop_source().stop_possible() es false.2)
other.get_id() es igual a std::jthread::id() y get_id() devuelve el valor de other.get_id() antes del inicio de la construcción.3) get_id() no es igual a std::jthread::id() (es decir, joinable es
true), y get_stop_source().stop_possible() es true.Excepciones
3) std::system_error si el hilo no se pudo iniciar. La excepción puede representar la condición de error
std::errc::resource_unavailable_try_again u otra condición de error específica de la implementación.Notas
Los argumentos de la función del hilo se mueven o se copian por valor. Si es necesario pasar un argumento por referencia a la función del hilo, debe ajustarse (por ejemplo, con std::ref o std::cref).
Se ignora cualquier valor de retorno de la función. Si la función lanza una excepción, se llama a std::terminate. Para pasar valores de retorno o excepciones al hilo llamante, se pueden usar std::promise o std::async.
Ejemplo
Ejecuta este código
#include <iostream>
#include <utility>
#include <thread>
#include <chrono>
using namespace std::literals;
void f1(int n)
{
for (int i = 0; i < 5; ++i) {
std::cout << "Hilo 1 ejecutando\n";
++n;
std::this_thread::sleep_for(10ms);
}
}
void f2(int& n)
{
for (int i = 0; i < 5; ++i) {
std::cout << "Hilo 2 ejecutando\n";
++n;
std::this_thread::sleep_for(10ms);
}
}
class foo
{
public:
void bar()
{
for (int i = 0; i < 5; ++i) {
std::cout << "Hilo 3 ejecutando\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 << "Hilo 4 ejecutando\n";
++n;
std::this_thread::sleep_for(10ms);
}
}
int n = 0;
};
int main()
{
int n = 0;
foo f;
baz b;
std::jthread t0; // t0 no es un hilo
std::jthread t1(f1, n + 1); // pasar por valor
std::jthread t2a(f2, std::ref(n)); // pasar por referencia
std::jthread t2b(std::move(t2a)); // t2b ahora ejecuta f2(). t2a ya no es un hilo
std::jthread t3(&foo::bar, &f); // t3 ejecuta foo::bar() en el objeto f
std::jthread t4(b); // t4 ejecuta baz::operator() en una copia del objeto b
t1.join();
t2b.join();
t3.join();
std::cout << "Valor final de n es " << n << '\n';
std::cout << "Valor final de f.n (foo::n) es " << f.n << '\n';
std::cout << "Valor final de b.n (baz::n) es " << b.n << '\n';
// t4 se une durante la destrucción
}
Posible salida:
Hilo 2 ejecutando
Hilo 1 ejecutando
Hilo 4 ejecutando
Hilo 3 ejecutando
Hilo 3 ejecutando
Hilo 4 ejecutando
Hilo 2 ejecutando
Hilo 1 ejecutando
Hilo 3 ejecutando
Hilo 1 ejecutando
Hilo 4 ejecutando
Hilo 2 ejecutando
Hilo 3 ejecutando
Hilo 1 ejecutando
Hilo 4 ejecutando
Hilo 2 ejecutando
Hilo 3 ejecutando
Hilo 1 ejecutando
Hilo 4 ejecutando
Hilo 2 ejecutando
Valor final de n es 5
Valor final de f.n (foo::n) es 5
Valor final de b.n (bar::n) es 0
Véase también
| Construye un nuevo objeto hilo (función miembro pública de std::thread)
| |
Documentación de C para thrd_create
| |