From 56a66ed93359a93a479001489b1230a69cde30f8 Mon Sep 17 00:00:00 2001 From: James Roseborough Date: Wed, 12 Sep 2012 05:36:50 +0000 Subject: [PATCH] Refactor coroutine lib for lua 5.2 compatibility --- src/core/org/luaj/vm2/LuaThread.java | 36 ++--- src/core/org/luaj/vm2/lib/CoroutineLib.java | 158 +++++++++++--------- 2 files changed, 105 insertions(+), 89 deletions(-) diff --git a/src/core/org/luaj/vm2/LuaThread.java b/src/core/org/luaj/vm2/LuaThread.java index 73cd0684..9ed032da 100644 --- a/src/core/org/luaj/vm2/LuaThread.java +++ b/src/core/org/luaj/vm2/LuaThread.java @@ -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; + } } diff --git a/src/core/org/luaj/vm2/lib/CoroutineLib.java b/src/core/org/luaj/vm2/lib/CoroutineLib.java index 98914051..7e037c9e 100644 --- a/src/core/org/luaj/vm2/lib/CoroutineLib.java +++ b/src/core/org/luaj/vm2/lib/CoroutineLib.java @@ -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 http://www.lua.org/manual/5.1/manual.html#5.2 */ -public class CoroutineLib extends VarArgFunction { - - 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; - - private LuaThread t; - - public CoroutineLib() { +public class CoroutineLib extends OneArgFunction { + + static long thread_orphan_check_interval = 30000; + + static int coroutine_count = 0; + + 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; - } - - 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 create extends LibFunction { + public LuaValue call(LuaValue f) { + return new LuaThread(f.checkfunction()); } } + + 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); + } }