tags:

views:

2356

answers:

8

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, and having yield save IP and restore SP+BP. Destructors and exception safety seem tricky but solvable.

Has it been done? Is it impossible?

+1  A: 

Does this point you in the right direction? It seems like an elegant solution that has lasted the test of time.....it's 9 years old!

[update] I'm actually making successful use of it myself. Curiousity got the better of me, so I looked into this solution, and found it was a good fit for a problem I've been working on for some time!

Dan
+1  A: 

You might be better off with an iterator than a coroutine if possible. That way you can keep calling next() to get the next value, but you can keep your state as member variables instead of local variables.

It might make things more maintainable. Another c++ developer might not immediately understand the coroutine whereas they might be more familiar with an iterator.

Steve g
+1  A: 

I dont think there are many full-blown, clean implementations in C++. One try that I like is protothread library.

yrp
+11  A: 

Yes it can be done with out a problem. All you need is a little asm to move the call stack to a newly allocated stack on the heap.

I would look at the experimental Boost.Coroutine library.

The one thing that you should watch out for is a stackoverflow. On most operating systems overflowing the stack will cause a SEGFAULT because virtual memory page is not mapped. However if you allocate the stack on the heap you don't get any guarantee. Just keep that in mind

witkamp
I think there should be a badge for being able to mention thze work "stackoverflow" in a valid technical context on SO!
Torsten Marek
Here's a nice standard C++ solution that doesn't require involving Boost :http://www.akira.ruc.dk/~keld/research/COROUTINE/
Dan
Unfortunately Boost.Coroutine is not supported for x86_64 :(
pachanga
A: 

You should always consider using threads instead; especially in modern hardware. If you have work that can be logically separated in Co-routines, using threads means the work might actually be done concurrently, by separate execution units (processor cores).

But, maybe you do want to use coroutines, perhaps because you have an well tested algorithm that has already been written and tested that way, or because you are porting code written that way.

If you work within Windows, you should take a look at fibers. Fibers will give you a coroutine-like framework with support from the OS.

I am not familiar with other OS's to recommend alternatives there.

Euro Micelli
I disagree about blindly favoring threads over fibers. In an optimal system the number of threads trying to run is equal to then number of cores (more if hyper threading). In a solution with LOTS of threads(100s), a thread pool running fibers can be far more efficient.
caspin
Thanks for commenting. However, I didn't say "blindly favor"; I said "always consider". I agree that there are circumstances where fibers or other coroutine methodologies might be more appropriate, but they can be even harder to "get right" than threads -- and that's saying a lot. Basically, I'm suggesting that for most circumstances you should use threads by default, unless you can convince yourself that there are good reasons to go for something else.
Euro Micelli
Threading means locking, whereas coroutines are naturally executed in order. Boom half your work is already done for you. Threads are good if you want to compute multiple heavy algorithms in parallel, I can't really think of any other reason to use them. I guess if there's some blocking API that has no non-blocking mode?
Longpoke
@Longpoke, I don't agree that half your work is done for you with coroutines. You trade thinking about locks for having to split your algorithm. Different things. Sometimes coroutines are better, sometimes not. That's what i meant by *consider threading*.
Euro Micelli
+5  A: 

On POSIX, you can use makecontext()/swapcontext() routines to portably switch execution contexts. On Windows, you can use the fiber API. Otherwise, all you need is a bit of glue assembly code that switches the machine context. I have implemented coroutines both with ASM (for AMD64) and with swapcontext(); neither is very hard.

zvrba
A: 

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.

apenwarr