std::packaged_task
callable object를 wrap하는 템플릿 클래스이다. 즉, 람다함수나 기존의 함수 혹은 callable object를 비동기적으로 부를 수 있게 해주는 wrapper라고 생각하면 된다. 예를 들어, 비동기 함수 처리에는 std::async를 사용하거나 future,promise 쌍으로 다른 thread에 할당시키는 방법이 있었다. 그런데 packaged_task를 사용하면 비동기적으로 호출할 수 있는 오브젝트를 만들었기 때문에 std::async 보다는 우리가 원하는 컨트롤 할 수 있을 뿐 아니라 쉽게 코드를 만들 수 있다.
Example Code
#include <iostream>
#include <chrono>
#include <future>
#include <thread>
int add1(int n)
{
return n + 1;
}
int main()
{
std::packaged_task<int(int)> add1Task(add1);
std::future<int> fut = add1Task.get_future(); // add1Task와 연결되는 future
add1Task(42);
std::cout << "ret : " << fut.get() << std::endl;
return 0;
}
그런데 future를 통해 value를 받았기 때문에 std::async를 사용한 것과 다를 바 없지 않나라고 생각할 수 있지만 차이가 존재한다.
차이점을 보면,
Example Code
auto fut1 = std::async(std::launch::async, add1, 42);
첫번째 차이점은 std::async 함수의 경우 해당 라인이 실행되는 순간 add1 함수가 비동기적으로 실행된다. 하지만 packaged_task 같은 경우 미리 Task를 만들어놓고 나중에 add1Task(42)를 실행시키는 순간 실행된다.
Example Code
#include <iostream>
#include <chrono>
#include <future>
#include <thread>
int add1(int n)
{
std::cout << std::this_thread::get_id() << std::endl;
return n + 1;
}
int main()
{
std::packaged_task<int(int)> add1Task(add1);
std::future<int> fut = add1Task.get_future(); // add1Task와 연결되는 future
std::cout << std::this_thread::get_id() << std::endl;
// packaged_task는 copy가 불가능하기 때문에 move 사용
std::jthread(std::move(add1Task), 42);
std::cout << "ret : " << fut.get() << std::endl;
return 0;
}
두번째 차이점은 std::async함수의 경우 사용자가 어떤 thread에 add1 함수를 할당시킬건지 지정할 수 없지만 packaged_task의 경우에는 이를 지정할 수 있다.
'C++ > Thread (Async)' 카테고리의 다른 글
[Async] std::async (0) | 2022.08.14 |
---|---|
[Async] shared_future (0) | 2022.08.11 |
[Async] Future, Promise (0) | 2022.08.10 |
[Async] 비동기 함수 Introduction (0) | 2022.08.10 |