3 분 소요

개요

C++20 부터 코루틴이 추가되었고, STL 에서는 코루틴 구현을 위해 다음의 유틸리티를 제공합니다.

항목 내용
coroutine_traits (C++20~) 코루틴 개체종속 타입promise_type을 외부에서 정의합니다.
coroutine_handle (C++20~) 코루틴을 재개하는 개체입니다.
noop_coroutine_promise (C++20~) (작성중)
noop_coroutine_handle (C++20~) std::coroutine_handle<std::noop_coroutine_promise>입니다.
noop_coroutine() (C++20~) (작성중)
suspend_always (C++20~) await_ready()에서 항상 false를 리턴하며, 대기합니다.
suspend_never (C++20~) await_ready()에서 항상 true를 리턴하며, 대기하지 않습니다.

coroutine_traits

co_await에서 코루틴 개체를 만드려면 명칭이 promise_type종속 타입이 있어야 한다고 언급했는데요,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
// 코루틴 개체
class MyCoroutine {  
public:
    struct MyPromise;
    using promise_type = MyPromise; // 명칭이 promise_type인 종속 타입이 있어야 합니다.
private:
    std::coroutine_handle<promise_type> m_Handler; // 코루틴 핸들
public:
    MyCoroutine(std::coroutine_handle<promise_type> handler) : m_Handler(handler) {}
    ~MyCoroutine() {
        if (m_Handler) {
            m_Handler.destroy(); 
        }
    }
    MyCoroutine(const MyCoroutine&) = delete;
    MyCoroutine(MyCoroutine&&) = delete;
    MyCoroutine& operator =(const MyCoroutine&) = delete;
    MyCoroutine& operator =(MyCoroutine&&) = delete;

    void Resume() const { .
        if (!m_Handler.done()) { 
            m_Handler.resume(); 
        }
    } 

    // Promise 개체
    struct MyPromise { 
        MyPromise() = default;
        ~MyPromise() = default;
        MyPromise(const MyPromise&) = delete;
        MyPromise(MyPromise&&) = delete;
        MyPromise& operator =(const MyPromise&) = delete;
        MyPromise& operator =(MyPromise&&) = delete;

        MyCoroutine get_return_object() { 
            return MyCoroutine{std::coroutine_handle<MyPromise>::from_promise(*this)};
        }
        auto initial_suspend() {return std::suspend_always{};} 
        auto final_suspend() noexcept {return std::suspend_always{};} 
        void unhandled_exception() {throw;} 
    };
};

// 코루틴 함수
MyCoroutine CoroutineFunc() {  
    std::cout << "CoroutineFunc #1" << std::endl;
    co_await std::suspend_always{}; 
    std::cout << "CoroutineFunc #2" << std::endl;
}

MyCoroutine obj = CoroutineFunc();
obj.Resume(); // 시작하자 마자 대기한 함수 실행
obj.Resume(); // co_await std::suspend_always{}; 이후 재개 

coroutine_traits코루틴 개체종속 타입promise_type을 외부에서 연결해 줄때 사용합니다.

  1. #1 : promise_type을 선언하지 않았습니다.
  2. #2 : MyCoroutine::MyPromisepromise_type으로 만듭니다. 이때 std 네임스페이스에 정의해야 합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
// 코루틴 개체
class MyCoroutine {  
public:
    struct MyPromise;     
    // using promise_type = MyPromise; // #1. promise_type을 선언하지 않았습니다.
private:
    std::coroutine_handle<MyPromise> m_Handler; // 코루틴 핸들
public:
    MyCoroutine(std::coroutine_handle<MyPromise> handler) : m_Handler(handler) {}
    ~MyCoroutine() {     
        if (m_Handler) {
            m_Handler.destroy();  
        }
    }
    MyCoroutine(const MyCoroutine&) = delete;
    MyCoroutine(MyCoroutine&&) = delete;
    MyCoroutine& operator =(const MyCoroutine&) = delete;
    MyCoroutine& operator =(MyCoroutine&&) = delete;

    void Resume() const { 
    if (!m_Handler.done()) { 
            m_Handler.resume(); 
        }
    } 
    
    // Promise 개체
    struct MyPromise { 
        MyPromise() = default;
        ~MyPromise() = default;
        MyPromise(const MyPromise&) = delete;
        MyPromise(MyPromise&&) = delete;
        MyPromise& operator =(const MyPromise&) = delete;
        MyPromise& operator =(MyPromise&&) = delete;

        MyCoroutine get_return_object() { 
            return MyCoroutine{std::coroutine_handle<MyPromise>::from_promise(*this)};
        }
        auto initial_suspend() {return std::suspend_always{};} 
        auto final_suspend() noexcept {return std::suspend_always{};} 
        void unhandled_exception() {throw;} 
    };
};  

namespace std {
    template<typename... ARGS>
    // #2. MyCoroutine::MyPromise를 promise_type으로 만듭니다.
    struct coroutine_traits<MyCoroutine, ARGS...> { 
        using promise_type = MyPromise;
    };
}

// 코루틴 함수
MyCoroutine CoroutineFunc() {  
    std::cout << "coroutine_traits #1" << std::endl;
    co_await std::suspend_always{}; 
    std::cout << "coroutine_traits #2" << std::endl;
} 

MyCoroutine obj = CoroutineFunc();
obj.Resume(); // 시작하자 마자 대기한 함수 실행
obj.Resume(); // co_await std::suspend_always{}; 이후 재개 

coroutine_handle

coroutine_handle코루틴을 재개하는 코루틴 핸들을 제공합니다. 자세한 사용 방법은 코루틴을 참고하시기 바랍니다.

항목 내용
done() (C++20~) 코루틴이 종료되었거나 예외가 발생하면 true를 리턴합니다.
operator bool (C++20~) 널검사를 합니다.
operator() (C++20~) resume()을 실행합니다.
resume() (C++20~) 코루틴을 재개합니다.
destroy() (C++20~) coroutine_handle을 소멸시킵니다.
promise() (C++20~) promise 개체에 접근합니다.
from_promise() (C++20~) promise 개체로부터 coroutine_handle을 생성합니다.
address() (C++20~) (작성중)
from_address() (C++20~) (작성중)

태그:

카테고리:

업데이트:

댓글남기기