woodb...@gmail.com wrote:
> I like span, but have yet to determine how coroutines
> would be helpful to me. I'm going to stick with 2017
> C++ for my open source code for now.
Coroutines are a very hard beast to understand, even for a very
experienced programmers. Both how they work, how they are used,
and what they are useful for, can be really obscure (and sometimes
hard to explain).
Here's one practical real-life example of where coroutines can be
useful:
Suppose you have a compressed file format decompressor. Quite often
you don't want to decompress the entire input file at once into RAM,
because the decompressed data can be enormous in size (too large to
even fit in RAM at once), and thus you want to decompress and process
it in chunks.
For example, you might want to decompress and hande 1 MB of (decompressed)
data at a time. You might even want, for efficiency, to have a 1 MB
static C-style array into which you decompress the data to to be
handled. In other words, decompress data from the input file into
the 1 MB array, and when the array gets full, handle that data,
and then continue decompressing more data into the same array,
starting from the beginning.
But this poses a problem: Most likely when you are decompressing
the data from the input file, it won't come in nice 1 MB chunks.
At some point something in the compressed input will probably
produce a chunk of data that would overflow the array. It won't
fit in the remaining space in the array.
In other words, you would need to stop decompressing the current
compressed block at the exact moment when the 1 MB array gets full,
call the routine that consumes the array, and then continue from
where you left off, writing the rest of the decompressed block to
the beginning of the array.
In order to be able to do this, you need to store the state of the
decompressor in full. It needs to be able to stop, jump somewhere
else, and then continue exactly from where it stopped.
This is certainly possible with current C++, but it can become
complicated. You need to not only store all the state of the
decompressor inside something (usually a class or struct), but to
also design your decompressor code so that it can continue exactly
from where it stopped (which, depending on the complexity of the
compressed file format, can become quite complicated).
This is where coroutines step in to help, as they automatize the
vast majority of that: At any point in your decompressor code you
can "yield", which jumps back to whatever called the decompressor,
and when that's done, it can return to the exact point where you
yielded, and the decompressor can continue as if nothing had happened.
The entire state at that point in the code is restored automatically.
This simplifies *significantly* this kind of situation, requiring the
programmer to do significantly less work to achieve this. The state is
stored automatically, and the routine can easily continue from wherever
there's a "yield", no matter where it is in the code, or how many
yield points there may be. Even if there's a dozen points in the
decompressor where the target buffer may get full, it doesn't matter.
The next time the execution returns to it, it will continue from that
point.