Waitable QTimer with C++20 coroutines

Found an example of overriding co_await operator and was able to implement my own version:

#include <chrono>
#include <coroutine>

//QTimer::singleShot accepts only milliseconds and a template version of the operator does not compile.
auto operator co_await(std::chrono::milliseconds d)
{
    class awaiter
    {
        std::chrono::milliseconds m_d;

    public:

        explicit awaiter(std::chrono::milliseconds d) : m_d(d) {}

        bool await_ready() const noexcept
        {
            return m_d <= std::chrono::milliseconds(0);
        }

        void await_suspend(std::coroutine_handle<> h) const noexcept
        {
            QTimer::singleShot(m_d, [h]() -> void
            {
                h.resume();
            });
        }

        void await_resume() const noexcept {}
    };

    return awaiter { d };
}

For those who did not work with QT, QTimer::singleShot simply calls the lambda on the current thread after a given interval.

The usage is:

struct task
{
    struct promise_type
    {
        task get_return_object() { return {}; }
        std::suspend_never initial_suspend() { return {}; }
        std::suspend_never final_suspend() noexcept { return {}; }
        void return_void() {}
        void unhandled_exception() { std::terminate(); }
    };
};

task testAwait()
{
    using namespace std::chrono_literals;

    std::cout << "testAwait started.";

    co_await 5s;

    std::cout << "testAwait finished.";
}

Leave a Reply

Your email address will not be published.