I doubt it can be done portably, but are there any solutions out there? I think it could be done by creating an alternate stack and reseting SP,BP, and IP on function entry
There's no easy way to implement coroutine. Because coroutine itself is out of C/C++'s stack abstraction just like thread. So it cannot be supported without language level changes to support.
Currently(C++11), all existing C++ coroutine implementations are all based on assembly level hacking which is hard to be safe and reliable crossing over platforms. To be reliable it needs to be standard, and handled by compilers rather than hacking.
There's a standard proposal - N3708 for this. Check it out if you're interested.
I've tried to implement coroutines myself using C++11 and threads:
#include <iostream>
#include <thread>
class InterruptedException : public std::exception {
};
class AsyncThread {
public:
AsyncThread() {
std::unique_lock<std::mutex> lock(mutex);
thread.reset(new std::thread(std::bind(&AsyncThread::run, this)));
conditionVar.wait(lock); // wait for the thread to start
}
~AsyncThread() {
{
std::lock_guard<std::mutex> _(mutex);
quit = true;
}
conditionVar.notify_all();
thread->join();
}
void run() {
try {
yield();
for (int i = 0; i < 7; ++i) {
std::cout << i << std::endl;
yield();
}
} catch (InterruptedException& e) {
return;
}
std::lock_guard<std::mutex> lock(mutex);
quit = true;
conditionVar.notify_all();
}
void yield() {
std::unique_lock<std::mutex> lock(mutex);
conditionVar.notify_all();
conditionVar.wait(lock);
if (quit) {
throw InterruptedException();
}
}
void step() {
std::unique_lock<std::mutex> lock(mutex);
if (!quit) {
conditionVar.notify_all();
conditionVar.wait(lock);
}
}
private:
std::unique_ptr<std::thread> thread;
std::condition_variable conditionVar;
std::mutex mutex;
bool quit = false;
};
int main() {
AsyncThread asyncThread;
for (int i = 0; i < 3; ++i) {
std::cout << "main: " << i << std::endl;
asyncThread.step();
}
}
For those who want to know how they may leverage Coroutines in a portable way in C++ y̶o̶u̶ ̶w̶i̶l̶l̶ ̶h̶a̶v̶e̶ ̶t̶o̶ ̶w̶a̶i̶t̶ ̶f̶o̶r̶ ̶C̶+̶+̶1̶7̶ the wait is over (see below)! The standards committee is working on the feature see the N3722 paper. To summarize the current draft of the paper, instead of Async and Await, the keywords will be resumable, and await.
Take a look at the experimental implementation in Visual Studio 2015 to play with Microsoft's experimental implementation. It doesn't look like clang has a implementation yet.
There is a good talk from Cppcon Coroutines a negative overhead abstraction outline the benefits of using Coroutines in C++ and how it affects simplicity and performance of the code.
At present we still have to use library implementations, but in the near future, we will have coroutines as a core C++ feature.
Update: Looks like the coroutine implementation is slated for C++20, but was released as a technical specification with C++17 (p0057r2). Visual C++, clang and gcc allow you to opt in using a compile time flag.
This is an old thread, but I would like to suggest a hack using Duff's device that is not os-dependent (as far as I remember):
C coroutines using Duff's device
And as an example, here is a telnet library I modified to use coroutines instead of fork/threads: Telnet cli library using coroutines
And since standard C prior to C99 is essentially a true subset of C++, this works well in C++ too.
For posterity,
Dmitry Vyukov's wondeful web site has a clever trick using ucontext and setjump to simulated coroutines in c++.
Also, Oliver Kowalke's context library was recently accepted into Boost, so hopefully we'll be seeing an updated version of boost.coroutine that works on x86_64 soon.
WvCont is a part of WvStreams that implements so-called semi-coroutines. These are a little easier to handle than full-on coroutines: you call into it, and it yields back to the person who called it.
It's implemented using the more flexible WvTask, which supports full-on coroutines; you can find it in the same library.
Works on win32 and Linux, at least, and probably any other Unix system.