Added optimizations to the task system

Added optimizations to the forward system
Fixed some debugger errors
This commit is contained in:
David Anderson 2005-10-25 20:38:00 +00:00
parent 0be7540637
commit 10a64737b5
10 changed files with 310 additions and 136 deletions

View File

@ -46,6 +46,8 @@
#ifndef FORWARD_H #ifndef FORWARD_H
#define FORWARD_H #define FORWARD_H
#include "sh_stack.h"
const int FORWARD_MAX_PARAMS = 32; const int FORWARD_MAX_PARAMS = 32;
enum ForwardExecType enum ForwardExecType
@ -171,7 +173,7 @@ class CForwardMngr
{ {
typedef CVector<CForward*> ForwardVec; typedef CVector<CForward*> ForwardVec;
typedef CVector<CSPForward*> SPForwardVec; typedef CVector<CSPForward*> SPForwardVec;
typedef CQueue<int> FreeSPVec; // Free SP Forwards typedef CStack<int> FreeSPVec; // Free SP Forwards
ForwardVec m_Forwards; ForwardVec m_Forwards;

View File

@ -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 T>
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

View File

@ -31,6 +31,9 @@
#include "amxmodx.h" #include "amxmodx.h"
#include "CTask.h" #include "CTask.h"
#include "sh_stack.h"
CStack<CTaskMngr::CTask *> *g_FreeTasks;
/*********************** CTask ***********************/ /*********************** CTask ***********************/
@ -73,12 +76,19 @@ void CTaskMngr::CTask::set(CPluginMngr::CPlugin *pPlugin, int iFunc, int iFlags,
if (iParamsLen) if (iParamsLen)
{ {
m_iParamLen = iParamsLen + 1; 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); memcpy(m_pParams, pParams, sizeof(cell)*iParamsLen);
m_pParams[iParamsLen] = 0; m_pParams[iParamsLen] = 0;
} else { } else {
m_iParamLen = 0; m_iParamLen = 0;
m_pParams = NULL;
} }
} }
@ -92,11 +102,7 @@ void CTaskMngr::CTask::clear()
m_iFunc = -1; m_iFunc = -1;
} }
if (m_pParams) m_iParamLen = 0;
{
delete [] m_pParams;
m_pParams = NULL;
}
m_pPlugin = NULL; m_pPlugin = NULL;
m_iId = 0; m_iId = 0;
@ -106,6 +112,7 @@ void CTaskMngr::CTask::clear()
m_bLoop = false; m_bLoop = false;
m_bAfterStart = false; m_bAfterStart = false;
m_bBeforeEnd = false; m_bBeforeEnd = false;
m_iParamLen = 0;
m_fNextExecTime = 0.0f; m_fNextExecTime = 0.0f;
} }
@ -174,6 +181,7 @@ void CTaskMngr::CTask::executeIfRequired(float fCurrentTime, float fTimeLimit, f
if (done) if (done)
{ {
clear(); clear();
g_FreeTasks->push(this);
} else { } else {
m_fNextExecTime += m_fBase; m_fNextExecTime += m_fBase;
} }
@ -197,12 +205,19 @@ CTaskMngr::CTask::CTask()
m_fNextExecTime = 0.0f; m_fNextExecTime = 0.0f;
m_iParamLen = 0; m_iParamLen = 0;
m_ParamSize = 0;
m_pParams = NULL; m_pParams = NULL;
} }
CTaskMngr::CTask::~CTask() CTaskMngr::CTask::~CTask()
{ {
clear(); clear();
if (m_pParams)
{
delete [] m_pParams;
m_pParams = NULL;
}
} }
/*********************** CTaskMngr ***********************/ /*********************** CTaskMngr ***********************/
@ -212,11 +227,17 @@ CTaskMngr::CTaskMngr()
m_pTmr_CurrentTime = NULL; m_pTmr_CurrentTime = NULL;
m_pTmr_TimeLimit = NULL; m_pTmr_TimeLimit = NULL;
m_pTmr_TimeLeft = NULL; m_pTmr_TimeLeft = NULL;
g_FreeTasks = new CStack<CTaskMngr::CTask *>();
} }
CTaskMngr::~CTaskMngr() 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) 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) 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 // first, search for free tasks
TaskListIter iter = m_Tasks.find(CTaskDescriptor(0, NULL, true)); if (!g_FreeTasks->empty())
if (iter)
{ {
// found: reuse it // 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 { } else {
// not found: make a new one // not found: make a new one
CTask *pTmp = new CTask; CTask *pTmp = new CTask;
if (!pTmp)
return;
pTmp->set(pPlugin, iFunc, iFlags, iId, fBase, iParamsLen, pParams, iRepeat, *m_pTmr_CurrentTime); pTmp->set(pPlugin, iFunc, iFlags, iId, fBase, iParamsLen, pParams, iRepeat, *m_pTmr_CurrentTime);
m_Tasks.put(pTmp); m_Tasks.put(pTmp);
} }
@ -254,8 +272,12 @@ int CTaskMngr::removeTasks(int iId, AMX *pAmx)
int i = 0; int i = 0;
while (iter) while (iter)
{
if (!iter->isFree())
{ {
iter->clear(); iter->clear();
g_FreeTasks->push(iter->getTask());
}
++i; ++i;
iter = m_Tasks.find(++iter, descriptor); iter = m_Tasks.find(++iter, descriptor);
} }
@ -297,5 +319,9 @@ void CTaskMngr::startFrame()
void CTaskMngr::clear() void CTaskMngr::clear()
{ {
m_Tasks.clear(); for (TaskListIter iter = m_Tasks.begin(); iter; ++iter)
{
if (!iter->isFree())
iter->clear();
}
} }

