FunMiles / PicoAsync

An open-source library for C++ coroutine based asynchronous programming on the Raspberry Pi Pico.
24 stars 3 forks source link

Add a CPU yield awaitable. #2

Open FunMiles opened 1 year ago

FunMiles commented 1 year ago

A purely coroutine based multi-tasking system needs all tasks to be good citizen of the cooperative multi-tasking system, yielding the CPU to other tasks in a periodic manner, enabling long running compute intensive tasks to run while not stopping other tasks from operating. A yield awaitable object is a clean way of achieving this goal. It can be awaited periodically in long running loops:

task<> do_some_long_computation(int iterationCount, auto &&operation, priority myPriority)
{
    for (int i = 0; i < iterationCount; ++i) {
         // Perform one iteration's work
         operation(i);
         // Yield the CPU, signaling the queueing system our priority (optional argument)
         co_await cpu::yield(myPriority); 
     }
}

An example of such use is for the SSD1306 code. Filling the OLED screen buffer to print text can take tens of thousands of cycles. The routine performing this operation should be capable of yielding so that time-critical operations can take place.

hattesen commented 11 months ago

Could a "poor man's version" of a yield awaitable be constructed as ...

co_await 0ms;

PS's:

FunMiles commented 11 months ago

Could a "poor man's version" of a yield awaitable be constructed as ...

co_await 0ms;

Yes, that is indeed a poor man's version. The ultimate version would have a sense of priority. Some running tasks could be purely "maintenance" type with no set deadline of execution. I think the question will remain opened/work in progress for a while.

PS's:

  • I really appreciate your effort to make C++ 20 coroutines approachable, and I believe is a great shame that a similar thing was not baked into C++ 20 itself, rather than delivering the over-designed mess that it presents itself as now.
  • Having a lot of "real world" examples, as this library has, is great for understanding typical use-cases, but I really miss some proper API documentation for the library.
  • Another thing that would assist users of this library – who may know nothing about C++ 20 coroutines – would be to provide top level documentation on how the coroutines work, explaining how/when context switching is performed, how task stacks are managed etc, possibly by copying/referencing existing C++20 documentation, such as ...

    Coroutines (C++20) A coroutine is a function that can suspend execution to be resumed later. Coroutines are stackless: they suspend execution by returning to the caller and the data that is required to resume execution is stored separately from the stack. (from cppreference)

I appreciate your comments. And I do agree with them. Unfortunately, I have been busy with many a thing and this library has been on the back burner, but I will get back to it and try to help with the descriptions your last two comments ask for.

Cheers.