O std::packaged_task é uma classe template da biblioteca padrão C++ que encapsula um objeto chamável, permitindo a obtenção assíncrona do resultado de sua execução. Internamente, ele gerencia doiss componentes principais: a tarefa encapsulada e um estado compartilhado.
A tarefa encapsulada refere-se ao objeto chamável, como um ponteiro para função, um functor ou uma expressão lambda. O estado compartilhado armazena o valor de retorno da tarefa ou qualquer exceção lançada durante sua execução, sendo acessível através de um objeto std::future.
O ciclo de vida do estado compartilhado persiste até que todos os objetos associados sejam destruídos. A seguir, um exemplo demonstrando seu uso básico, com uma função alternativa para cálculo de fatorial:
#include <iostream>
#include <future>
#include <thread>
int fatorial(int n) {
if (n <= 1) return 1;
int resultado = 1;
for (int i = 2; i <= n; ++i) {
resultado *= i;
}
return resultado;
}
int main() {
std::packaged_task<int(int)> tarefa(fatorial);
std::future<int> futuro = tarefa.get_future();
std::thread thread_exec(std::move(tarefa), 7);
int valor = futuro.get();
std::cout << "Fatorial de 7 é: " << valor << std::endl;
thread_exec.join();
return 0;
}
Construtores
- Construtor padrão:
packaged_task() noexcept;
Inicializa um objeto sem estado compartilhado válido. - Construtor por inicialização:
template<class Fn> explicit packaged_task(Fn&& fn);
Cria umpackaged_taskcom a tarefa fornecida. - Construtor com alocador:
template<class Fn, class Alloc> explicit packaged_task(allocator_arg_t, const Alloc& a, Fn&& fn);
Permite especificar um alocador personalizado para o estado compartilhado.
O construtor de cópia é desabilitado:
packaged_task(const packaged_task&) = delete;
O construtor de movimento é permitido:
packaged_task(packaged_task&& outro) noexcept;
Funções Membro
-
std::future<R> get_future();
Retorna um objetostd::futurevinculado ao estado compartilhado. -
bool valid() const noexcept;
Verifica se opackaged_taskpossui um estado compartilhado válido. Objetos criados pelo construtor padrão retornamfalse, a menos que tenham sido movidos ou torcados. ```std::future executar(std::packaged_task<int(int)&> tsk, int arg) { if (tsk.valid()) { auto f = tsk.get_future(); std::thread(std::move(tsk), arg).detach(); return f; } return {}; }
-
template<class... Args> void operator()(Args&&... args);
Invoca a tarefa encapsulada com os argumentos fornecidos. Se a execução for bem-suceidda, o valor de retorno é armazenado no estado compartilhado; caso contrário, a exceção é capturada. Em ambos os casos, o estado fica pronto para consulta viastd::future. -
template<class... Args> void make_ready_at_thread_exit(Args&&... args);
Executa a tarefa, mas marca o estado como pronto somente quando a thread corrente termina. Isso é útil para sincronização fina com o término da thread. -
void reset();
Recria o estado compartilhado, mantendo a tarefa original. Permite reutilizar o mesmopackaged_taskpara múltiplas execuções. ```#include #include #include
int dobro(int x) { return x * 2; }
int main() { std::packaged_task<int(int)> tarefa(dobro); auto futuro = tarefa.get_future();
std::thread(std::move(tarefa), 50).detach(); std::cout << "Dobro de 50: " << futuro.get() << std::endl; tarefa.reset(); futuro = tarefa.get_future(); std::thread(std::move(tarefa), 75).detach(); std::cout << "Dobro de 75: " << futuro.get() << std::endl; return 0;}
-
void swap(packaged_task& outro) noexcept;
Troca o conteúdo (incluindo o estado compartilhado e a tarefa) com outro objetopackaged_task.