Today I saw discussion about boost.coroutine on gmane:
Generators and coroutines are conceptually the same feature and I have implementation of $generator thing that can be used to implement coroutines.
My implementation is of 15 lines of code and does not require any threads/fibers and so context switches – pure C++ with macro magic, pretty straightforward though.
Anyway, here is an example how coroutine can be implemented using that $generator thing.
First, let’s define coroutine (or generator) that will establish connection with some server and will supply (yield) data chunks read from socket:
$generator(net_reader) { socket_t sock; byte buffer[2048]; net_reader(const char* addr) { sock.connect(addr); } // from $emit to $stop is a body of our coroutine: $emit(slice<byte>) // Coroutine will emit slice<byte> values. Start of coroutine body. while( sock.valid() ) { slice<byte> r(buffer,0); r.length = sock.read(buffer,sizeof(buffer)); if(r.length) $yield( r ); else break; } $stop; // stop. End of coroutine body. };
Having this we can write code that will read data chunk by chunk and store it in some array.
array<byte> data; net_reader get("data.example.com:4002"); for(slice<byte> chunk; get(chunk);) data.push(chunk);
That’s easy, no?
Yes, $generator thing is not free from problems (e.g. you cannot use switch()
inside its body) but other than that and in 99% of coroutine cases you will get what is needed from generators/coroutines. And without those tons of code.