Úvod do std::packaged_task v C++
V moderním C++ (od verze C++11) byla do standardní knihovny přidána řada nástrojů pro práci s vícevláknovým programováním a asynchronním zpracováním. Jedním z těchto nástrojů je třída std::packaged_task, která umožňuje snadné propojení mezi funkcemi a jejich výsledky pomocí objektů std::future. Tento článek se zaměřuje na vysvětlení, jak std::packaged_task funguje, a ukazuje jeho praktické využití.
Co je std::packaged_task?
std::packaged_task je šablona třídy, která zapouzdřuje funkci nebo volatelný objekt (callable) a umožňuje jeho asynchronní spuštění. Výsledek této funkce je propojen s objektem std::future, což umožňuje získat výsledek výpočtu v jiném vlákně nebo později v programu.
Deklarace třídy vypadá následovně:
template <class R, class... Args>
class std::packaged_task<R(Args...)>;
- R: Návratový typ funkce.
- Args…: Parametry funkce.
Jak std::packaged_task funguje?
Hlavní myšlenkou je, že std::packaged_task přijme funkci (nebo jiný volatelný objekt) a propojí ji s objektem std::future. Když je funkce spuštěna, výsledek je uložen a může být získán prostřednictvím std::future.
Příklad použití
Podívejme se na jednoduchý příklad, jak použít std::packaged_task:
#include <iostream>
#include <future>
#include <thread>
#include <chrono>
// Funkce, která provádí nějaký výpočet
int dlouhy_vypocet(int x) {
std::this_thread::sleep_for(std::chrono::seconds(2)); // Simulace zpoždění
return x * x;
}
int main() {
// Vytvoření std::packaged_task s funkcí
std::packaged_task<int(int)> task(dlouhy_vypocet);
// Získání std::future pro výsledek
std::future<int> result = task.get_future();
// Spuštění úkolu v samostatném vlákně
std::thread t(std::move(task), 5);
// Mezitím můžeme provádět jiné operace
std::cout << "Výpočet probíhá...\n";
// Získání výsledku
std::cout << "Výsledek: " << result.get() << "\n";
// Ukončení vlákna
t.join();
return 0;
}
Vysvětlení příkladu
- Vytvoření
std::packaged_task: Objekttaskzapouzdřuje funkcidlouhy_vypocet. - Propojení s
std::future: Pomocítask.get_future()získáme objektstd::future, který bude obsahovat výsledek výpočtu. - Spuštění úkolu: Úkol je spuštěn v samostatném vlákně pomocí
std::thread. - Získání výsledku: Metoda
result.get()blokuje hlavní vlákno, dokud není výpočet dokončen, a poté vrátí výsledek.
Kdy použít std::packaged_task?
std::packaged_task je užitečný v situacích, kdy chcete explicitně řídit spuštění funkce a propojit její výsledek s objektem std::future. Je vhodný pro scénáře, kde potřebujete:
- Asynchronní zpracování s možností získání výsledku.
- Přesné řízení spuštění úkolu (např. v kombinaci s vlákny nebo frontami úkolů).
Závěr
std::packaged_task je výkonný nástroj pro práci s asynchronním programováním v C++. Umožňuje snadné propojení mezi funkcemi a jejich výsledky pomocí std::future. Přestože je jeho použití méně časté než například std::async, poskytuje větší flexibilitu a kontrolu nad spuštěním úkolů. Pokud potřebujete explicitní řízení nad asynchronními operacemi, std::packaged_task je skvělou volbou.