tgparkk / notepad

1 stars 0 forks source link

promise 와 future #3

Open tgparkk opened 5 months ago

tgparkk commented 5 months ago

std::thread 로 스레드를 만들면 그 스레드가 종료된 후에는 최종 결과를 받기 힘들다. 예외나 여러 가지 에러를 처리하는 데도 문제가 발생한다. (스레드가 던진 익셉션을 그 스레드가 받지 않으면 c++ 런타임은 std::terminate() 를 호출해서 app 전체를 종료시킨다.)

이때 future를 사용하면 스레드의 실행 결과를 쉽게 받아올 수 있을 뿐만 아니라 익셉션을 다른 스레드로 전달할 수 있다. (물론 익셉션이 발생한 스레드에서 벗어나지 않도록 항상 같은 스레드 안에서 처리하는 것이 바람짐)

스레드의 실행 결과를 promise에 담으면 future로 그 값을 가져올 수 있다. 채널에 비유하면 promise는 입력 포트고, future는 출력 포트인 셈이다.

A 스레드와 B 스레드가 있을 때 A 스레드가 어떤 계산을 B 스레드로 처리하기 위해 std::promise를 생성해서 B 스레드를 구동할 떄 이 promise를 인수로 전달한다. (이때 promise는 복제될 수 없고, 이동만 가능하다.) B 스레드는 이 promise 에 값을 저장한다. A 스레드는 promise를 B 스레드로 이동시키기 전에 생성된 promise 에 get_future() 를 호출한다.

void DoWork(std::promise<int> thePromise)
{
  // 원하는 작업 수행
  // 최종 결과를 promise 에 저장
  thePromise.set_value(42);
}

int main()
{
  // 스레드에 전달할 promise를 생성
  std::promise<int> myPromise;
  // 이 promise에 대한 future를 가져온다.
  auto theFuture = myPromise.get_future();
  // 스레드를 생성하고 앞에서 만든 promise를 인수로 전달한다.
  std::thread theThread { DoWork, std::move(myPromise) };

  // 원하는 작업 수행
  // ~~

  // 최종 결과를 가져온다.
  int result = threFuture.get();
  std::cout << result << std::endl;

  // 스레드 join
  theThread.join();

}

-- 위 코드는 단순 예제이며, 스레드를 생성후에 계산한뒤 future 에 대해 get() 을 호출했다. 그러면 최종 결과가 나올 때까지 블록된다. 하지만 실전에서는 future 에 최종 결과가 나왔는지 주기적으로 검사하도록 구현하거나(wait_for() ) , 또는 조건 변수와 같은 동기화 기법을 사용하도록 구현한다.