lewissbaker / cppcoro

A library of C++ coroutine abstractions for the coroutines TS
MIT License
3.36k stars 462 forks source link

Cooperative multi-task / event loop with co_await #199

Open asfernandes opened 3 years ago

asfernandes commented 3 years ago

I'd like to create something like an event loop that schedules tasks and do some logic when a task (or sub-task) is co_awaited.

Basically I want something like sync_wait that runs in a loop running just a piece of a task (until its next co_await).

For example this one is a code working, but not given what I want:

#include <cppcoro/task.hpp>
#include <cppcoro/sync_wait.hpp>
#include <iostream>

cppcoro::task<int> f2()
{
    std::cout << "f2.1\n";
    co_return 2;
}

cppcoro::task<int> f1()
{
    std::cout << "f1.1\n";
    auto co = f2();
    std::cout << "f1.2\n";
    auto r = co_await co;
    std::cout << "f1.3\n";
    co_return r;
}

int main()
{
    std::cout << "main.1\n";
    auto co = f1();
    std::cout << "main.2\n";
    auto r = sync_wait(co);
    std::cout << "main.3: " << r << '\n';
    return 0;
}

I want something like this:

int main()
{
    std::cout << "main.1\n";
    auto co = f1();
    std::cout << "main.2\n";

    auto r = start_task(co);
    do
    {
        std::cout << "main loop\n";
    } while (r.continue());

    std::cout << "main.3: " << r << '\n';
    return 0;
}

Can I achieve this with this library?

I need that all the code run in the same thread.

ddurham2 commented 2 years ago

I have the same question. Looking for a way to have coroutinues run atop an event loop. Some events may be ui-event handlers, other events may be the signal to resume a suspended coroutine.

The closest concept I see in the current api is to have a blocking call use an single_consumer_event to suspend itself, and then the resuming event calls .set() to continue it. But how, from the event loop we start a task until it suspends, and then get control back to process the next message, I haven't figured out.

Basically, I'm asking how to get an event handler to invoke a()

... run a() -> b() -> c() ---
 ^                           |
 |                           |
  --------------------------

... and then getting c()'s suspend to return control back to what called a()

Here, maybe c() could co_await a single_consumer_event, but I don't see where control goes at that point.