future는 비동기 방식으로 일을 처리할 때 유용하게 사용할 수 있다.
기존 쓰레드와 비교하여 보면 어렵지 않게 알 수 있다.
#include <future>
int64 Calculate()
{
int64 sum = 0;
for (int32 i = 0; i < 100'000; i++)
sum += i;
return sum;
}
int main()
{
// 동기(syncronous) 실행
//int64 sum = Calculate();
//cout << sum << endl;
// 이전방식
//thread t(Calculate);
// TODO
//t.join();
// std::future
{
// 1) deferred -> lazy evaluation 지연해서 실행
// 2) async -> 별도의 쓰레드를 만들어서 실행
// 3) deferred | async -> 둘 중 알아서 골라서 실행
std::future<int64> future = std::async(std::launch::async, Calculate);
// TODO
int64 sum = future.get(); // 결과물이 이제서야 필요하다!
}
}
std::async 함수로 future를 만들고 결과물이 필요할 때 future에서 가져온다.
잠시 비동기로 실행할 기능이 필요하다면 thread를 만들기보다 future를 쓰는게 작성, 관리가 유리하다.
그 외 기능들을 살펴보자.
// 시간을 주고 결과가 나왔는지 확인 할 수 있다.
std::future_status status = future.wait_for(1ms);
if (status == future_status::ready)
{
// TODO
}
class Knight
{
public:
int64 GetHP() { return 100; }
};
// 멤버함수 사용가능
Knight knight;
std::future<int64> future2 = std::async(std::launch::async, &Knight::GetHP, knight);
std::promise를 이용해 future를 만들 수도 있다. 이 방법을 이용해서 다른 쓰레드간 메모리를 공유할 수 있다. 전역변수등을 통한 메모리 공유 방식을 쓰지 않아도 되기 때문에 코드가 깔끔해진다.
void PromiseWorker(std::promise<string>&& promise)
{
promise.set_value("Secret message");
}
int main()
{
// std::promise
{
// 미래(std::future)에 결과물을 반환해줄꺼라 약속(std::promise) 해줘 (계약서?)
std::promise<string> promise;
std::future<string> future = promise.get_future();
thread t(PromiseWorker, std::move(promise));
string message = future.get();
cout << message << endl;
t.join();
}
}
std::packaged_task를 통해서 future를 만들 수도 있다. 다른 Promise와 다른 점은 함수의 리턴값과 future가 연결된다는 점이다.
void TaskWorker(std::packaged_task<int64(void)>&& task)
{
task();
}
int main()
{
// std::packaged_task
{
std::packaged_task<int64(void)> task(Calculate);
std::future<int64> future = task.get_future();
std::thread t(TaskWorker, std::move(task));
int64 sum = future.get();
cout << sum << endl;
t.join();
}
}
처음 방식과 다른 점은 처음 방식은 작업을 실행하는 전용 쓰레드를 만든 반면, packaged_task방법은 범용 쓰레드를 만들고 여러 작업을 해당 쓰레드에서 처리하게끔 할 수 있다는 점이다.
future는 일회성으로 필요한 비동기 작업을 mutex, condition_variable까지 쓰지 않고 간편하게 사용할 수 있다는 장점이 있다.
1) async
원하는 함수를 동기적으로 실행.
2) promise
공유 메모리를 promise를 통해 future로 받아줌.
3) packaged_task
함수의 실행 결과를 future로 받아줌.
참조 : [C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버 - 인프런 | 강의 (inflearn.com)
댓글 영역