From cd5da6097812baf125c2dc4f1d12e1a3f4985464 Mon Sep 17 00:00:00 2001 From: Nicolas Noble Date: Mon, 5 Aug 2013 11:53:57 -0700 Subject: Greatly simplifying the LuaYield mechanism so to avoid double-recursive calls in resume(). --- includes/BLua.h | 6 +++--- includes/Task.h | 3 --- src/BLua.cc | 59 ++++++++++++++++++++++++++----------------------------- tests/test-Lua.cc | 2 +- 4 files changed, 32 insertions(+), 38 deletions(-) diff --git a/includes/BLua.h b/includes/BLua.h index a464a77..ccf7bee 100644 --- a/includes/BLua.h +++ b/includes/BLua.h @@ -162,7 +162,7 @@ class Lua { void dumpvars(IO out, const String & prefix, int idx = -1); Lua thread(bool saveit = true); int yield(int nresults = 0) { return lua_yield(L, nresults); } - int yield(Future) throw (GeneralException) __attribute__((noreturn)); + int yield(Future) throw (GeneralException); bool yielded() { return lua_status(L) == LUA_YIELD; } bool resume(int nargs = 0) throw (GeneralException); void showstack(int level = M_INFO); @@ -195,8 +195,8 @@ class Lua { private: void dumpvars_i(IO out, const String & prefix, int idx); void dumpvars_r(IO out, int idx, int depth = 0) throw (GeneralException); - bool resumeC(); - bool yieldC() throw (GeneralException); + bool resumeC(int & nargs); + void yieldC() throw (GeneralException); void processException(GeneralException & e); lua_State * L; diff --git a/includes/Task.h b/includes/Task.h index 940afe3..a8702b4 100644 --- a/includes/Task.h +++ b/includes/Task.h @@ -287,7 +287,6 @@ class Future { friend class Lua; func_t m_func; Events::BaseEvent * m_evt = NULL; - bool m_ranOnce = false; }; template @@ -298,7 +297,6 @@ R Future::get() { Task::operationYield(m_evt, Task::INTERRUPTIBLE); m_evt = NULL; try { - m_ranOnce = true; r = m_func(); return r; } @@ -316,7 +314,6 @@ void Future::run() { Task::operationYield(m_evt, Task::INTERRUPTIBLE); m_evt = NULL; try { - m_ranOnce = true; m_func(); return; } diff --git a/src/BLua.cc b/src/BLua.cc index bed33a0..247a8ab 100644 --- a/src/BLua.cc +++ b/src/BLua.cc @@ -98,7 +98,7 @@ int Balau::LuaStatics::dumpvars(lua_State * __L) { L.dumpvars(h, prefix); Task * t = new CopyTask(s, h); Events::TaskEvent * evt = new Events::TaskEvent(t); - L.yield(Future([evt, s]() mutable { + return L.yield(Future([evt, s]() mutable { for (;;) { if (evt->gotSignal()) { evt->ack(); @@ -767,19 +767,15 @@ Balau::Lua Balau::Lua::thread(bool saveit) { bool Balau::Lua::resume(int nargs) throw (GeneralException) { int r; - if (resumeC()) { - if (yielded()) { - yieldC(); - return true; - } else { - return false; - } - } + if (resumeC(nargs)) + yieldC(); r = lua_resume(L, nargs); - if (r == LUA_YIELD) - return yieldC(); + if (r == LUA_YIELD) { + yieldC(); + return true; + } if (r == 0) return false; @@ -805,7 +801,7 @@ bool Balau::Lua::resume(int nargs) throw (GeneralException) { } } -bool Balau::Lua::resumeC() { +bool Balau::Lua::resumeC(int & nargs) { if (!yielded()) return false; @@ -829,9 +825,6 @@ bool Balau::Lua::resumeC() { delete p; pop(); - int nargs = 0; - bool yieldedAgain = false; - try { nargs = f.get(); } @@ -843,50 +836,54 @@ bool Balau::Lua::resumeC() { p->m_evt = e.getEvent(); push((void *) p); push((void *) &s_signature); - yieldedAgain = true; } catch (LuaYield & y) { Future * p = new Future(y.m_f); push((void *) p); push((void *) &s_signature); - yieldedAgain = true; } catch (Balau::GeneralException & e) { processException(e); } - if (!yieldedAgain) - resume(nargs); + return true; } int Balau::Lua::yield(Future f) throw (GeneralException) { - throw LuaYield(f); + int r = 0; + try { + r = f.get(); + } + catch (EAgain & e) { + LuaYield y(f); + y.m_f.m_evt = e.getEvent(); + throw y; + } + return r; } -bool Balau::Lua::yieldC() throw (GeneralException) { +void Balau::Lua::yieldC() throw (GeneralException) { if (!yielded()) - return true; + return; if (gettop() < 2) - return true; + return; if (!islightuserdata(-1)) - return true; + return; if (!islightuserdata(-2)) - return true; + return; void * s = touserdata(); if (s != &s_signature) - return true; + return; Future * p = (Future *) touserdata(-2); - if (p->m_ranOnce) - Task::operationYield(p->m_evt, Task::STACKLESS); - - resumeC(); - return yieldC(); + IAssert(p->m_evt, "There should always be an event here at that point..."); + Task::operationYield(p->m_evt, Task::STACKLESS); + IAssert(false, "That point shouldn't be reached."); } void Balau::Lua::processException(GeneralException & e) { diff --git a/tests/test-Lua.cc b/tests/test-Lua.cc index ed6e754..9337d35 100644 --- a/tests/test-Lua.cc +++ b/tests/test-Lua.cc @@ -115,7 +115,7 @@ int sLua_ObjectTest::ObjectTest_proceed_static(Lua & L, int n, int caller) throw break; case OBJECTTEST_YIELDTEST: - L.yield(Future([=]() mutable { + return L.yield(Future([=]() mutable { int y = L.tonumber(); L.pop(); L.push((lua_Number) y + 1); -- cgit v1.2.3