View File

@ -34,7 +34,7 @@
class CTaskMngr class CTaskMngr
{ {
private: public:
/*** class CTask ***/ /*** class CTask ***/
class CTask class CTask
{ {
@ -52,6 +52,7 @@ private:
int m_iParamLen; int m_iParamLen;
cell *m_pParams; cell *m_pParams;
cell m_ParamSize;
bool m_bFree; bool m_bFree;
// execution // execution
@ -70,6 +71,7 @@ private:
void resetNextExecTime(float fCurrentTime); void resetNextExecTime(float fCurrentTime);
bool shouldRepeat(); bool shouldRepeat();
CTask *getTask() { return this; }
CTask(); CTask();
~CTask(); ~CTask();

View File

@ -936,6 +936,8 @@ int Handler::HandleModule(const char *module)
cell hea_addr, *phys_addr, retval; cell hea_addr, *phys_addr, retval;
DisableDebugHandler(m_pAmx);
//temporarily set prenit //temporarily set prenit
m_pAmx->flags |= AMX_FLAG_PRENIT; m_pAmx->flags |= AMX_FLAG_PRENIT;
amx_PushString(m_pAmx, &hea_addr, &phys_addr, module, 0, 0); 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); amx_Release(m_pAmx, hea_addr);
m_pAmx->flags &= ~AMX_FLAG_PRENIT; m_pAmx->flags &= ~AMX_FLAG_PRENIT;
EnableDebugHandler(m_pAmx);
if (err != AMX_ERR_NONE) if (err != AMX_ERR_NONE)
return 0; return 0;
@ -966,6 +970,8 @@ int Handler::HandleNative(const char *native, int index, int trap)
if (pDebugger && trap) if (pDebugger && trap)
pDebugger->BeginExec(); pDebugger->BeginExec();
else if (pDebugger && !trap)
DisableDebugHandler(m_pAmx);
cell hea_addr, *phys_addr, retval; 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; m_pAmx->flags &= ~AMX_FLAG_PRENIT;
if (pDebugger && trap) if (pDebugger && trap)
pDebugger->EndExec(); pDebugger->EndExec();
else if (pDebugger && !trap)
EnableDebugHandler(m_pAmx);
amx_Release(m_pAmx, hea_addr); amx_Release(m_pAmx, hea_addr);

View File

@ -454,6 +454,8 @@ int set_amxnatives(AMX* amx, char error[128])
int idx, err; int idx, err;
cell retval; cell retval;
DisableDebugHandler(amx);
if (amx_FindPublic(amx, "plugin_natives", &idx) == AMX_ERR_NONE) if (amx_FindPublic(amx, "plugin_natives", &idx) == AMX_ERR_NONE)
{ {
if ((err = amx_Exec(amx, &retval, idx)) != AMX_ERR_NONE) if ((err = amx_Exec(amx, &retval, idx)) != AMX_ERR_NONE)
@ -463,6 +465,8 @@ int set_amxnatives(AMX* amx, char error[128])
} }
} }
EnableDebugHandler(amx);
amx->flags &= ~(AMX_FLAG_PRENIT); amx->flags &= ~(AMX_FLAG_PRENIT);
return (amx->error = AMX_ERR_NONE); return (amx->error = AMX_ERR_NONE);
@ -1689,6 +1693,22 @@ void *Module_ReqFnptr(const char *funcName)
return NULL; 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 #if !defined MEMORY_TEST && !defined WIN32
void * ::operator new(size_t size) void * ::operator new(size_t size)
{ {

View File

@ -50,5 +50,7 @@
int CheckModules(AMX *amx, char error[128]); int CheckModules(AMX *amx, char error[128]);
const char *StrCaseStr(const char *as, const char *bs); const char *StrCaseStr(const char *as, const char *bs);
void DisableDebugHandler(AMX *amx);
void EnableDebugHandler(AMX *amx);
#endif // __MODULES_H__ #endif // __MODULES_H__

View File

@ -786,9 +786,6 @@
<File <File
RelativePath="..\CQueue.h"> RelativePath="..\CQueue.h">
</File> </File>
<File
RelativePath="..\CStack.h">
</File>
<File <File
RelativePath="..\CString.h"> RelativePath="..\CString.h">
</File> </File>
@ -825,6 +822,9 @@
<File <File
RelativePath="..\resource.h"> RelativePath="..\resource.h">
</File> </File>
<File
RelativePath="..\sh_stack.h">
</File>
<File <File
RelativePath="..\zlib\zconf.h"> RelativePath="..\zlib\zconf.h">
</File> </File>

View File

@ -29,7 +29,7 @@
*/ */
#include "amxmodx.h" #include "amxmodx.h"
#include "CStack.h" #include "sh_stack.h"
#include "natives.h" #include "natives.h"
#ifdef __linux__ #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"); LogError(amx, AMX_ERR_NATIVE, "Not currently in a dynamic native");
return 0; return 0;
} }
regnative *pNative = g_NativeStack.top(); regnative *pNative = g_NativeStack.front();
if (pNative->style) if (pNative->style)
{ {
LogError(amx, AMX_ERR_NATIVE, "Wrong style of dynamic native"); 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"); LogError(amx, AMX_ERR_NATIVE, "Not currently in a dynamic native");
return 0; return 0;
} }
regnative *pNative = g_NativeStack.top(); regnative *pNative = g_NativeStack.front();
if (pNative->style) if (pNative->style)
{ {
LogError(amx, AMX_ERR_NATIVE, "Wrong style of dynamic native"); 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"); LogError(amx, AMX_ERR_NATIVE, "Not currently in a dynamic native");
return 0; return 0;
} }
regnative *pNative = g_NativeStack.top(); regnative *pNative = g_NativeStack.front();
if (pNative->style) if (pNative->style)
{ {
LogError(amx, AMX_ERR_NATIVE, "Wrong style of dynamic native"); 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"); LogError(amx, AMX_ERR_NATIVE, "Not currently in a dynamic native");
return 0; return 0;
} }
regnative *pNative = g_NativeStack.top(); regnative *pNative = g_NativeStack.front();
if (pNative->style) if (pNative->style)
{ {
LogError(amx, AMX_ERR_NATIVE, "Wrong style of dynamic native"); 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"); LogError(amx, AMX_ERR_NATIVE, "Not currently in a dynamic native");
return 0; return 0;
} }
regnative *pNative = g_NativeStack.top(); regnative *pNative = g_NativeStack.front();
if (pNative->style) if (pNative->style)
{ {
LogError(amx, AMX_ERR_NATIVE, "Wrong style of dynamic native"); 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"); LogError(amx, AMX_ERR_NATIVE, "Not currently in a dynamic native");
return 0; return 0;
} }
regnative *pNative = g_NativeStack.top(); regnative *pNative = g_NativeStack.front();
if (pNative->style) if (pNative->style)
{ {
LogError(amx, AMX_ERR_NATIVE, "Wrong style of dynamic native"); 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"); LogError(amx, AMX_ERR_NATIVE, "Not currently in a dynamic native");
return 0; return 0;
} }
regnative *pNative = g_NativeStack.top(); regnative *pNative = g_NativeStack.front();
if (pNative->style) if (pNative->style)
{ {
LogError(amx, AMX_ERR_NATIVE, "Wrong style of dynamic native"); 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"); LogError(amx, AMX_ERR_NATIVE, "Not currently in a dynamic native");
return 0; return 0;
} }
regnative *pNative = g_NativeStack.top(); regnative *pNative = g_NativeStack.front();
if (pNative->style != 1) if (pNative->style != 1)
{ {
LogError(amx, AMX_ERR_NATIVE, "Wrong style of dynamic native"); LogError(amx, AMX_ERR_NATIVE, "Wrong style of dynamic native");

219
amxmodx/sh_stack.h Executable file
View File

@ -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 T> class CStack
{
T *m_Elements;
size_t m_AllocatedSize;
size_t m_UsedSize;
public:
friend class iterator;
class iterator
{
CStack<T> *m_pParent;
size_t m_Index;
public:
iterator(CStack<T> *pParent, size_t id) : m_pParent(pParent), m_Index(id)
{
}
iterator(CStack<T> *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