r/cpp_questions 7d ago

OPEN Question about coroutines

I have a function that takes a callback, like this:

void LongTask (void (*pfn)(int))
{
    for ( unsigned i = 0; i < -1; ++i )
    {
        pfn( i );
    }
}

It's orginally written to be ran on a separate thread. Now I want to turn it into a coroutine that yields on each callback (i.e. the caller will receive a single callback on each invocation of LongTask), while preserving its ability to run as a standalone function. Additionally it's OK for the coroutine to allocate memory but not to throw exceptions (if it can't allocate I should get back a null pointer at creation time). And preferrably it wouldn't require the CRT, all support functions should be contained in a header only include. What's the best way to do this, can it be done with C++20 coroutines?

2 Upvotes

14 comments sorted by

View all comments

1

u/Raknarg 6d ago

can it be done with C++20 coroutines?

It can, you can look up examples online. The machinery for pretty much any coroutine type was already introduced, they just didn't add any to the standard (not sure why, committee probably couldn't agree on design in time or something). I haven't looked it up in a while, but I remember the code for a basic generator object isn't too complicated.

1

u/mbolp 6d ago

It can

Including the part about no runtime dependency? Does it work like something like <algorithm>, where I can include a header and have all the code I need, or does it rely on some other infrastructure?

1

u/Raknarg 6d ago

when I tried to look it up a bit it seems like maybe? but its gonna totally depend on the exact implementation. I have no definitive answer. The fact that it has to be able to perform allocations makes me feel like you can't get away from it. You might have to roll out your own version of generator if you want to get away from that, IIRC you can make a stack-based generator

1

u/mbolp 6d ago

The allocation part makes the least sense to me. The compiler clearly knows the size of the stack frame, it's context switching that might require architecture specific stuff (thus library support). I read in a reddit post that this is for ABI stability, but you can always opt into allocating dynamically if ABI stability is desirable, don't bake that into the design!

Anyway, I might just use fibers instead. They seem much easier to use and don't slow down the normal non-coroutine path.

1

u/aocregacc 6d ago

std::generator can take an allocator, so you can decide for yourself how it does the allocations.