From 10a64737b5fb23e47354a158da68a7df2a4e1cd1 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Tue, 25 Oct 2005 20:38:00 +0000 Subject: [PATCH] Added optimizations to the task system Added optimizations to the forward system Fixed some debugger errors --- amxmodx/CForward.h | 4 +- amxmodx/CStack.h | 105 ---------------- amxmodx/CTask.cpp | 60 ++++++--- amxmodx/CTask.h | 4 +- amxmodx/debugger.cpp | 8 ++ amxmodx/modules.cpp | 20 +++ amxmodx/modules.h | 2 + amxmodx/msvc/amxmodx_mm.vcproj | 6 +- amxmodx/natives.cpp | 18 +-- amxmodx/sh_stack.h | 219 +++++++++++++++++++++++++++++++++ 10 files changed, 310 insertions(+), 136 deletions(-) delete mode 100755 amxmodx/CStack.h create mode 100755 amxmodx/sh_stack.h diff --git a/amxmodx/CForward.h b/amxmodx/CForward.h index 759b3959..28ff4d3f 100755 --- a/amxmodx/CForward.h +++ b/amxmodx/CForward.h @@ -46,6 +46,8 @@ #ifndef FORWARD_H #define FORWARD_H +#include "sh_stack.h" + const int FORWARD_MAX_PARAMS = 32; enum ForwardExecType @@ -171,7 +173,7 @@ class CForwardMngr { typedef CVector ForwardVec; typedef CVector SPForwardVec; - typedef CQueue FreeSPVec; // Free SP Forwards + typedef CStack FreeSPVec; // Free SP Forwards ForwardVec m_Forwards; diff --git a/amxmodx/CStack.h b/amxmodx/CStack.h deleted file mode 100755 index e509924f..00000000 --- a/amxmodx/CStack.h +++ /dev/null @@ -1,105 +0,0 @@ -/* AMX Mod X -* -* by the AMX Mod X Development Team -* originally developed by OLO -* -* -* This program is free software; you can redistribute it and/or modify it -* under the terms of the GNU General Public License as published by the -* Free Software Foundation; either version 2 of the License, or (at -* your option) any later version. -* -* This program is distributed in the hope that it will be useful, but -* WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -* General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software Foundation, -* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -* -* In addition, as a special exception, the author gives permission to -* link the code of this program with the Half-Life Game Engine ("HL -* Engine") and Modified Game Libraries ("MODs") developed by Valve, -* L.L.C ("Valve"). You must obey the GNU General Public License in all -* respects for all of the code used other than the HL Engine and MODs -* from Valve. If you modify this file, you may extend this exception -* to your version of the file, but you are not obligated to do so. If -* you do not wish to do so, delete this exception statement from your -* version. -*/ - -//by David "BAILOPAN" Anderson -#ifndef _INCLUDE_CSTACK_H -#define _INCLUDE_CSTACK_H - -template -class CStack -{ -public: - struct CStackItem - { - public: - T item; - CStackItem *prev; - }; - -public: - CStack() - { - mSize = 0; - mStack = NULL; - } - - ~CStack() - { - CStackItem *p, *t; - p = mStack; - - while (p) - { - t = p->prev; - delete p; - p = t; - } - - mStack = NULL; - } - - bool empty() - { - return (mSize == 0); - } - - void push(const T & v) - { - CStackItem *p = new CStackItem; - p->item = v; - p->prev = mStack; - mStack = p; - mSize++; - } - - void pop() - { - CStackItem *p = mStack; - mStack = p->prev; - delete p; - mSize--; - } - - T & top() - { - return mStack->item; - } - - size_t size() - { - return mSize; - } -private: - CStackItem *mStack; - size_t mSize; -}; - -#endif //_INCLUDE_CQUEUE_H diff --git a/amxmodx/CTask.cpp b/amxmodx/CTask.cpp index 2cd33de9..7e266769 100755 --- a/amxmodx/CTask.cpp +++ b/amxmodx/CTask.cpp @@ -31,6 +31,9 @@ #include "amxmodx.h" #include "CTask.h" +#include "sh_stack.h" + +CStack *g_FreeTasks; /*********************** CTask ***********************/ @@ -73,12 +76,19 @@ void CTaskMngr::CTask::set(CPluginMngr::CPlugin *pPlugin, int iFunc, int iFlags, if (iParamsLen) { m_iParamLen = iParamsLen + 1; - m_pParams = new cell[m_iParamLen]; + if (m_ParamSize < m_iParamLen) + { + m_ParamSize = m_iParamLen; + cell *temp = new cell[m_ParamSize]; + memset(temp, 0, sizeof(cell) * m_ParamSize); + if (m_pParams != NULL) + delete [] m_pParams; + m_pParams = temp; + } memcpy(m_pParams, pParams, sizeof(cell)*iParamsLen); m_pParams[iParamsLen] = 0; } else { m_iParamLen = 0; - m_pParams = NULL; } } @@ -92,11 +102,7 @@ void CTaskMngr::CTask::clear() m_iFunc = -1; } - if (m_pParams) - { - delete [] m_pParams; - m_pParams = NULL; - } + m_iParamLen = 0; m_pPlugin = NULL; m_iId = 0; @@ -106,6 +112,7 @@ void CTaskMngr::CTask::clear() m_bLoop = false; m_bAfterStart = false; m_bBeforeEnd = false; + m_iParamLen = 0; m_fNextExecTime = 0.0f; } @@ -174,6 +181,7 @@ void CTaskMngr::CTask::executeIfRequired(float fCurrentTime, float fTimeLimit, f if (done) { clear(); + g_FreeTasks->push(this); } else { m_fNextExecTime += m_fBase; } @@ -197,12 +205,19 @@ CTaskMngr::CTask::CTask() m_fNextExecTime = 0.0f; m_iParamLen = 0; + m_ParamSize = 0; m_pParams = NULL; } CTaskMngr::CTask::~CTask() { clear(); + + if (m_pParams) + { + delete [] m_pParams; + m_pParams = NULL; + } } /*********************** CTaskMngr ***********************/ @@ -212,11 +227,17 @@ CTaskMngr::CTaskMngr() m_pTmr_CurrentTime = NULL; m_pTmr_TimeLimit = NULL; m_pTmr_TimeLeft = NULL; + + g_FreeTasks = new CStack(); } CTaskMngr::~CTaskMngr() { - clear(); + while (!g_FreeTasks->empty()) + g_FreeTasks->pop(); + delete g_FreeTasks; + + m_Tasks.clear(); } void CTaskMngr::registerTimers(float *pCurrentTime, float *pTimeLimit, float *pTimeLeft) @@ -229,19 +250,16 @@ void CTaskMngr::registerTimers(float *pCurrentTime, float *pTimeLimit, float *pT void CTaskMngr::registerTask(CPluginMngr::CPlugin *pPlugin, int iFunc, int iFlags, cell iId, float fBase, int iParamsLen, const cell *pParams, int iRepeat) { // first, search for free tasks - TaskListIter iter = m_Tasks.find(CTaskDescriptor(0, NULL, true)); - - if (iter) + if (!g_FreeTasks->empty()) { // found: reuse it - iter->set(pPlugin, iFunc, iFlags, iId, fBase, iParamsLen, pParams, iRepeat, *m_pTmr_CurrentTime); + CTask *pTmp = g_FreeTasks->front(); + g_FreeTasks->pop(); + pTmp->set(pPlugin, iFunc, iFlags, iId, fBase, iParamsLen, pParams, iRepeat, *m_pTmr_CurrentTime); } else { // not found: make a new one CTask *pTmp = new CTask; - if (!pTmp) - return; - pTmp->set(pPlugin, iFunc, iFlags, iId, fBase, iParamsLen, pParams, iRepeat, *m_pTmr_CurrentTime); m_Tasks.put(pTmp); } @@ -255,7 +273,11 @@ int CTaskMngr::removeTasks(int iId, AMX *pAmx) while (iter) { - iter->clear(); + if (!iter->isFree()) + { + iter->clear(); + g_FreeTasks->push(iter->getTask()); + } ++i; iter = m_Tasks.find(++iter, descriptor); } @@ -297,5 +319,9 @@ void CTaskMngr::startFrame() void CTaskMngr::clear() { - m_Tasks.clear(); + for (TaskListIter iter = m_Tasks.begin(); iter; ++iter) + { + if (!iter->isFree()) + iter->clear(); + } } diff --git a/amxmodx/CTask.h b/amxmodx/CTask.h index 223d42f1..b026cd9e 100755 --- a/amxmodx/CTask.h +++ b/amxmodx/CTask.h @@ -34,7 +34,7 @@ class CTaskMngr { -private: +public: /*** class CTask ***/ class CTask { @@ -52,6 +52,7 @@ private: int m_iParamLen; cell *m_pParams; + cell m_ParamSize; bool m_bFree; // execution @@ -70,6 +71,7 @@ private: void resetNextExecTime(float fCurrentTime); bool shouldRepeat(); + CTask *getTask() { return this; } CTask(); ~CTask(); diff --git a/amxmodx/debugger.cpp b/amxmodx/debugger.cpp index 5837ec00..e0f29ec8 100755 --- a/amxmodx/debugger.cpp +++ b/amxmodx/debugger.cpp @@ -936,6 +936,8 @@ int Handler::HandleModule(const char *module) cell hea_addr, *phys_addr, retval; + DisableDebugHandler(m_pAmx); + //temporarily set prenit m_pAmx->flags |= AMX_FLAG_PRENIT; amx_PushString(m_pAmx, &hea_addr, &phys_addr, module, 0, 0); @@ -943,6 +945,8 @@ int Handler::HandleModule(const char *module) amx_Release(m_pAmx, hea_addr); m_pAmx->flags &= ~AMX_FLAG_PRENIT; + EnableDebugHandler(m_pAmx); + if (err != AMX_ERR_NONE) return 0; @@ -966,6 +970,8 @@ int Handler::HandleNative(const char *native, int index, int trap) if (pDebugger && trap) pDebugger->BeginExec(); + else if (pDebugger && !trap) + DisableDebugHandler(m_pAmx); cell hea_addr, *phys_addr, retval; @@ -1005,6 +1011,8 @@ int Handler::HandleNative(const char *native, int index, int trap) m_pAmx->flags &= ~AMX_FLAG_PRENIT; if (pDebugger && trap) pDebugger->EndExec(); + else if (pDebugger && !trap) + EnableDebugHandler(m_pAmx); amx_Release(m_pAmx, hea_addr); diff --git a/amxmodx/modules.cpp b/amxmodx/modules.cpp index 913c7914..8877b523 100755 --- a/amxmodx/modules.cpp +++ b/amxmodx/modules.cpp @@ -453,6 +453,8 @@ int set_amxnatives(AMX* amx, char error[128]) int idx, err; cell retval; + + DisableDebugHandler(amx); if (amx_FindPublic(amx, "plugin_natives", &idx) == AMX_ERR_NONE) { @@ -463,6 +465,8 @@ int set_amxnatives(AMX* amx, char error[128]) } } + EnableDebugHandler(amx); + amx->flags &= ~(AMX_FLAG_PRENIT); return (amx->error = AMX_ERR_NONE); @@ -1689,6 +1693,22 @@ void *Module_ReqFnptr(const char *funcName) return NULL; } +void DisableDebugHandler(AMX *amx) +{ + amx_SetDebugHook(amx, NULL); +} + +void EnableDebugHandler(AMX *amx) +{ + if (amx->flags & AMX_FLAG_DEBUG) + { + if (amx->userdata[UD_DEBUGGER] != NULL) + { + amx_SetDebugHook(amx, &Debugger::DebugHook); + } + } +} + #if !defined MEMORY_TEST && !defined WIN32 void * ::operator new(size_t size) { diff --git a/amxmodx/modules.h b/amxmodx/modules.h index 9e7a3ae4..a8f55295 100755 --- a/amxmodx/modules.h +++ b/amxmodx/modules.h @@ -50,5 +50,7 @@ int CheckModules(AMX *amx, char error[128]); const char *StrCaseStr(const char *as, const char *bs); +void DisableDebugHandler(AMX *amx); +void EnableDebugHandler(AMX *amx); #endif // __MODULES_H__ diff --git a/amxmodx/msvc/amxmodx_mm.vcproj b/amxmodx/msvc/amxmodx_mm.vcproj index d9b983a9..b84a1dd0 100755 --- a/amxmodx/msvc/amxmodx_mm.vcproj +++ b/amxmodx/msvc/amxmodx_mm.vcproj @@ -786,9 +786,6 @@ - - @@ -825,6 +822,9 @@ + + diff --git a/amxmodx/natives.cpp b/amxmodx/natives.cpp index 52c96103..b9bae033 100755 --- a/amxmodx/natives.cpp +++ b/amxmodx/natives.cpp @@ -29,7 +29,7 @@ */ #include "amxmodx.h" -#include "CStack.h" +#include "sh_stack.h" #include "natives.h" #ifdef __linux__ @@ -146,7 +146,7 @@ static cell AMX_NATIVE_CALL get_string(AMX *amx, cell *params) LogError(amx, AMX_ERR_NATIVE, "Not currently in a dynamic native"); return 0; } - regnative *pNative = g_NativeStack.top(); + regnative *pNative = g_NativeStack.front(); if (pNative->style) { LogError(amx, AMX_ERR_NATIVE, "Wrong style of dynamic native"); @@ -167,7 +167,7 @@ static cell AMX_NATIVE_CALL set_string(AMX *amx, cell *params) LogError(amx, AMX_ERR_NATIVE, "Not currently in a dynamic native"); return 0; } - regnative *pNative = g_NativeStack.top(); + regnative *pNative = g_NativeStack.front(); if (pNative->style) { LogError(amx, AMX_ERR_NATIVE, "Wrong style of dynamic native"); @@ -190,7 +190,7 @@ static cell AMX_NATIVE_CALL get_param(AMX *amx, cell *params) LogError(amx, AMX_ERR_NATIVE, "Not currently in a dynamic native"); return 0; } - regnative *pNative = g_NativeStack.top(); + regnative *pNative = g_NativeStack.front(); if (pNative->style) { LogError(amx, AMX_ERR_NATIVE, "Wrong style of dynamic native"); @@ -209,7 +209,7 @@ static cell AMX_NATIVE_CALL get_param_byref(AMX *amx, cell *params) LogError(amx, AMX_ERR_NATIVE, "Not currently in a dynamic native"); return 0; } - regnative *pNative = g_NativeStack.top(); + regnative *pNative = g_NativeStack.front(); if (pNative->style) { LogError(amx, AMX_ERR_NATIVE, "Wrong style of dynamic native"); @@ -230,7 +230,7 @@ static cell AMX_NATIVE_CALL set_param_byref(AMX *amx, cell *params) LogError(amx, AMX_ERR_NATIVE, "Not currently in a dynamic native"); return 0; } - regnative *pNative = g_NativeStack.top(); + regnative *pNative = g_NativeStack.front(); if (pNative->style) { LogError(amx, AMX_ERR_NATIVE, "Wrong style of dynamic native"); @@ -253,7 +253,7 @@ static cell AMX_NATIVE_CALL get_array(AMX *amx, cell *params) LogError(amx, AMX_ERR_NATIVE, "Not currently in a dynamic native"); return 0; } - regnative *pNative = g_NativeStack.top(); + regnative *pNative = g_NativeStack.front(); if (pNative->style) { LogError(amx, AMX_ERR_NATIVE, "Wrong style of dynamic native"); @@ -279,7 +279,7 @@ static cell AMX_NATIVE_CALL set_array(AMX *amx, cell *params) LogError(amx, AMX_ERR_NATIVE, "Not currently in a dynamic native"); return 0; } - regnative *pNative = g_NativeStack.top(); + regnative *pNative = g_NativeStack.front(); if (pNative->style) { LogError(amx, AMX_ERR_NATIVE, "Wrong style of dynamic native"); @@ -308,7 +308,7 @@ static cell AMX_NATIVE_CALL param_convert(AMX *amx, cell *params) LogError(amx, AMX_ERR_NATIVE, "Not currently in a dynamic native"); return 0; } - regnative *pNative = g_NativeStack.top(); + regnative *pNative = g_NativeStack.front(); if (pNative->style != 1) { LogError(amx, AMX_ERR_NATIVE, "Wrong style of dynamic native"); diff --git a/amxmodx/sh_stack.h b/amxmodx/sh_stack.h new file mode 100755 index 00000000..04158ca1 --- /dev/null +++ b/amxmodx/sh_stack.h @@ -0,0 +1,219 @@ +/* ======== SourceMM ======== +* Copyright (C) 2004-2005 Metamod:Source Development Team +* No warranties of any kind +* +* License: zlib/libpng +* +* Author(s): Pavol "PM OnoTo" Marko +* ============================ +*/ + +#ifndef __SH_STACK_H__ +#define __SH_STACK_H__ + +#define SH_STACK_DEFAULT_SIZE 4 + +//namespace SourceHook +//{/ + // Vector + template class CStack + { + T *m_Elements; + size_t m_AllocatedSize; + size_t m_UsedSize; + public: + friend class iterator; + class iterator + { + CStack *m_pParent; + size_t m_Index; + public: + iterator(CStack *pParent, size_t id) : m_pParent(pParent), m_Index(id) + { + } + + iterator(CStack *pParent) : m_pParent(pParent), m_Index(0) + { + } + + iterator() : m_pParent(NULL), m_Index(0) + { + } + + T &operator *() + { + return m_pParent->m_Elements[m_Index]; + } + const T &operator *() const + { + return m_pParent->m_Elements[m_Index]; + } + + T * operator->() + { + return m_pParent->m_Elements + m_Index; + } + + const T * operator->() const + { + return m_pParent->m_Elements + m_Index; + } + + iterator & operator++() // preincrement + { + ++m_Index; + return (*this); + } + + iterator operator++(int) // postincrement + { + iterator tmp = *this; + ++m_Index; + return tmp; + } + + iterator & operator--() // predecrement + { + --m_Index; + return (*this); + } + + iterator operator--(int) // postdecrememnt + { + iterator tmp = *this; + --m_Index; + return tmp; + } + + bool operator==(const iterator & right) const + { + return (m_pParent == right.m_pParent && m_Index == right.m_Index); + } + + bool operator!=(const iterator & right) const + { + return !(*this == right); + } + }; + CStack() : m_Elements(new T[SH_STACK_DEFAULT_SIZE]), + m_AllocatedSize(SH_STACK_DEFAULT_SIZE), + m_UsedSize(0) + { + } + CStack(size_t size) : m_Elements(new T[size]), + m_AllocatedSize(size), + m_UsedSize(0) + { + } + + CStack(const CStack &other) : m_Elements(NULL), + m_AllocatedSize(0), + m_UsedSize(0) + { + reserve(other.m_AllocatedSize); + m_UsedSize = other.m_UsedSize; + for (size_t i = 0; i < m_UsedSize; ++i) + m_Elements[i] = other.m_Elements[i]; + } + + ~CStack() + { + if (m_Elements) + delete [] m_Elements; + } + + void operator=(const CStack &other) + { + if (m_AllocatedSize < other.m_AllocatedSize) + { + if (m_Elements) + delete [] m_Elements; + m_Elements = new T[other.m_AllocatedSize]; + m_AllocatedSize = other.m_AllocatedSize; + } + m_UsedSize = other.m_UsedSize; + for (size_t i = 0; i < m_UsedSize; ++i) + m_Elements[i] = other.m_Elements[i]; + } + + bool push(const T &val) + { + if (m_UsedSize + 1 == m_AllocatedSize) + { + // zOHNOES! REALLOCATE! + m_AllocatedSize *= 2; + T *newElements = new T[m_AllocatedSize]; + if (!newElements) + { + m_AllocatedSize /= 2; + return false; + } + if (m_Elements) + { + for (size_t i = 0; i < m_UsedSize; ++i) + newElements[i] = m_Elements[i]; + delete [] m_Elements; + } + m_Elements = newElements; + } + m_Elements[m_UsedSize++] = val; + return true; + } + void pop() + { + --m_UsedSize; + } + + T &front() + { + return m_Elements[m_UsedSize - 1]; + } + + const T &front() const + { + return m_Elements[m_UsedSize - 1]; + } + + iterator begin() + { + return iterator(this, 0); + } + iterator end() + { + return iterator(this, m_UsedSize); + } + + size_t size() + { + return m_UsedSize; + } + size_t capacity() + { + return m_AllocatedSize; + } + bool empty() + { + return m_UsedSize == 0 ? true : false; + } + bool reserve(size_t size) + { + if (size > m_AllocatedSize) + { + T *newElements = new T[size]; + if (!newElements) + return false; + if (m_Elements) + { + for (size_t i = 0; i < m_UsedSize; ++i) + newElements[i] = m_Elements[i]; + delete [] m_Elements; + } + m_Elements = newElements; + m_AllocatedSize = size; + } + return true; + } + }; +//}; //namespace SourceHook + +#endif