ProgrammingLang/c++

[C++개발자되기]29. promise 와 future 그리고 async

jinkwon.kim 2022. 8. 11. 09:28
728x90
반응형

>>[C++ 관련 모든 글 보기]

개요 

    thread로 부터 수행 결과 값을 받는 방법을 알아 보겠습니다.

 

기본  원리

    future와 thread간 promise를 매개변수로 사용하여 비동기 처리에대한 값을 얻어 옵니다.

1. future

    미래에 어떤 값을 받고 자 할 따 사용.

2. promise

    future에 값을 넘겨주기 위해서 사용

Code

#include <iostream>
#include <thread>
#include <future>

void worker(std::promise<std::string> *p)
{
    p->set_value("some data");
}

int main()
{
	std::promise<std::string> p;

	std::future<std::string> data = p.get_future();
	
    std::thread t(worker, &p);
	
    // 없어도 아래 get에서 대기 합니다.
    data.wait();
	
    std::cout << "받은 데이터 : " <<  data.get() << std::endl;
	
    t.join();
	return 0;
}

무한 대기 회피 (wait_for)

    future에서 wait를 하면 무한 대기가 걸립니다. 이를 회피 하는 방법

future에서 제공하는 wait_for를 사용하여 무한 대기를 회피 합니다.

 

Code

#include <iostream>
#include <thread>
#include <future>

void worker(std::promise<std::string> *p)
{
    std::this_thread::sleep_for(std::chrono::seconds(3));
    p->set_value("some data");
}

int main()
{
   std::promise<std::string> p;
   std::future<std::string> data = p.get_future();

   std::thread t(worker, &p);
   
#if 0
    /*
    * 기본 코드, 무한 대기
    */
    data.wait();
#else
    while (true) {
        std::future_status status = data.wait_for(std::chrono::seconds(1));
        if (std::future_status::timeout == status) {
            //timeout이 경우 수행
            std::cerr << ">";
        } else if (std::future_status::ready == status) {
            //data에 값이 세팅되었을 경우 수행
            break;
        }
    }
#endif

   std::cout << "받은 데이터 : " <<  data.get() << std::endl;

   t.join();

   return 0;
}

유의 사항. 

std::future에서 get은 딱 1번 밖에사용을 못합니다. 아래와 같이 2번 사용할경우 

"error : std::future_error: No associated state" 가 발생 합니다.

std::cout << "받은 데이터 : " <<  data.get() << std::endl;
try {
    std::cout << "받은 데이터 : " <<  data.get() << std::endl;
} catch (std::exception &e) {
    std::cout << "error : " <<  e.what() << std::endl;
}

std::shared_future 란?

std::shared_future에서 get을 여러번 사용이 필요 할때 사용 합니다. 

Ex) 여러 Thread를 동시에 실행 시키고 싶을때 사용 가능 합니다. 

    각 Thread에서 future::get()를 통하여 대기 하게 한 후, main thread에서 promise를 setting하는 방식으로 사용 합니다.

 

std::async 란?

    thread를 만들어서 관리하고 싶지 않을때 사용 합니다.

앞서 promise  packaged_task 는 비동기적으로 실행을 하기 위해서는, 쓰레드를 명시적으로 생성해서 실행해야만 했습니다. 하지만 std::async 에 어떤 함수를 전달한다면, 아예 쓰레드를 알아서 만들어서 해당 함수를 비동기적으로 실행하고, 그 결과값을 future 에 전달합니다.

 

std::async는 std::task 클래스 기반으로 만들어진 클래스로 Thread를 만들 때 사용됩니다.

std::async는 std::thread와 달리 내부적으로 Thread Pool을 만들어 Thread를 관리하게 되며,

예외처리, 값 return 등.... std::thread보다 안정적이며 프로그래머가 사용하기 편리한 기능입니다.

std::async는 반환 값을 std::future로 받습니다.

 

 

Code -1 

핵심 코드

  std::async(std::launch::async, ()[] {})에서 std::launch::async는 바로 실행하는 선언입니다.

즉, std::async가 a로 넘어가는 순간 바로 실행됩니다.

 

반면 std::async(std::launch::deferred, ()[] {})에서 std::launch::deferred는 실행하지 않고 대기합니다.

그 후 .get() or .wait()을 만나면 실행하게 됩니다.

 

이 외에도 std::launch부분을 생략할 수도 있습니다.

#include <iostream>
#include <thread>
#include <future>

int main()
{
    std::shared_future<std::string> data = std::async(std::launch::async,[](){
        std::this_thread::sleep_for(std::chrono::seconds(3));
        return std::string("some data");
    });

   while (true) {
        std::future_status status = data.wait_for(std::chrono::seconds(1));

        if (std::future_status::timeout == status) {
            //timeout이 경우 수행
            std::cerr << ">";
        } else if (std::future_status::ready == status) {
            //data에 값이 세팅되었을 경우 수행
            break;
        }
    }

   std::cout << "받은 데이터 : " <<  data.get() << std::endl;
    try {
        std::cout << "받은 데이터 : " <<  data.get() << std::endl;
    } catch (std::exception &e) {
        std::cout << "error : " <<  e.what() << std::endl;
    }

   return 0;
}

Code - 2

std::future<void> f_thread = std::async(std::launch::async, lambda ())?

get하면 어떻게 되는가?

728x90
반응형

'ProgrammingLang > c++' 카테고리의 다른 글

[C++개발자되기] 32. STL Container 실무  (0) 2022.12.28
[C++개발자되기] 31. sscanf 정규 표현식  (1) 2022.10.25
[C++]Template  (0) 2022.06.21
[C++] The Best Parts of C++  (0) 2022.03.08
[C++] 언어의 철학  (0) 2022.01.25