Sign in to follow this  

Emulating continuations in C++?

This topic is 4745 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Is it possible to emulate continuations in C++? If so, how might I go about doing this? I'm not sure how I'd save the contents of the stack to begin with, and this sounds like it'll need to be relegated to assembly.

Share this post


Link to post
Share on other sites
Pardon my ignorance as I don't actually know what a continuation is, although I'm interested now. It sounds like your trying to program using other language idioms in C++.
There are cleaner and more effective ways to program in C++ than resorting to assembly just to emmulate other language features. Trust me, it's better in the long run.

In other words:
"When in Rome... "

Share this post


Link to post
Share on other sites
Even if you could duplicate the stack effects, which would be a non-trivial task in and of itself, I don't think you'd be able to capture effects on heap objects properly. The best you could probably hope for is a clean stack unwind, but that's only a pale shadow of a true continuation.

So no, probably not.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
[quote]Original post by iMalc
Quote:
Pardon my ignorance as I don't actually know what a continuation is, although I'm interested now. It sounds like your trying to program using other language idioms in C++.

A continuation is just a fancy term for a means of representing the executable state of a program at a given point. In a language with stack frames like C++, this means the state of stack. The basic idea is that, instead of having a function return a value, functions take an argument that is another function called the continuation. The result of that function is then given to the continuation as an argument. It's a little bit of a kooky concept, but continuations are basically gotos with parameters.

Here's a more in-depth explanation if you're confuzzled. You can also Google for "continuation language feature", "continuation-passing style", and similar terms.

Quote:
There are cleaner and more effective ways to program in C++ than resorting to assembly just to emmulate other language features. Trust me, it's better in the long run.

Rest assured, this is purely an academic exercise. I'm not actually planning to use them in a serious program. I'd just prefer to experiment and practice with them a bit using a language I already know. Similarly, when a professional basketball player wants to practice a new jump shot, he doesn't head for the tennis court or go bowling. ;)

Share this post


Link to post
Share on other sites
GPG2 had a few articles on micro-threading AI that saved off the current state of the stack and could then restore it later. The code in GPG only works on x86, but I got it to work on MIPS also... there's just a whole bunch more registers to save (don't forget saved FPU registers!!! that was a nasty bug.....), and you need to do some extra fancy footwork with the function headers to make sure specify your own preamble (different call/ret convention) and not let the compiler optimize it away (i.e. you need the ret to finally happen at the right time so all descructors get called correctly).

A pretty big pain to get it all working, but it is possible :)

Share this post


Link to post
Share on other sites
I know that you can simulate the same (sementicaly and syntaxicaly speaking) exception handling than Java in pure C with setjump, longjump and several macro definitions, so I suppose that you could simulate the continuation in the same way. The issue is that the documentation about the implementation is at home and I'll back home in two month, but I'm sure that it should be possible to googling that, sorry :).
-uto-

Share this post


Link to post
Share on other sites
Evidentally some people don't understand continuations.

Continuations are not the same as 'exception handlers'. In most languages, once an exception has been handled, it's not possible to continue processing from the point where the exception was raised. With exception handling implemented by continuations, on the other hand, it is possible.

Properly implementing continuations isn't quite as simple as copying the stack. Consider the following code snippet:


void foo ()
{
int x = 0;
try {
bar(&x);
} catch (std::continuation<char *> cc) {
cc();
}
std::cout << x << std::endl;
}

void bar (int* x)
{
++*x;
throw_cc "some error";
++*x;
}



One might expect the output to be 2. However, throw_cc would cause stack copying, and so the second ++*x would incremement a local copy of x. Although that's fine if you're expecting it, this isn't how continuations behave in Scheme, and most people might not expect it.

The problem isn't indefeatable. It just means that you have to do a little more than copying the stack.

Share this post


Link to post
Share on other sites
[quote]Original post by Anonymous Poster
Quote:
Original post by iMalc
Quote:
Pardon my ignorance as I don't actually know what a continuation is, although I'm interested now. It sounds like your trying to program using other language idioms in C++.

A continuation is just a fancy term for a means of representing the executable state of a program at a given point. In a language with stack frames like C++, this means the state of stack. The basic idea is that, instead of having a function return a value, functions take an argument that is another function called the continuation. The result of that function is then given to the continuation as an argument. It's a little bit of a kooky concept, but continuations are basically gotos with parameters.

Here's a more in-depth explanation if you're confuzzled. You can also Google for "continuation language feature", "continuation-passing style", and similar terms.

Quote:
There are cleaner and more effective ways to program in C++ than resorting to assembly just to emmulate other language features. Trust me, it's better in the long run.

Rest assured, this is purely an academic exercise. I'm not actually planning to use them in a serious program. I'd just prefer to experiment and practice with them a bit using a language I already know. Similarly, when a professional basketball player wants to practice a new jump shot, he doesn't head for the tennis court or go bowling. ;)
Okay thanks, I understand now. Good luck with that.
If I'm correct, Jade is one language that has continuations (non-fatal, resumeable exceptions)
I like flangazor's idea for this btw. In fact if you keep the changes localised you might be able to distribute it as a source code patch to anyone else wanting to use it.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
And what would continuations true be useful for? I mean, what can I do with them that isn't possible (or extremely inconvenient) in C++? Thanks.

Share this post


Link to post
Share on other sites
Of interest.

Paul Graham discusses it in an email.

I spent a bit of time writing a call/cc example for Bigloo and then generated the C code from it so you could see how it goes about doing it, but it is written by a machine for machine compiltion and is not very readable. The C code is quite long, too so I'm not going to post it. If you have bigloo, you can check it out if you are interested.

The code was:

(module my-test
(main start))

(define test
(call-with-current-continuation
(lambda (exit)
(for-each (lambda (x)
(if (negative? x)
(exit x)))
'(54 0 37 -3 245 19))
#t))) ;returns -3

(define start
(lambda (argv::pair)
(test)))


The command line was: bigloo -cgen -call/cc -o callcc.c callcc.scm where callcc.scm was the scheme file.

AP, call/cc is useful for programming what you mean and not having to jump through hoops. e.g. in the above example, you mean to say "for each, see if the value is negative and if it is, return." Obviously, once you found a negative number you don't want to look through more items. This doesn't seem so great in this example, but the benefit is that you return to where it says call/cc regardless of how deep you go. This is essential in languages like Scheme where recursion is the name of the game. Otherwise, you would just be returning to the previous recursed call and would need to set up all sorts of flags and such to show that you really wanted to leave.

Share this post


Link to post
Share on other sites

This topic is 4745 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this