From 5fb06d7e787610c4a26f083d4c9ecbe20d065621 Mon Sep 17 00:00:00 2001 From: Ilari Liusvaara Date: Fri, 21 Jun 2013 00:25:04 +0300 Subject: [PATCH] Fix Lua functions when called in coroutines --- include/library/luabase.hpp | 26 ++++++++++++++++++++------ src/library/luabase.cpp | 22 +++++++++++++++++++++- 2 files changed, 41 insertions(+), 7 deletions(-) diff --git a/include/library/luabase.hpp b/include/library/luabase.hpp index 1476aff8..9e146167 100644 --- a/include/library/luabase.hpp +++ b/include/library/luabase.hpp @@ -172,6 +172,10 @@ public: */ lua_state() throw(std::bad_alloc); /** + * Create a new state with specified master state. + */ + lua_state(lua_state& _master, lua_State* L); +/** * Destroy a state. */ ~lua_state() throw(); @@ -182,6 +186,14 @@ public: */ lua_State* handle() { return lua_handle; } /** + * Get the master state. + */ + lua_state& get_master() { return master ? *master : *this; } +/** + * Set the internal state object. + */ + void handle(lua_State* l) { lua_handle = l; } +/** * Set OOM handler. */ void set_oom_handler(void (*oom)()) { oom_handler = oom ? oom : builtin_oom; } @@ -353,6 +365,7 @@ private: static void builtin_oom(); static void* builtin_alloc(void* user, void* old, size_t olds, size_t news); void (*oom_handler)(); + lua_state* master; lua_State* lua_handle; std::map functions; lua_state(lua_state&); @@ -371,11 +384,11 @@ template struct lua_obj_pin * Parameter _object: The object to pin. */ lua_obj_pin(lua_state& _state, T* _object) - : state(_state) + : state(_state.get_master()) { - state.pushlightuserdata(this); - state.pushvalue(-2); - state.rawset(LUA_REGISTRYINDEX); + _state.pushlightuserdata(this); + _state.pushvalue(-2); + _state.rawset(LUA_REGISTRYINDEX); obj = _object; } /** @@ -450,8 +463,9 @@ template class lua_class { try { lua_class_bind_data* b = (lua_class_bind_data*)lua_touserdata(LS, lua_upvalueindex(1)); - T* p = lua_class::get(*b->state, 1, b->fname); - return (p->*(b->fn))(*b->state); + lua_state L(*b->state, LS); + T* p = lua_class::get(L, 1, b->fname); + return (p->*(b->fn))(L); } catch(std::exception& e) { std::string err = e.what(); lua_pushlstring(LS, err.c_str(), err.length()); diff --git a/src/library/luabase.cpp b/src/library/luabase.cpp index 1ece70d5..f826ab49 100644 --- a/src/library/luabase.cpp +++ b/src/library/luabase.cpp @@ -10,8 +10,9 @@ namespace void* ptr = lua_touserdata(L, lua_upvalueindex(1)); lua_state* state = reinterpret_cast(lua_touserdata(L, lua_upvalueindex(2))); lua_function* f = reinterpret_cast(ptr); + lua_state _L(*state, L); try { - return f->invoke(*state); + return f->invoke(_L); } catch(std::exception& e) { lua_pushfstring(L, "%s", e.what()); lua_error(L); @@ -84,13 +85,22 @@ namespace lua_state::lua_state() throw(std::bad_alloc) { + master = NULL; lua_handle = NULL; oom_handler = builtin_oom; regqueue_t::do_ready(*this, true); } +lua_state::lua_state(lua_state& _master, lua_State* L) +{ + master = &_master; + lua_handle = L; +} + lua_state::~lua_state() throw() { + if(master) + return; regqueue_t::do_ready(*this, false); if(lua_handle) lua_close(lua_handle); @@ -128,6 +138,8 @@ lua_function::~lua_function() throw() void lua_state::reset() throw(std::bad_alloc, std::runtime_error) { + if(master) + return master->reset(); if(lua_handle) { lua_State* tmp = lua_newstate(lua_state::builtin_alloc, this); if(!tmp) @@ -145,6 +157,8 @@ void lua_state::reset() throw(std::bad_alloc, std::runtime_error) void lua_state::deinit() throw() { + if(master) + return master->deinit(); if(lua_handle) lua_close(lua_handle); lua_handle = NULL; @@ -152,6 +166,8 @@ void lua_state::deinit() throw() void lua_state::do_register(const std::string& name, lua_function& fun) throw(std::bad_alloc) { + if(master) + return master->do_register(name, fun); functions[name] = &fun; if(lua_handle) register_lua_function(*this, name, fun); @@ -159,11 +175,15 @@ void lua_state::do_register(const std::string& name, lua_function& fun) throw(st void lua_state::do_unregister(const std::string& name) throw() { + if(master) + return master->do_unregister(name); functions.erase(name); } bool lua_state::do_once(void* key) { + if(master) + return master->do_once(key); pushlightuserdata(key); rawget(LUA_REGISTRYINDEX); if(type(-1) == LUA_TNIL) { -- 2.11.4.GIT