From ed8edf065c25798f2402996669029e8e49cc4823 Mon Sep 17 00:00:00 2001 From: Patman64 Date: Fri, 19 Dec 2014 00:46:50 -0500 Subject: [PATCH] Fix bug in previous commit that caused temporary bindings to die early. Instead of decrementing all their counters every time an event occurs, only the counters of the bindings being executed will be decremented. `_LuaTemporariesDied` is a small optimization to prevent unnecessary calls to `UpdateTemporaryBindings`. It will only be called when a temporary binding has run out of shots and needs to be cleaned up. --- ElunaBinding.h | 48 +++++++++++++++++++++++------------------------- HookMgr.cpp | 25 ++++++++++++++++++++++--- 2 files changed, 45 insertions(+), 28 deletions(-) diff --git a/ElunaBinding.h b/ElunaBinding.h index ba53fb1..693afc2 100644 --- a/ElunaBinding.h +++ b/ElunaBinding.h @@ -20,8 +20,19 @@ extern "C" class ElunaBind { public: - typedef std::pair FunctionRefCounterPair; // (function reference, remaining calls counter) - typedef std::vector FunctionRefVector; + struct Binding + { + int functionReference; + bool isTemporary; + uint32 remainingShots; + + Binding(int funcRef, uint32 shots) : + functionReference(funcRef), + isTemporary(shots != 0), + remainingShots(shots) + {} + }; + typedef std::vector FunctionRefVector; typedef UNORDERED_MAP EventToFunctionsMap; Eluna& E; @@ -57,7 +68,7 @@ public: for (EventToFunctionsMap::iterator itr = Bindings.begin(); itr != Bindings.end(); ++itr) { for (FunctionRefVector::iterator it = itr->second.begin(); it != itr->second.end(); ++it) - luaL_unref(E.L, LUA_REGISTRYINDEX, (*it).first); + luaL_unref(E.L, LUA_REGISTRYINDEX, (*it).functionReference); itr->second.clear(); } Bindings.clear(); @@ -69,17 +80,10 @@ public: { for (FunctionRefVector::iterator it = itr->second.begin(); it != itr->second.end();) { - uint32 counter = (*it).second; - - if (counter > 1) + Binding &b = (*it); + if (b.isTemporary && b.remainingShots == 0) { - counter--; - (*it).second = counter; - it++; - } - else if (counter == 1) - { - luaL_unref(E.L, LUA_REGISTRYINDEX, (*it).first); + luaL_unref(E.L, LUA_REGISTRYINDEX, b.functionReference); it = itr->second.erase(it); } else @@ -102,7 +106,7 @@ public: void Insert(int eventId, int funcRef, uint32 shots) // Inserts a new registered event { - Bindings[eventId].push_back(std::make_pair(funcRef, shots)); + Bindings[eventId].push_back(Binding(funcRef, shots)); } // Checks if there are events for ID @@ -136,7 +140,7 @@ public: for (EventToFunctionsMap::iterator it = itr->second.begin(); it != itr->second.end(); ++it) { for (FunctionRefVector::iterator i = it->second.begin(); i != it->second.end(); ++i) - luaL_unref(E.L, LUA_REGISTRYINDEX, (*i).first); + luaL_unref(E.L, LUA_REGISTRYINDEX, (*i).functionReference); it->second.clear(); } itr->second.clear(); @@ -152,16 +156,10 @@ public: { for (FunctionRefVector::iterator i = it->second.begin(); i != it->second.end();) { - uint32 counter = (*i).second; - if (counter > 1) + Binding &b = (*i); + if (b.isTemporary && b.remainingShots == 0) { - counter--; - (*i).second = counter; - i++; - } - else if (counter == 1) - { - luaL_unref(E.L, LUA_REGISTRYINDEX, (*i).first); + luaL_unref(E.L, LUA_REGISTRYINDEX, b.functionReference); i = it->second.erase(i); } else @@ -195,7 +193,7 @@ public: void Insert(uint32 entryId, int eventId, int funcRef, uint32 shots) // Inserts a new registered event { - Bindings[entryId][eventId].push_back(std::make_pair(funcRef, shots)); + Bindings[entryId][eventId].push_back(Binding(funcRef, shots)); } // Returns true if the entry has registered binds diff --git a/HookMgr.cpp b/HookMgr.cpp index 292ab84..50772d7 100644 --- a/HookMgr.cpp +++ b/HookMgr.cpp @@ -51,8 +51,17 @@ using namespace HookMgr; const char* _LuaBindType = this->BINDMAP->groupName; \ uint32 _LuaEvent = EVENT; \ int _LuaStackTop = lua_gettop(L); \ + bool _LuaTemporariesDied = false; \ for (size_t i = 0; i < this->BINDMAP->Bindings[_LuaEvent].size(); ++i) \ - lua_rawgeti(L, LUA_REGISTRYINDEX, (this->BINDMAP->Bindings[_LuaEvent][i].first)); \ + { \ + if (this->BINDMAP->Bindings[_LuaEvent][i].isTemporary) \ + { \ + this->BINDMAP->Bindings[_LuaEvent][i].remainingShots--; \ + if (this->BINDMAP->Bindings[_LuaEvent][i].remainingShots == 0) \ + _LuaTemporariesDied = true; \ + } \ + lua_rawgeti(L, LUA_REGISTRYINDEX, (this->BINDMAP->Bindings[_LuaEvent][i].functionReference)); \ + } \ int _LuaFuncTop = lua_gettop(L); \ int _LuaFuncCount = _LuaFuncTop-_LuaStackTop; \ Eluna::Push(L, _LuaEvent); @@ -86,8 +95,17 @@ using namespace HookMgr; const char* _LuaBindType = _LuaBind->groupName; \ uint32 _LuaEvent = EVENT; \ int _LuaStackTop = lua_gettop(L); \ + bool _LuaTemporariesDied = false; \ for (size_t i = 0; i < this->BINDMAP->Bindings[ENTRY][_LuaEvent].size(); ++i) \ - lua_rawgeti(L, LUA_REGISTRYINDEX, (this->BINDMAP->Bindings[ENTRY][_LuaEvent][i].first)); \ + { \ + if (this->BINDMAP->Bindings[ENTRY][_LuaEvent][i].isTemporary) \ + { \ + this->BINDMAP->Bindings[ENTRY][_LuaEvent][i].remainingShots--; \ + if (this->BINDMAP->Bindings[ENTRY][_LuaEvent][i].remainingShots == 0) \ + _LuaTemporariesDied = true; \ + } \ + lua_rawgeti(L, LUA_REGISTRYINDEX, (this->BINDMAP->Bindings[ENTRY][_LuaEvent][i].functionReference)); \ + } \ int _LuaFuncTop = lua_gettop(L); \ int _LuaFuncCount = _LuaFuncTop-_LuaStackTop; \ Eluna::Push(L, _LuaEvent); @@ -123,7 +141,8 @@ using namespace HookMgr; ELUNA_LOG_ERROR("[Eluna]: Ending event %u for %s, stack top was %i and was supposed to be between %i and %i. Report to devs", _LuaEvent, _LuaBindType, lua_gettop(L), _LuaStackTop, _LuaStackTop + _LuaFuncCount * _LuaReturnValues); \ } \ lua_settop(L, _LuaStackTop); \ - _LuaBind->UpdateTemporaryBindings(); \ + if (_LuaTemporariesDied) \ + _LuaBind->UpdateTemporaryBindings(); \ if (!this->event_level) \ this->InvalidateObjects(); // Invalidate objects on outermost hook call