본문 바로가기
Language/C++

[C++] std::promise, std::future

by 어발 2024. 12. 4.
std::promise<>
 - 스레드 사이에서 "값 또는 예외를 공유" 할 수 있는 템플릿
 - <future> 헤더
 - promise 통해서 전달된 데이터는 std::future<>를 통해서 얻을 수 있다.
 - set_value()는 한번만 사용할 수 있다.
 - future()는 한번만 꺼낼 수 있다.

std::future<> 멤버 함수
 - get() : 결과를 꺼내기. (한번만 사용 가능)
 - wait() : 결과값이 준비될 때까지 대기
 - wait_for() : 주어진 시간 만큼 대기
 - wait_until() : 주어진 시간까지 대기
   -> wait_for/wait_until 함수의 반환값
      - std::future_status::ready : 결과값이 준비 됨.
      - std::future_status::timeout : 시간초과
      - std::future_status::defferred : 연산을 수행할 함수가 아직 시작 안됨. async()함수에서 사용.
 - share() : shared_future 얻기
 - valid() : 유효성 확인

1. std::promise & std::future 기본예제

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

using namespace std::literals;

void add(std::promise<int>&& p, int a, int b) {
	int s = a + b;
    std::this_thread::sleep_for(1s);
    p.set_value(s);
    /* NOTE: 스레드가 끝날때 set_value를 수행하는 함수도 있음
    	p.set_value_at_thread_exit(s); */
}

int main() {
	std::promise<int> pm;
    std::future<int> ft = pm.get_future();
    std::thread t(add, std::move(pm), 10, 20);
    
    int ret = ft.get();  // blocking : thread가 끝날때까지
    std::cout << ret << std::endl;
    t.join();
}

 

2. std::promise & std::future로 예외 전달하기

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

void divide(std::promise<int>& p, int a, int b) {
	try {
    	if (b == 0)
        	throw std::runtime_error("divide by zero");
            
		p.set_value(a/b);
	}
    catch(...) {
		p.set_exception(std::current_exception());
        /* NOTE: 스레드가 종료했을때 보내는 함수도 있다.
        	p.set_exception_at_thread_exit(std::current_exception()); */
    }
}

int main() {
	std::promise<int> pm;
    std::future<int> ft = pm.get_future();
    
    std::thread t(divide, std::ref(pm), 10, 0);
    
    try {
		int ret = ft.get();
    }
    catch(std::exception &e) {
		std::cout << e.what() << std::endl;
    }
    
    t.join();
}

3. std::promise로 void형 전달하기

#include <iostream>
#include <thread>
#include <future>
#include <vector>
#include <numeric>

int main() {
	std::vector<int> v1 = {1,2,3,4,5,6,7,8,9,10};
    std::vecor<int> v2(10);
    
    std::promise<void> pm1;
    std::future<void> ft1 = pm1.get_futre();
    
    std::promise<int> pm2;
    std::future<int> ft2 = pm2.get_future();
    
    std::thread t([&]{
    	std::partial_sum(v1.begin(), v1.end(), v2.begin());	// 부분합 구하기
        
        pm1.set_value(); // 1번째 연산이 종료되었음을 알린다.
        
        int s = std::accumulate(v2.begin(), v2.end(), 0);	// 구간의 합 구하기
        
        pm2.set_value(s);	// 2번째 연산이 종료되었음을 알린다.
    });
    
    ft1.get();
    
    for (auto n : v2)
    	std:;cout << n << ",";
    
    int ret = ft2.get();
    std::cout << ret << std::endl;
    
    t.join();
}

4. std::future의 wait 예제

#include <iostream>
#include <thread>
#include <future>
#include <chrono>
using namespace std::literals;

void add(std::promise<int>&& p, int a, int b) {
	std::this_thread::sleep_for(3s);
    p.set_value(a+b);
}

int main() {
	std::promise<int> pm;
    std::future<int> ft = pm.get_futre();
    
    std::thread t(add, std::move(pm), 10, 20);
    
    std::future_status ret = ft.wait_for(2s);
    
    if (ret == std::future_status::ready)
    	std::cout << "ready!" << std::endl;
    else if (ret == std::future_status::timeout)
        std::cout << "timeout!" << std::endl;
    else
    	std::cout << "deffered!" << std::endl;
        
    t.join();
}

 

5. std::shared_future 예제

#include <iostream>
#include <thread>
#include <future>
#include <chrono>
using namespace std::literals;

void add(std::promise<int>&& p, int a, int b) {
	std::this_thread::sleep_for(1s);
    p.set_value(a + b);
}

void consume(std::sharead_future<int> sf) {
	sf.get();
    std::cout << "finish foo" << std::endl;
}

int main() {
	std::promise<int> pm;
    std::future<int> ft = pm.get_future();
    // std::future<int> ft2 = ft; //error
    std::shared_future<int> sft = ft.share();
    
    std::thread t(add, std::move(pm), 10, 20);
    
    std::thread t1(consume, sft);
    std::thread t2(consume, sft);
    
    t.join();
    t1.join();
    t2.join();
}
728x90

'Language > C++' 카테고리의 다른 글

[C++] std::async  (0) 2024.12.20
[C++] std::packaged_task  (0) 2024.12.18
[C++] std::ref, std::reference_wrapper  (1) 2023.09.01
[C++] std::thread  (0) 2023.09.01
[C++] std::chrono  (0) 2023.09.01

댓글