C++20의 가장 간단한 코루틴 예제

코루틴은 C++20 표준에서 도입되었습니다. 안타깝게도 표준 라이브러리는 인터페이스만 제공하고 이벤트 루프, 대기자, 약속 등은 프로그래머에게 남겨두기 때문에 숙련된 개발자에게도 구현이 친숙하지 않습니다.

이것은 사람들이 학습을 시작하는 데 도움이 될 수 있는 최소한의 작업 예입니다.

#include <iostream>
#include <coroutine>
#include <thread>
#include <queue>
#include <functional>

std::queue<std::function<bool()>> task_queue;

struct sleep {
    sleep(int n) : delay{n} {}

    constexpr bool await_ready() const noexcept { return false; }

    void await_suspend(std::coroutine_handle<> h) const noexcept {
        auto start = std::chrono::steady_clock::now();
        task_queue.push([start, h, d = delay] {
            if (decltype(start)::clock::now() - start > d) {
                h.resume();
                return true;
            } else {
                return false;
            }
        });
    }

    void await_resume() const noexcept {}

    std::chrono::milliseconds delay;
};


struct Task {
    struct promise_type {
        promise_type() = default;
        Task get_return_object() { return {}; }
        std::suspend_never initial_suspend() { return {}; } 
        std::suspend_always final_suspend() noexcept { return {}; }
        void unhandled_exception() {}
    };
};

Task foo1() noexcept {
    std::cout << "1. hello from foo1" << std::endl;
    for (int i = 0; i < 10; ++i) {
        co_await sleep{10};
        std::cout << "2. hello from foo1" << std::endl;
    }
}

Task foo2() noexcept {
    std::cout << "1. hello from foo2" << std::endl;
    for (int i = 0; i < 10; ++i) {
        co_await sleep{10};
        std::cout << "2. hello from foo2" << std::endl;
    }
}

//call foo
int main() {
    foo1();
    foo2();

    while (!task_queue.empty()) {
        auto task = task_queue.front();
        if (!task()) {
            task_queue.push(task);
        }
        task_queue.pop();

        std::this_thread::sleep_for(std::chrono::milliseconds(10));
    }
}


여기에서 마법이 일어납니다co_await sleep{10};. 현재 코루틴이 일시 중단되고 awaiter는 핸들러를 사용하여 나중에 다시 시작합니다. 이 예에서 awaiter는 작업을 이벤트 루프로 연기하여 절전 시간이 만료되었는지 확인합니다.

다음은 작업 대기열이 있는 간단한 이벤트 루프입니다.

while (!task_queue.empty()) {
    auto task = task_queue.front();
    if (!task()) {
        task_queue.push(task);
    }
    task_queue.pop();
    std::this_thread::sleep_for(std::chrono::milliseconds(10));
}


코루틴에 대해 자세히 읽기 시작하기 전에 이 예제를 조금 살펴보십시오. 희망, 도움이 되었습니다!

좋은 웹페이지 즐겨찾기