diff --git a/ElunaTemplate.h b/ElunaTemplate.h index b2dc902..d5f61b0 100644 --- a/ElunaTemplate.h +++ b/ElunaTemplate.h @@ -67,7 +67,7 @@ public: // Get wrapped object pointer void* GetObj() const { return object; } // Returns whether the object is valid or not - bool IsValid() const { return _isvalid; } + bool IsValid() const { return !callstackid || callstackid == sEluna->GetCallstackId(); } // Returns whether the object can be invalidated or not bool CanInvalidate() const { return _invalidate; } // Returns pointer to the wrapped object's type name @@ -84,7 +84,13 @@ public: void SetValid(bool valid) { ASSERT(!valid || (valid && object)); - _isvalid = valid; + if (valid) + if (CanInvalidate()) + callstackid = sEluna->GetCallstackId(); + else + callstackid = 0; + else + callstackid = 1; } // Sets whether the pointer will be invalidated at end of calls void SetValidation(bool invalidate) @@ -95,11 +101,11 @@ public: void Invalidate() { if (CanInvalidate()) - _isvalid = false; + callstackid = 1; } private: - bool _isvalid; + uint64 callstackid; bool _invalidate; void* object; const char* type_name; @@ -253,31 +259,11 @@ public: return 1; } - void* obj_voidptr = static_cast(const_cast(obj)); - - lua_pushstring(L, ELUNA_OBJECT_STORE); - lua_rawget(L, LUA_REGISTRYINDEX); - ASSERT(lua_istable(L, -1)); - lua_pushlightuserdata(L, obj_voidptr); - lua_rawget(L, -2); - if (ElunaObject* elunaObj = Eluna::CHECKTYPE(L, -1, tname, false)) - { - // set userdata valid - elunaObj->SetValid(true); - - // remove userdata_table, leave userdata - lua_remove(L, -2); - return 1; - } - lua_pop(L, 1); - // left userdata_table in stack - // Create new userdata ElunaObject** ptrHold = static_cast(lua_newuserdata(L, sizeof(ElunaObject*))); if (!ptrHold) { ELUNA_LOG_ERROR("%s could not create new userdata", tname); - lua_pop(L, 2); lua_pushnil(L); return 1; } @@ -289,16 +275,11 @@ public: if (!lua_istable(L, -1)) { ELUNA_LOG_ERROR("%s missing metatable", tname); - lua_pop(L, 3); + lua_pop(L, 2); lua_pushnil(L); return 1; } lua_setmetatable(L, -2); - - lua_pushlightuserdata(L, obj_voidptr); - lua_pushvalue(L, -2); - lua_rawset(L, -4); - lua_remove(L, -2); return 1; } @@ -396,7 +377,7 @@ public: }; template -ElunaObject::ElunaObject(T * obj, bool manageMemory) : _isvalid(false), _invalidate(!manageMemory), object(obj), type_name(ElunaTemplate::tname) +ElunaObject::ElunaObject(T * obj, bool manageMemory) : callstackid(1), _invalidate(!manageMemory), object(obj), type_name(ElunaTemplate::tname) { SetValid(true); } diff --git a/LuaEngine.cpp b/LuaEngine.cpp index 7dd4e3e..c8ae8c4 100644 --- a/LuaEngine.cpp +++ b/LuaEngine.cpp @@ -232,14 +232,6 @@ void Eluna::OpenLua() // Register methods and functions RegisterFunctions(this); - // Create hidden table with weak values - lua_newtable(L); - lua_newtable(L); - lua_pushstring(L, "v"); - lua_setfield(L, -2, "__mode"); - lua_setmetatable(L, -2); - lua_setfield(L, LUA_REGISTRYINDEX, ELUNA_OBJECT_STORE); - // Set lua require folder paths (scripts folder structure) lua_getglobal(L, "package"); lua_pushstring(L, lua_requirepath.c_str()); @@ -526,18 +518,8 @@ void Eluna::RunScripts() void Eluna::InvalidateObjects() { - lua_pushstring(L, ELUNA_OBJECT_STORE); - lua_rawget(L, LUA_REGISTRYINDEX); - ASSERT(lua_istable(L, -1)); - - lua_pushnil(L); - while (lua_next(L, -2)) - { - if (ElunaObject* elunaObj = CHECKOBJ(L, -1, false)) - elunaObj->Invalidate(); - lua_pop(L, 1); - } - lua_pop(L, 1); + ++callstackid; + ASSERT(callstackid, "Callstackid overflow"); } void Eluna::Report(lua_State* _L) diff --git a/LuaEngine.h b/LuaEngine.h index 79ab5e0..a45ae17 100644 --- a/LuaEngine.h +++ b/LuaEngine.h @@ -111,7 +111,6 @@ struct LuaScript std::string modulepath; }; -#define ELUNA_OBJECT_STORE "Eluna Object Store" #define ELUNA_STATE_PTR "Eluna State Ptr" #define LOCK_ELUNA Eluna::Guard __guard(Eluna::GetLock()) @@ -140,6 +139,14 @@ private: // lua path variable for require() function static std::string lua_requirepath; + // A counter for lua event stacks that occur (see event_level). + // This is used to determine whether an object belongs to the current call stack or not. + // 0 is reserved for always belonging to the call stack + // 1 is reserved for a non valid callstackid + uint64 callstackid = 2; + // A counter for the amount of nested events. When the event_level + // reaches 0 we are about to return back to C++. At this point the + // objects used during the event stack are invalidated. uint32 event_level; // When a hook pushes arguments to be passed to event handlers, // this is used to keep track of how many arguments were pushed. @@ -312,6 +319,7 @@ public: bool ShouldReload() const { return reload; } bool IsEnabled() const { return enabled && IsInitialized(); } bool HasLuaState() const { return L != NULL; } + uint64 GetCallstackId() const { return callstackid; } int Register(lua_State* L, uint8 reg, uint32 entry, uint64 guid, uint32 instanceId, uint32 event_id, int functionRef, uint32 shots); // Checks