Initial draft of coroutines library.

This commit is contained in:
James Roseborough
2007-10-20 00:51:15 +00:00
parent 8e2ff119f9
commit 78eaaf0fa0
8 changed files with 233 additions and 4 deletions

View File

@@ -1382,7 +1382,7 @@ public interface VM {
* This function pops <code>n</code> values from the stack
* <code>from</code>, and pushes them onto the stack <code>to</code>.
*/
public void xmove(StackState to, int n);
public void xmove(VM to, int n);
/**
* Yields a coroutine. <span class="apii">[-?, +?, <em>-</em>]</span>

View File

@@ -3,20 +3,35 @@ package lua.io;
import lua.StackState;
import lua.VM;
import lua.value.LFunction;
import lua.value.LValue;
import lua.value.LTable;
public class Closure extends LFunction {
public LValue env;
public LTable env;
public Proto p;
public UpVal[] upVals;
// TODO: change arg type to VM?
/**
* @deprecated construct with environment instead
* @param state
* @param p
*/
public Closure(StackState state, Proto p) {
this.env = state._G;
this.p = p;
upVals = new UpVal[p.nups];
}
/**
* Construct using a prototype and initial environment.
* @param p
* @param env
*/
public Closure(Proto p, LTable env) {
this.p = p;
this.env = env;
upVals = new UpVal[p.nups];
}
// called by vm when there is an OP_CALL
// in this case, we are on the stack,
// and simply need to cue the VM to treat it as a stack call

View File

@@ -1,9 +1,33 @@
package lua.value;
import lua.Lua;
import lua.StackState;
import lua.VM;
import lua.io.Closure;
public class LThread extends LValue {
private static final int STATUS_SUSPENDED = 1;
private static final int STATUS_NORMAL = 2;
private static final int STATUS_ACTIVE = 3;
private static final int STATUS_DEAD = 4;
private static final String[] NAMES = {
"suspended",
"normal",
"active",
"dead" };
private int status = STATUS_SUSPENDED;
private StackState threadVm;
public LThread(Closure c) {
// TODO: inherit globals!
threadVm = new StackState();
threadVm.pushlvalue(new Closure(c.p, threadVm._G));
}
public int luaGetType() {
return Lua.LUA_TTHREAD;
}
@@ -11,4 +35,74 @@ public class LThread extends LValue {
public String toJavaString() {
return "thread: "+hashCode();
}
public String getStatus() {
return NAMES[status];
}
/** This needs to leave any values returned by yield in the corouting
* on the calling vm stack
* @param vm
* @param prior
*/
public void resumeFrom(VM vm, LThread prior) {
if ( status == STATUS_DEAD ) {
vm.settop(0);
vm.pushboolean(false);
vm.pushstring("cannot resume dead coroutine");
return;
}
// set prior thread to normal status while we are running
if ( prior != null )
prior.status = STATUS_NORMAL;
try {
// copy args in
if ( threadVm.cc < 0 ) {
vm.xmove(threadVm, vm.gettop() - 2);
threadVm.prepStackCall();
} else {
threadVm.settop(0);
vm.xmove(threadVm, vm.gettop() - 2);
}
// run this vm until it yields
status = STATUS_ACTIVE;
while ( threadVm.cc >= 0 && status == STATUS_ACTIVE )
threadVm.exec();
// copy return values from yielding stack state
vm.settop(0);
vm.pushboolean(true);
if ( threadVm.cc >= 0 ) {
threadVm.xmove(vm, threadVm.gettop() - 1);
} else {
threadVm.base = 0;
threadVm.xmove(vm, threadVm.gettop());
}
} catch ( Throwable t ) {
status = STATUS_DEAD;
vm.settop(0);
vm.pushboolean(false);
vm.pushstring("thread: "+t);
} finally {
if ( threadVm.cc < 0 )
status = STATUS_DEAD;
// reset prior thread status
if ( prior != null )
prior.status = STATUS_ACTIVE;
}
}
public boolean yield() {
if ( status == STATUS_ACTIVE )
status = STATUS_SUSPENDED;
return true;
}
}