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;
|
static long thread_orphan_check_interval = 30000;
|
||||||
|
|
||||||
private static final int STATUS_INITIAL = 0;
|
public static final int STATUS_INITIAL = 0;
|
||||||
private static final int STATUS_SUSPENDED = 1;
|
public static final int STATUS_SUSPENDED = 1;
|
||||||
private static final int STATUS_RUNNING = 2;
|
public static final int STATUS_RUNNING = 2;
|
||||||
private static final int STATUS_NORMAL = 3;
|
public static final int STATUS_NORMAL = 3;
|
||||||
private static final int STATUS_DEAD = 4;
|
public static final int STATUS_DEAD = 4;
|
||||||
private static final String[] STATUS_NAMES = {
|
public static final String[] STATUS_NAMES = {
|
||||||
"suspended",
|
"suspended",
|
||||||
"suspended",
|
"suspended",
|
||||||
"running",
|
"running",
|
||||||
"normal",
|
"normal",
|
||||||
"dead",};
|
"dead",};
|
||||||
|
|
||||||
private final State state;
|
public final State state;
|
||||||
|
|
||||||
/** Field to hold state of error condition during debug hook function calls. */
|
/** Field to hold state of error condition during debug hook function calls. */
|
||||||
public LuaValue err;
|
public LuaValue err;
|
||||||
@@ -153,14 +153,6 @@ public class LuaThread extends LuaValue {
|
|||||||
return running_thread;
|
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
|
* Callback used at the beginning of a call to prepare for possible getfenv/setfenv calls
|
||||||
* @param function Function being called
|
* @param function Function being called
|
||||||
@@ -217,13 +209,13 @@ public class LuaThread extends LuaValue {
|
|||||||
return state.lua_resume(this, args);
|
return state.lua_resume(this, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
static class State implements Runnable {
|
public static class State implements Runnable {
|
||||||
final WeakReference lua_thread;
|
final WeakReference lua_thread;
|
||||||
final LuaValue function;
|
public final LuaValue function;
|
||||||
Varargs args = LuaValue.NONE;
|
Varargs args = LuaValue.NONE;
|
||||||
Varargs result = LuaValue.NONE;
|
Varargs result = LuaValue.NONE;
|
||||||
String error = null;
|
String error = null;
|
||||||
int status = LuaThread.STATUS_INITIAL;
|
public int status = LuaThread.STATUS_INITIAL;
|
||||||
|
|
||||||
State(LuaThread lua_thread, LuaValue function) {
|
State(LuaThread lua_thread, LuaValue function) {
|
||||||
this.lua_thread = new WeakReference(lua_thread);
|
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;
|
LuaThread previous_thread = LuaThread.running_thread;
|
||||||
try {
|
try {
|
||||||
LuaThread.running_thread = new_thread;
|
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 {
|
try {
|
||||||
this.result = args;
|
this.result = args;
|
||||||
this.status = STATUS_SUSPENDED;
|
this.status = STATUS_SUSPENDED;
|
||||||
@@ -336,4 +328,8 @@ public class LuaThread extends LuaValue {
|
|||||||
return level>0 && level<=calls? functions[calls-level]: null;
|
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;
|
package org.luaj.vm2.lib;
|
||||||
|
|
||||||
|
import org.luaj.vm2.LuaError;
|
||||||
import org.luaj.vm2.LuaTable;
|
import org.luaj.vm2.LuaTable;
|
||||||
import org.luaj.vm2.LuaThread;
|
import org.luaj.vm2.LuaThread;
|
||||||
import org.luaj.vm2.LuaValue;
|
import org.luaj.vm2.LuaValue;
|
||||||
import org.luaj.vm2.Varargs;
|
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}
|
* Subclass of {@link LibFunction} which implements the lua standard {@code coroutine}
|
||||||
@@ -54,77 +57,94 @@ import org.luaj.vm2.Varargs;
|
|||||||
* @see JmePlatform
|
* @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>
|
* @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;
|
static long thread_orphan_check_interval = 30000;
|
||||||
private static final int CREATE = 1;
|
|
||||||
private static final int RESUME = 2;
|
static int coroutine_count = 0;
|
||||||
private static final int RUNNING = 3;
|
|
||||||
private static final int STATUS = 4;
|
public LuaValue call(LuaValue env) {
|
||||||
private static final int YIELD = 5;
|
LuaTable coroutine = new LuaTable();
|
||||||
private static final int WRAP = 6;
|
coroutine.set("create", new create());
|
||||||
private static final int WRAPPED = 7;
|
coroutine.set("resume", new resume());
|
||||||
|
coroutine.set("running", new running());
|
||||||
private LuaThread t;
|
coroutine.set("status", new status());
|
||||||
|
coroutine.set("yield", new yield());
|
||||||
public CoroutineLib() {
|
coroutine.set("wrap", new wrap());
|
||||||
|
env.set("coroutine", coroutine);
|
||||||
|
env.get("package").get("loaded").set("coroutine", TRUE);
|
||||||
|
return coroutine;
|
||||||
}
|
}
|
||||||
|
|
||||||
private CoroutineLib(LuaThread t) {
|
final class create extends LibFunction {
|
||||||
this.t = t;
|
public LuaValue call(LuaValue f) {
|
||||||
}
|
return new LuaThread(f.checkfunction());
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Varargs invoke(Varargs args) {
|
|
||||||
switch ( opcode ) {
|
|
||||||
case INIT: {
|
|
||||||
return init(args.arg1());
|
|
||||||
}
|
|
||||||
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 LuaThread r = LuaThread.getRunning();
|
|
||||||
return LuaThread.isMainThread(r)? NIL: r;
|
|
||||||
}
|
|
||||||
case STATUS: {
|
|
||||||
return valueOf( args.checkthread(1).getStatus() );
|
|
||||||
}
|
|
||||||
case YIELD: {
|
|
||||||
return LuaThread.yield( args );
|
|
||||||
}
|
|
||||||
case WRAP: {
|
|
||||||
final LuaValue func = args.checkfunction(1);
|
|
||||||
final LuaThread thread = new LuaThread(func);
|
|
||||||
CoroutineLib cl = new CoroutineLib(thread);
|
|
||||||
cl.name = "wrapped";
|
|
||||||
cl.opcode = WRAPPED;
|
|
||||||
return cl;
|
|
||||||
}
|
|
||||||
case WRAPPED: {
|
|
||||||
final Varargs result = t.resume( args );
|
|
||||||
if ( result.arg1().toboolean() ) {
|
|
||||||
return result.subargs(2);
|
|
||||||
} else {
|
|
||||||
error( result.arg(2).tojstring() );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return NONE;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final class resume extends VarArgFunction {
|
||||||
|
public Varargs invoke(Varargs args) {
|
||||||
|
if (!(args.arg1() instanceof LuaThread)) argerror(1, "thread");
|
||||||
|
final LuaThread t = (LuaThread) args.arg1();
|
||||||
|
return resume( t, args.subargs(2) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final class running extends VarArgFunction {
|
||||||
|
public Varargs invoke(Varargs args) {
|
||||||
|
final LuaThread r = LuaThread.getRunning();
|
||||||
|
return varargsOf(r, valueOf(r.isMainThread()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static final class status extends LibFunction {
|
||||||
|
public LuaValue call(LuaValue t) {
|
||||||
|
LuaThread lt = t.checkthread();
|
||||||
|
return valueOf( lt.getStatus() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
return new wrapper(thread);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {
|
||||||
|
return error( result.arg(2).tojstring() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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