mirror of
https://github.com/azerothcore/mod-ale
synced 2025-11-29 15:38:17 +08:00
Fix inefficient InvalidateObjects
This commit is contained in:
@@ -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<void*>(const_cast<T*>(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<ElunaObject**>(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<typename T>
|
||||
ElunaObject::ElunaObject(T * obj, bool manageMemory) : _isvalid(false), _invalidate(!manageMemory), object(obj), type_name(ElunaTemplate<T>::tname)
|
||||
ElunaObject::ElunaObject(T * obj, bool manageMemory) : callstackid(1), _invalidate(!manageMemory), object(obj), type_name(ElunaTemplate<T>::tname)
|
||||
{
|
||||
SetValid(true);
|
||||
}
|
||||
|
||||
@@ -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<ElunaObject>(L, -1, false))
|
||||
elunaObj->Invalidate();
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
++callstackid;
|
||||
ASSERT(callstackid, "Callstackid overflow");
|
||||
}
|
||||
|
||||
void Eluna::Report(lua_State* _L)
|
||||
|
||||
10
LuaEngine.h
10
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
|
||||
|
||||
Reference in New Issue
Block a user