Future
계속 사용해야 하는 Event는 CV를 활용하면 되지만
단발성 Event인 경우는 CV를 사용하기엔 너무 과하다
thread를 만들고 cv변수를 만들고
해당 변수의 멀티스레드에서 활용되면 lock도 관리해주어야 한다
따라서
간단하게 사용하기 위해 Future가 도입되었다
Future 예시
#include <future>
int64 Calculate()
{
int64 sum = 0;
for (int32 i = 0; i < 100'000; i++)
{
sum += i;
}
return sum;
}
int main()
{
//// 동기(synchronous) 실행
//int sum = Calculate();
//cout << sum << endl;
// std::future
{
std::future<int64> future1 = std::async(std::launch::deferred, Calculate);
std::future<int64> future2 = std::async(std::launch::async, Calculate);
int64 sum1 = future1.get();
int64 sum2 = future2.get();
}
}
위의 코드에서 async의 첫번째 인자에
deferred는 스레드를 활용하는 것은 아니고 그냥 지연실행을 시킨다
async는 스레드 하나를 생성해 해당 스레드에게 실행을 시킨다
객체 대상의 Future
전역, static 말고도 객체 대상의 멤버 함수도 아래와 같이 실행시킬 수 있다
class Knight
{
public:
int64 GetHp() { return 100; }
};
Knight knight;
std::future<int64> future = std::async(std::launch::async, &Knight::GetHp, knight);
현업에서의 Future
게임의 데이터 파일을 로딩하는 경우
너무 많은 시간이 걸리기 때문에
future를 통해 단발적인 멀티스레드 작업을 진행하는 경우도 있다
Future의 wait, wait_for, get
wait는 무한정 기다리는 것이기에 get이랑 큰 차이가 없다
그래서 wait_for, get 만 기억을 하면 되는데
wait_for은 특정 시간 동안 기다리는 것으로 현재 진행 상태를 확인 가능하다
get은 그 결과를 받아오는 것으로
만약, 아직 결과를 받아올 수 없는 진행상태라면
해당 작업이 끝날 때까지 기다렸다가 결과를 받아온다
std::future<int64> future = std::async(std::launch::async, Calculate);
std::future_status status = future.wait_for(1ms);
if (status == future_status::ready)
{
// TODO
}
//future.wait();
int64 sum = future.get();
Future 만드는 다른 방법
1) async
위에서 사용한 async 방식은
원하는 함수를 비동기적으로 실행을 했었다
2) promise
결과물을 promise를 통해 future로 받아준다
future를 이용해 단발성 Event를 만들 때,
만약 스레드 간 통신을 하며
전역변수를 만들어야 하는데 이러한 경우에는
굳이 전역변수를 만들 필요없이 promise를 이용하면 된다
참고로
promise는 오른값으로 move가 되면서 소유권을 잃게 되고
future.get()은 한번 호출하면 소유권을 잃게 된다
3) packaged_task
원하는 함수의 실행 결과를 packaged_task를 통해 future로 받아준다
특정 함수를 진행하는 단발성 스레드를 만들어 처리하는 기존 방식들과는 달리
스레드를 만든 다음에 task를 여러 개 건네줄 수도 있다
#include <future>
int64 Calculate()
{
int64 sum = 0;
for (int32 i = 0; i < 100'000; i++)
{
sum += i;
}
return sum;
}
void PromiseWorker(std::promise<string>&& promise)
{
promise.set_value("Secret Message");
}
void TaskWorker(std::packaged_task<int64(void)> && task)
{
task();
}
int main()
{
// std::promise
{
std::promise<string> promise;
std::future<string> future = promise.get_future();
thread t(PromiseWorker, std::move(promise));
string messeage = future.get();
t.join();
}
// 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();
t.join();
}
}
'게임 서버' 카테고리의 다른 글
[게임서버 섹션2 Note] CPU 파이프라인 (0) | 2024.12.30 |
---|---|
[게임서버 섹션2 Note] 캐시 (0) | 2024.12.30 |
[게임서버 섹션2 Note] Condition Variable (0) | 2024.12.30 |
[게임서버 섹션2 Note] Event (0) | 2024.12.30 |
[게임서버 섹션2 Note] Sleep (0) | 2024.12.29 |