git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@7477 c06c8d41-db1a-0410-9941-cceddc491573
JPFT2IRK2624J6QS72PSRMPYJQRIWSV567GFLC2JOJD7246XHOTAC
EJ4GIPFSSQCQASUMRF4CR2WPUQOTEHFRGLOYEZ7BH6YEMIR6DN4QC
GQL5SIGBHLU3FMCE54XVGLRY5AZHRM6DUEB722REA2DPLGJSN6EQC
7Y5HSDFKA5TPLS2TWTRFMQVX6UXUDHXU5MUMXQSDFAIY4THQ3BIQC
YE7M665QKDGI7Y5WMERCWJNDZ4FUZ6GRUCK4E6GZH4SWCUM6RWLAC
SDLKLUNFGVKDS55DDJZCBAVIB7NL3RRYPTACAY65SCUQKV6APFSAC
Q2FZIIGQECGP2FKKWLGDBBQVGCFZ4JTY53PFPJP6X7YKC23AQGFQC
JDPJS5SNW6ZTY5DYV5QUBG2WVJ45FJ4CAOK6KDJKPEI2HLIHVLRQC
W52PCSHX72WAMWKG6L4BPUBVMO6E72KYYBNKAA7554KNOTY6V7WQC
// Remove the Lua marker table from the registry.
if (initialised)
{
lua_pushlightuserdata(dlua, this);
lua_pushnil(dlua);
lua_settable(dlua, LUA_REGISTRYINDEX);
}
// First save the unmarshall Lua function.
lua_pushlightuserdata(dlua, const_cast<map_lua_marker*>(this));
lua_gettable(dlua, LUA_REGISTRYINDEX);
return (lua_istable(dlua, -1));
if (marker_table.get())
{
marker_table->push();
return (lua_istable(dlua, -1));
}
else
{
return (false);
}
class lua_shutdown_listener
{
public:
virtual void shutdown(CLua &lua) = 0;
};
// A convenience class to keep a reference to a lua object on the stack.
// This is useful to hang on to things that cannot be directly retrieved by
// C++ code, such as Lua function references.
class lua_datum : public lua_shutdown_listener
{
public:
lua_datum(CLua &lua, int stackpos = -1, bool pop = true);
lua_datum(const lua_datum &other);
void shutdown(CLua &lua);
// 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);
}
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);
}
/////////////////////////////////////////////////////////////////////
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);
}
}