상세 컨텐츠

본문 제목

Future

똑똑한 개발/C++ 게임개발

by 성댕쓰 2021. 8. 7. 18:41

본문

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)

'똑똑한 개발 > C++ 게임개발' 카테고리의 다른 글

CPU 파이프라인  (0) 2021.08.09
캐시  (0) 2021.08.07
Condition variable  (0) 2021.08.07
Event  (0) 2021.08.07
Sleep  (0) 2021.08.06

관련글 더보기

댓글 영역