diff options
author | dshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573> | 2008-11-18 20:07:42 +0000 |
---|---|---|
committer | dshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573> | 2008-11-18 20:07:42 +0000 |
commit | a06523dd0f46c2536e070e58c9288419bbcbf22e (patch) | |
tree | 1c49523bf609b18ee5e6a529e18e34438b62bfad /crawl-ref/source/clua.cc | |
parent | ff00ffd9da330a94bd282bcc127157672e589a9a (diff) | |
download | crawl-ref-a06523dd0f46c2536e070e58c9288419bbcbf22e.tar.gz crawl-ref-a06523dd0f46c2536e070e58c9288419bbcbf22e.zip |
Added lua_datum to wrap the common task of retaining references to Lua objects in the Lua registry.
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@7477 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'crawl-ref/source/clua.cc')
-rw-r--r-- | crawl-ref/source/clua.cc | 84 |
1 files changed, 82 insertions, 2 deletions
diff --git a/crawl-ref/source/clua.cc b/crawl-ref/source/clua.cc index 477d772a40..9fa1a79a9a 100644 --- a/crawl-ref/source/clua.cc +++ b/crawl-ref/source/clua.cc @@ -84,12 +84,17 @@ CLua::CLua(bool managed) CLua::~CLua() { + // Copy the listener vector, because listeners may remove + // themselves from the listener list when we notify them of a + // shutdown. + const std::vector<lua_shutdown_listener*> slisteners = shutdown_listeners; + for (int i = 0, size = slisteners.size(); i < size; ++i) + slisteners[i]->shutdown(*this); shutting_down = true; if (_state) lua_close(_state); } -// This has the disadvantage of repeatedly trying init_lua if it fails. lua_State *CLua::state() { if (!_state) @@ -597,7 +602,7 @@ void CLua::init_lua() _state = managed_vm? lua_newstate(_clua_allocator, this) : luaL_newstate(); if (!_state) - return; + end(1, false, "Unable to create Lua state."); lua_stack_cleaner clean(_state); @@ -658,6 +663,22 @@ void CLua::load_cmacro() execfile("clua/macro.lua", true, true); } +void CLua::add_shutdown_listener(lua_shutdown_listener *listener) +{ + if (std::find(shutdown_listeners.begin(), shutdown_listeners.end(), + listener) == shutdown_listeners.end()) + shutdown_listeners.push_back(listener); +} + +void CLua::remove_shutdown_listener(lua_shutdown_listener *listener) +{ + std::vector<lua_shutdown_listener*>::iterator i = + std::find(shutdown_listeners.begin(), shutdown_listeners.end(), + listener); + if (i != shutdown_listeners.end()) + shutdown_listeners.erase(i); +} + ///////////////////////////////////////////////////////////////////// static void _clua_register_metatable(lua_State *ls, const char *tn, @@ -2849,3 +2870,62 @@ std::string quote_lua_string(const std::string &s) { return replace_all_of(replace_all_of(s, "\\", "\\\\"), "\"", "\\\""); } + +///////////////////////////////////////////////////////////////////// + +lua_datum::lua_datum(CLua &_lua, int stackpos, bool pop) + : need_cleanup(true), lua(_lua) +{ + // Store the datum in the registry indexed by "this". + lua_pushvalue(lua, stackpos); + lua_pushlightuserdata(lua, this); + // Move the key (this) before the value. + lua_insert(lua, -2); + lua_settable(lua, LUA_REGISTRYINDEX); + + if (pop && stackpos < 0) + lua_pop(lua, -stackpos); + + lua.add_shutdown_listener(this); +} + +lua_datum::lua_datum(const lua_datum &o) + : need_cleanup(true), lua(o.lua) +{ + lua_pushlightuserdata(lua, this); + o.push(); + lua_settable(lua, LUA_REGISTRYINDEX); + + lua.add_shutdown_listener(this); +} + +void lua_datum::push() const +{ + lua_pushlightuserdata(lua, const_cast<lua_datum*>(this)); + lua_gettable(lua, LUA_REGISTRYINDEX); + + // The value we saved is now on top of the Lua stack. +} + +lua_datum::~lua_datum() +{ + cleanup(); +} + +void lua_datum::shutdown(CLua &) +{ + cleanup(); +} + +void lua_datum::cleanup() +{ + if (need_cleanup) + { + need_cleanup = false; + lua.remove_shutdown_listener(this); + + lua_pushlightuserdata(lua, this); + lua_pushnil(lua); + lua_settable(lua, LUA_REGISTRYINDEX); + } +} |