A VM in Java with tail-calls and continuations

Friday, July 22, 2005

User Guide - Part Four

In my previous installment I showed you some examples of using continuations. From them you can see continuations are a sort of non-local jumps (a bit like exceptions). Isn't that dangerous? Yes, it is - but fun! Let's have an example:

@interpretable Continuation aMethod() {
return new Continuation();
}

@interpretable void anotherMethod() {
Continuation cont = aMethod();

synchronized (this) {
cont.returnTo(cont);
}
}

Note the synchronized block. Now that's nasty, right? If you jump somewhere else, just like that, this will remain locked, right? Well, no... Remember continuations are “a bit like exceptions” and the JauVM will handle the unlocking for you, just like the JVM does with exceptions. We have a new problem though:
@interpretable Continuation aMethod() {
return new Continuation();
}

@interpretable void anotherMethod() {
Continuation cont = null;

synchronized (this) {
cont = aMethod();
}

cont.returnTo(cont);
}

What's happening here? Well, you acquire the lock, then you save the Continuation and release the lock. Afterwards you invoke the Continuation, and you're suddenly inside the synchronized block without the lock.

Now wait a minute. Can't the JauVM reacquire the lock for me? Unfortunately no, it's not that simple. And we have the same problem with try ... finally too - finallys are ran, but we have no “initially”.

To amend this issue an new Throwable was devised - the continuing class. It can be used to tag a catch clause of a try block as the code to be run when that try is reentered. Confusing? Examples will help.

In the presence of continuations code, a synchronized should look like this:
synchronized (this) {
try {
// ...
} catch (continuing c) {
Monitor.enter(this);
}
}

And a try ... finally (safeguarding a JDBC connection, in this case) should be:
Connection conn = pool.getConnection();
try {
// ...
} catch (continuing c) {
conn = pool.getConnection();
} finally {
conn.close();
}

As you can see, the catch continuing clause is about reacquiring the resources you've freed when you first left the try block.

But what's this continuing class like? Here it is:
public final class continuing extends Error {
private continuing() {
}
}

The class is final and the constructor private because there should be no objects of this kind - again this is just a tag! It extends Error for it mustn't be a checked exception, and shouldn't normally be caught either - though it doesn't make a difference if you catch Throwable, only continuing works.

Also, you're probably curious about that Monitor class. Well, it will have to be written in assembly, and I haven't made up my mind about an assembler yet (Jamaica, Jasmin...) It'll have at least enter and exit static methods, but you'll see.

And that's it, for now! User guide over. Not complete, but I hope I've passed along the general picture. By the way, I'm open to suggestions for names for these all classes and methods (especially the continuing exception, which I particularly dislike).

Thanks for “listening”!

No comments:

Archive