Refactor coroutine lib for lua 5.2 compatibility
This commit is contained in:
@@ -70,19 +70,19 @@ public class LuaThread extends LuaValue {
|
||||
*/
|
||||
static long thread_orphan_check_interval = 30000;
|
||||
|
||||
private static final int STATUS_INITIAL = 0;
|
||||
private static final int STATUS_SUSPENDED = 1;
|
||||
private static final int STATUS_RUNNING = 2;
|
||||
private static final int STATUS_NORMAL = 3;
|
||||
private static final int STATUS_DEAD = 4;
|
||||
private static final String[] STATUS_NAMES = {
|
||||
public static final int STATUS_INITIAL = 0;
|
||||
public static final int STATUS_SUSPENDED = 1;
|
||||
public static final int STATUS_RUNNING = 2;
|
||||
public static final int STATUS_NORMAL = 3;
|
||||
public static final int STATUS_DEAD = 4;
|
||||
public static final String[] STATUS_NAMES = {
|
||||
"suspended",
|
||||
"suspended",
|
||||
"running",
|
||||
"normal",
|
||||
"dead",};
|
||||
|
||||
private final State state;
|
||||
public final State state;
|
||||
|
||||
/** Field to hold state of error condition during debug hook function calls. */
|
||||
public LuaValue err;
|
||||
@@ -153,14 +153,6 @@ public class LuaThread extends LuaValue {
|
||||
return running_thread;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if this is the main thread
|
||||
* @return true if this is the main thread
|
||||
*/
|
||||
public static boolean isMainThread(LuaThread r) {
|
||||
return r == main_thread;
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback used at the beginning of a call to prepare for possible getfenv/setfenv calls
|
||||
* @param function Function being called
|
||||
@@ -217,13 +209,13 @@ public class LuaThread extends LuaValue {
|
||||
return state.lua_resume(this, args);
|
||||
}
|
||||
|
||||
static class State implements Runnable {
|
||||
public static class State implements Runnable {
|
||||
final WeakReference lua_thread;
|
||||
final LuaValue function;
|
||||
public final LuaValue function;
|
||||
Varargs args = LuaValue.NONE;
|
||||
Varargs result = LuaValue.NONE;
|
||||
String error = null;
|
||||
int status = LuaThread.STATUS_INITIAL;
|
||||
public int status = LuaThread.STATUS_INITIAL;
|
||||
|
||||
State(LuaThread lua_thread, LuaValue function) {
|
||||
this.lua_thread = new WeakReference(lua_thread);
|
||||
@@ -243,7 +235,7 @@ public class LuaThread extends LuaValue {
|
||||
}
|
||||
}
|
||||
|
||||
synchronized Varargs lua_resume(LuaThread new_thread, Varargs args) {
|
||||
public synchronized Varargs lua_resume(LuaThread new_thread, Varargs args) {
|
||||
LuaThread previous_thread = LuaThread.running_thread;
|
||||
try {
|
||||
LuaThread.running_thread = new_thread;
|
||||
@@ -271,7 +263,7 @@ public class LuaThread extends LuaValue {
|
||||
}
|
||||
}
|
||||
|
||||
synchronized Varargs lua_yield(Varargs args) {
|
||||
public synchronized Varargs lua_yield(Varargs args) {
|
||||
try {
|
||||
this.result = args;
|
||||
this.status = STATUS_SUSPENDED;
|
||||
@@ -336,4 +328,8 @@ public class LuaThread extends LuaValue {
|
||||
return level>0 && level<=calls? functions[calls-level]: null;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isMainThread() {
|
||||
return this.state.function == null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,10 +21,13 @@
|
||||
******************************************************************************/
|
||||
package org.luaj.vm2.lib;
|
||||
|
||||
import org.luaj.vm2.LuaError;
|
||||
import org.luaj.vm2.LuaTable;
|
||||
import org.luaj.vm2.LuaThread;
|
||||
import org.luaj.vm2.LuaValue;
|
||||
import org.luaj.vm2.Varargs;
|
||||
import org.luaj.vm2.lib.jme.JmePlatform;
|
||||
import org.luaj.vm2.lib.jse.JsePlatform;
|
||||
|
||||
/**
|
||||
* Subclass of {@link LibFunction} which implements the lua standard {@code coroutine}
|
||||
@@ -54,77 +57,94 @@ import org.luaj.vm2.Varargs;
|
||||
* @see JmePlatform
|
||||
* @see <a href="http://www.lua.org/manual/5.1/manual.html#5.2">http://www.lua.org/manual/5.1/manual.html#5.2</a>
|
||||
*/
|
||||
public class CoroutineLib extends VarArgFunction {
|
||||
public class CoroutineLib extends OneArgFunction {
|
||||
|
||||
private static final int INIT = 0;
|
||||
private static final int CREATE = 1;
|
||||
private static final int RESUME = 2;
|
||||
private static final int RUNNING = 3;
|
||||
private static final int STATUS = 4;
|
||||
private static final int YIELD = 5;
|
||||
private static final int WRAP = 6;
|
||||
private static final int WRAPPED = 7;
|
||||
static long thread_orphan_check_interval = 30000;
|
||||
|
||||
private LuaThread t;
|
||||
static int coroutine_count = 0;
|
||||
|
||||
public CoroutineLib() {
|
||||
public LuaValue call(LuaValue env) {
|
||||
LuaTable coroutine = new LuaTable();
|
||||
coroutine.set("create", new create());
|
||||
coroutine.set("resume", new resume());
|
||||
coroutine.set("running", new running());
|
||||
coroutine.set("status", new status());
|
||||
coroutine.set("yield", new yield());
|
||||
coroutine.set("wrap", new wrap());
|
||||
env.set("coroutine", coroutine);
|
||||
env.get("package").get("loaded").set("coroutine", TRUE);
|
||||
return coroutine;
|
||||
}
|
||||
|
||||
private CoroutineLib(LuaThread t) {
|
||||
this.t = t;
|
||||
}
|
||||
|
||||
private LuaTable init(LuaValue env) {
|
||||
LuaTable t = new LuaTable();
|
||||
bind(t, CoroutineLib.class, new String[] {
|
||||
"create", "resume", "running", "status", "yield", "wrap" },
|
||||
CREATE);
|
||||
env.set("coroutine", t);
|
||||
PackageLib.instance.LOADED.set("coroutine", t);
|
||||
return t;
|
||||
final class create extends LibFunction {
|
||||
public LuaValue call(LuaValue f) {
|
||||
return new LuaThread(f.checkfunction());
|
||||
}
|
||||
}
|
||||
|
||||
final class resume extends VarArgFunction {
|
||||
public Varargs invoke(Varargs args) {
|
||||
switch ( opcode ) {
|
||||
case INIT: {
|
||||
return init(args.arg1());
|
||||
if (!(args.arg1() instanceof LuaThread)) argerror(1, "thread");
|
||||
final LuaThread t = (LuaThread) args.arg1();
|
||||
return resume( t, args.subargs(2) );
|
||||
}
|
||||
case CREATE: {
|
||||
final LuaValue func = args.checkfunction(1);
|
||||
return new LuaThread(func);
|
||||
}
|
||||
case RESUME: {
|
||||
final LuaThread t = args.checkthread(1);
|
||||
return t.resume( args.subargs(2) );
|
||||
}
|
||||
case RUNNING: {
|
||||
|
||||
final class running extends VarArgFunction {
|
||||
public Varargs invoke(Varargs args) {
|
||||
final LuaThread r = LuaThread.getRunning();
|
||||
return LuaThread.isMainThread(r)? NIL: r;
|
||||
return varargsOf(r, valueOf(r.isMainThread()));
|
||||
}
|
||||
case STATUS: {
|
||||
return valueOf( args.checkthread(1).getStatus() );
|
||||
}
|
||||
case YIELD: {
|
||||
return LuaThread.yield( args );
|
||||
|
||||
static final class status extends LibFunction {
|
||||
public LuaValue call(LuaValue t) {
|
||||
LuaThread lt = t.checkthread();
|
||||
return valueOf( lt.getStatus() );
|
||||
}
|
||||
case WRAP: {
|
||||
final LuaValue func = args.checkfunction(1);
|
||||
}
|
||||
|
||||
final class yield extends VarArgFunction {
|
||||
public Varargs invoke(Varargs args) {
|
||||
return yield( args );
|
||||
}
|
||||
}
|
||||
|
||||
final class wrap extends LibFunction {
|
||||
public LuaValue call(LuaValue f) {
|
||||
final LuaValue func = f.checkfunction();
|
||||
final LuaThread thread = new LuaThread(func);
|
||||
CoroutineLib cl = new CoroutineLib(thread);
|
||||
cl.name = "wrapped";
|
||||
cl.opcode = WRAPPED;
|
||||
return cl;
|
||||
return new wrapper(thread);
|
||||
}
|
||||
case WRAPPED: {
|
||||
final Varargs result = t.resume( args );
|
||||
}
|
||||
|
||||
final class wrapper extends VarArgFunction {
|
||||
final LuaThread luathread;
|
||||
wrapper(LuaThread luathread) {
|
||||
this.luathread = luathread;
|
||||
}
|
||||
public Varargs invoke(Varargs args) {
|
||||
final Varargs result = resume(luathread, args);
|
||||
if ( result.arg1().toboolean() ) {
|
||||
return result.subargs(2);
|
||||
} else {
|
||||
error( result.arg(2).tojstring() );
|
||||
return error( result.arg(2).tojstring() );
|
||||
}
|
||||
}
|
||||
default:
|
||||
return NONE;
|
||||
}
|
||||
|
||||
Varargs yield(Varargs args) {
|
||||
final LuaThread.State s = LuaThread.getRunning().state;
|
||||
if (s.function == null)
|
||||
throw new LuaError("cannot yield main thread");
|
||||
return s.lua_yield(args);
|
||||
}
|
||||
|
||||
Varargs resume(LuaThread t, Varargs args) {
|
||||
final LuaThread.State s = t.state;
|
||||
if (s.status > LuaThread.STATUS_SUSPENDED)
|
||||
return LuaValue.varargsOf(LuaValue.FALSE,
|
||||
LuaValue.valueOf("cannot resume "+(s.status==LuaThread.STATUS_DEAD? "dead": "non-suspended")+" coroutine"));
|
||||
return s.lua_resume(t, args);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user