From 8bb55a25830c3f7d2c67c8571786b6806fb8f515 Mon Sep 17 00:00:00 2001 From: "Nicolas \"Pixel\" Noble" Date: Thu, 25 Jul 2013 10:58:33 +0200 Subject: Lua now properly yields when an operation throws EAgain. --- includes/BLua.h | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) (limited to 'includes') diff --git a/includes/BLua.h b/includes/BLua.h index bf7caae..e11c3fb 100644 --- a/includes/BLua.h +++ b/includes/BLua.h @@ -1,5 +1,7 @@ #pragma once +#include + extern "C" { #include #include @@ -7,6 +9,7 @@ extern "C" { #include #include +#include namespace Balau { @@ -271,8 +274,16 @@ template T * LuaObjectFactory::getMe(Lua & L, int idx) { return L.recast(idx); } class LuaHelpersBase { + public: + static bool resume(Lua & L); + static Events::BaseEvent * getEvent(Lua & L); protected: static void validate(const lua_functypes_t & entry, bool method, int n, Lua & L, const char * className); + static void pushContext(Lua & L, std::function context, Events::BaseEvent * evt); + private: + LuaHelpersBase(std::function context, Events::BaseEvent * evt) : m_context(context), m_evt(evt) { } + std::function m_context; + Events::BaseEvent * m_evt; }; template @@ -280,6 +291,39 @@ class LuaHelpers : public LuaHelpersBase { public: static int method_multiplex(int caller, lua_State * __L, int (*proceed)(Lua & L, int n, T * obj, int caller), int (*proceed_static)(Lua & L, int n, int caller), lua_functypes_t * tab, bool method) { Lua L(__L); + return method_multiplex(caller, L, proceed, proceed_static, tab, method); + } + + private: + static int method_multiplex(int caller, Lua & L, int (*proceed)(Lua & L, int n, T * obj, int caller), int (*proceed_static)(Lua & L, int n, int caller), lua_functypes_t * tab, bool method) { + int r; + + try { + r = method_multiplex_internal(caller, L, proceed, proceed_static, tab, method); + } + catch (EAgain e) { + pushContext(L, [caller, proceed, proceed_static, tab, method](Lua & L) -> int { return method_multiplex_resume(caller, L, proceed, proceed_static, tab, method); }, e.getEvent()); + r = L.yield(L.gettop()); + } + + return r; + } + + static int method_multiplex_resume(int caller, Lua & L, int (*proceed)(Lua & L, int n, T * obj, int caller), int (*proceed_static)(Lua & L, int n, int caller), lua_functypes_t * tab, bool method) { + int r; + + try { + r = method_multiplex_internal(caller, L, proceed, proceed_static, tab, method); + } + catch (EAgain e) { + pushContext(L, [caller, proceed, proceed_static, tab, method](Lua & L) -> int { return method_multiplex_resume(caller, L, proceed, proceed_static, tab, method); }, e.getEvent()); + r = -1; + } + + return r; + } + + static int method_multiplex_internal(int caller, Lua & L, int (*proceed)(Lua & L, int n, T * obj, int caller), int (*proceed_static)(Lua & L, int n, int caller), lua_functypes_t * tab, bool method) { int add = method ? 1 : 0; int n = L.gettop() - add; T * obj = 0; -- cgit v1.2.3