Switch to re-entrant lists in ForwardSys and CForward.
This commit is contained in:
parent
d0843ab997
commit
88a47ff681
@ -33,6 +33,7 @@
|
|||||||
#include "common_logic.h"
|
#include "common_logic.h"
|
||||||
#include <bridge/include/IScriptManager.h>
|
#include <bridge/include/IScriptManager.h>
|
||||||
#include <amtl/am-string.h>
|
#include <amtl/am-string.h>
|
||||||
|
#include <ReentrantList.h>
|
||||||
|
|
||||||
using namespace ke;
|
using namespace ke;
|
||||||
|
|
||||||
@ -86,27 +87,22 @@ IChangeableForward *CForwardManager::CreateForwardEx(const char *name, ExecType
|
|||||||
void CForwardManager::OnPluginLoaded(IPlugin *plugin)
|
void CForwardManager::OnPluginLoaded(IPlugin *plugin)
|
||||||
{
|
{
|
||||||
/* Attach any globally managed forwards */
|
/* Attach any globally managed forwards */
|
||||||
for (auto iter=m_managed.begin(); iter!=m_managed.end(); iter++)
|
for (ForwardIter iter(m_managed); !iter.done(); iter.next()) {
|
||||||
{
|
|
||||||
CForward *fwd = (*iter);
|
CForward *fwd = (*iter);
|
||||||
IPluginFunction *pFunc = plugin->GetBaseContext()->GetFunctionByName(fwd->GetForwardName());
|
IPluginFunction *pFunc = plugin->GetBaseContext()->GetFunctionByName(fwd->GetForwardName());
|
||||||
if (pFunc)
|
if (pFunc)
|
||||||
{
|
|
||||||
fwd->AddFunction(pFunc);
|
fwd->AddFunction(pFunc);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CForwardManager::OnPluginUnloaded(IPlugin *plugin)
|
void CForwardManager::OnPluginUnloaded(IPlugin *plugin)
|
||||||
{
|
{
|
||||||
for (auto iter=m_managed.begin(); iter!=m_managed.end(); iter++)
|
for (ForwardIter iter(m_managed); !iter.done(); iter.next()) {
|
||||||
{
|
|
||||||
CForward *fwd = (*iter);
|
CForward *fwd = (*iter);
|
||||||
fwd->RemoveFunctionsOfPlugin(plugin);
|
fwd->RemoveFunctionsOfPlugin(plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto iter=m_unmanaged.begin(); iter!=m_unmanaged.end(); iter++)
|
for (ForwardIter iter(m_unmanaged); !iter.done(); iter.next()) {
|
||||||
{
|
|
||||||
CForward *fwd = (*iter);
|
CForward *fwd = (*iter);
|
||||||
fwd->RemoveFunctionsOfPlugin(plugin);
|
fwd->RemoveFunctionsOfPlugin(plugin);
|
||||||
}
|
}
|
||||||
@ -114,7 +110,7 @@ void CForwardManager::OnPluginUnloaded(IPlugin *plugin)
|
|||||||
|
|
||||||
IForward *CForwardManager::FindForward(const char *name, IChangeableForward **ifchng)
|
IForward *CForwardManager::FindForward(const char *name, IChangeableForward **ifchng)
|
||||||
{
|
{
|
||||||
for (auto iter=m_managed.begin(); iter!=m_managed.end(); iter++) {
|
for (ForwardIter iter(m_managed); !iter.done(); iter.next()) {
|
||||||
CForward *fwd = (*iter);
|
CForward *fwd = (*iter);
|
||||||
if (strcmp(fwd->GetForwardName(), name) == 0) {
|
if (strcmp(fwd->GetForwardName(), name) == 0) {
|
||||||
if (ifchng)
|
if (ifchng)
|
||||||
@ -123,7 +119,7 @@ IForward *CForwardManager::FindForward(const char *name, IChangeableForward **if
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto iter=m_unmanaged.begin(); iter!=m_unmanaged.end(); iter++) {
|
for (ForwardIter iter(m_unmanaged); !iter.done(); iter.next()) {
|
||||||
CForward *fwd = (*iter);
|
CForward *fwd = (*iter);
|
||||||
if (strcmp(fwd->GetForwardName(), name) == 0) {
|
if (strcmp(fwd->GetForwardName(), name) == 0) {
|
||||||
if (ifchng)
|
if (ifchng)
|
||||||
@ -152,8 +148,7 @@ void CForwardManager::OnPluginPauseChange(IPlugin *plugin, bool paused)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
/* Attach any globally managed forwards */
|
/* Attach any globally managed forwards */
|
||||||
for (auto iter=m_managed.begin(); iter!=m_managed.end(); iter++)
|
for (ForwardIter iter(m_managed); !iter.done(); iter.next()) {
|
||||||
{
|
|
||||||
CForward *fwd = (*iter);
|
CForward *fwd = (*iter);
|
||||||
IPluginFunction *pFunc = plugin->GetBaseContext()->GetFunctionByName(fwd->GetForwardName());
|
IPluginFunction *pFunc = plugin->GetBaseContext()->GetFunctionByName(fwd->GetForwardName());
|
||||||
// Only add functions, if they aren't registered yet!
|
// Only add functions, if they aren't registered yet!
|
||||||
@ -169,8 +164,7 @@ void CForwardManager::OnPluginPauseChange(IPlugin *plugin, bool paused)
|
|||||||
*************************************/
|
*************************************/
|
||||||
|
|
||||||
CForward::CForward(ExecType et, const char *name, const ParamType *types, unsigned num_params)
|
CForward::CForward(ExecType et, const char *name, const ParamType *types, unsigned num_params)
|
||||||
: m_IterGuard(nullptr),
|
: m_numparams(0),
|
||||||
m_numparams(0),
|
|
||||||
m_varargs(0),
|
m_varargs(0),
|
||||||
m_ExecType(et),
|
m_ExecType(et),
|
||||||
m_curparam(0),
|
m_curparam(0),
|
||||||
@ -239,7 +233,6 @@ int CForward::Execute(cell_t *result, IForwardFilter *filter)
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
FuncIter iter = m_functions.begin();
|
|
||||||
cell_t cur_result = 0;
|
cell_t cur_result = 0;
|
||||||
cell_t high_result = 0;
|
cell_t high_result = 0;
|
||||||
cell_t low_result = 0;
|
cell_t low_result = 0;
|
||||||
@ -252,9 +245,7 @@ int CForward::Execute(cell_t *result, IForwardFilter *filter)
|
|||||||
memcpy(temp_info, m_params, sizeof(m_params));
|
memcpy(temp_info, m_params, sizeof(m_params));
|
||||||
m_curparam = 0;
|
m_curparam = 0;
|
||||||
|
|
||||||
FuncIteratorGuard guard(&m_IterGuard, &iter);
|
for (FuncIter iter(m_functions); !iter.done(); iter.next())
|
||||||
|
|
||||||
while (iter != m_functions.end())
|
|
||||||
{
|
{
|
||||||
IPluginFunction *func = (*iter);
|
IPluginFunction *func = (*iter);
|
||||||
|
|
||||||
@ -349,9 +340,6 @@ int CForward::Execute(cell_t *result, IForwardFilter *filter)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!guard.Triggered())
|
|
||||||
iter++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
@ -616,30 +604,24 @@ bool CForward::RemoveFunction(IPluginContext *pContext, funcid_t index)
|
|||||||
|
|
||||||
bool CForward::RemoveFunction(IPluginFunction *func)
|
bool CForward::RemoveFunction(IPluginFunction *func)
|
||||||
{
|
{
|
||||||
bool found = false;
|
ReentrantList<IPluginFunction *> *lst;
|
||||||
LinkedList<IPluginFunction *> *lst;
|
|
||||||
|
|
||||||
if (func->IsRunnable())
|
if (func->IsRunnable())
|
||||||
lst = &m_functions;
|
lst = &m_functions;
|
||||||
else
|
else
|
||||||
lst = &m_paused;
|
lst = &m_paused;
|
||||||
|
|
||||||
for (auto iter = lst->begin(); iter != lst->end(); iter++)
|
bool found = false;
|
||||||
{
|
for (FuncIter iter(lst); !iter.done(); iter.next()) {
|
||||||
if ((*iter) == func)
|
if (*iter == func) {
|
||||||
{
|
iter.remove();
|
||||||
m_IterGuard->FixIteratorChain(iter);
|
|
||||||
found = true;
|
found = true;
|
||||||
lst->erase(iter);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Cancel a call, if any */
|
/* Cancel a call, if any */
|
||||||
if (found || m_curparam)
|
if (found || m_curparam)
|
||||||
{
|
|
||||||
func->Cancel();
|
func->Cancel();
|
||||||
}
|
|
||||||
|
|
||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
@ -647,19 +629,13 @@ bool CForward::RemoveFunction(IPluginFunction *func)
|
|||||||
unsigned int CForward::RemoveFunctionsOfPlugin(IPlugin *plugin)
|
unsigned int CForward::RemoveFunctionsOfPlugin(IPlugin *plugin)
|
||||||
{
|
{
|
||||||
unsigned int removed = 0;
|
unsigned int removed = 0;
|
||||||
IPluginContext *pContext = plugin->GetBaseContext();
|
for (FuncIter iter(m_functions); !iter.done(); iter.next()) {
|
||||||
for (auto iter=m_functions.begin(); iter!=m_functions.end();)
|
IPluginFunction *func = *iter;
|
||||||
{
|
if (func->GetParentContext() == plugin->GetBaseContext()) {
|
||||||
IPluginFunction *func = (*iter);
|
iter.remove();
|
||||||
if (func->GetParentContext() == pContext)
|
|
||||||
{
|
|
||||||
iter = m_functions.erase(iter);
|
|
||||||
removed++;
|
removed++;
|
||||||
} else {
|
|
||||||
iter++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return removed;
|
return removed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -678,13 +654,13 @@ bool CForward::AddFunction(IPluginFunction *func)
|
|||||||
|
|
||||||
bool CForward::IsFunctionRegistered(IPluginFunction *func)
|
bool CForward::IsFunctionRegistered(IPluginFunction *func)
|
||||||
{
|
{
|
||||||
LinkedList<IPluginFunction *> *lst;
|
ReentrantList<IPluginFunction *> *lst;
|
||||||
if (func->IsRunnable())
|
if (func->IsRunnable())
|
||||||
lst = &m_functions;
|
lst = &m_functions;
|
||||||
else
|
else
|
||||||
lst = &m_paused;
|
lst = &m_paused;
|
||||||
|
|
||||||
for (auto iter = lst->begin(); iter != lst->end(); iter++) {
|
for (FuncIter iter(lst); !iter.done(); iter.next()) {
|
||||||
if ((*iter) == func)
|
if ((*iter) == func)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -31,58 +31,14 @@
|
|||||||
#include <IForwardSys.h>
|
#include <IForwardSys.h>
|
||||||
#include <IPluginSys.h>
|
#include <IPluginSys.h>
|
||||||
#include "common_logic.h"
|
#include "common_logic.h"
|
||||||
#include <amtl/am-linkedlist.h>
|
|
||||||
#include "ISourceMod.h"
|
#include "ISourceMod.h"
|
||||||
|
#include "ReentrantList.h"
|
||||||
|
|
||||||
typedef ke::LinkedList<IPluginFunction *>::iterator FuncIter;
|
typedef ReentrantList<IPluginFunction *>::iterator FuncIter;
|
||||||
|
|
||||||
/* :TODO: a global name max define for sourcepawn, should mirror compiler's sNAMEMAX */
|
/* :TODO: a global name max define for sourcepawn, should mirror compiler's sNAMEMAX */
|
||||||
#define FORWARDS_NAME_MAX 64
|
#define FORWARDS_NAME_MAX 64
|
||||||
|
|
||||||
class FuncIteratorGuard
|
|
||||||
{
|
|
||||||
bool triggered;
|
|
||||||
FuncIteratorGuard **pprev;
|
|
||||||
FuncIter *iter;
|
|
||||||
FuncIteratorGuard *next;
|
|
||||||
public:
|
|
||||||
FuncIteratorGuard(FuncIteratorGuard **pprev, FuncIter *iter)
|
|
||||||
: triggered(false), pprev(pprev), iter(iter), next(*pprev)
|
|
||||||
{
|
|
||||||
*pprev = this;
|
|
||||||
}
|
|
||||||
|
|
||||||
~FuncIteratorGuard()
|
|
||||||
{
|
|
||||||
*pprev = next;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool Triggered()
|
|
||||||
{
|
|
||||||
bool t = triggered;
|
|
||||||
triggered = false;
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This should not read from |this| before the NULL check, because FwdSys
|
|
||||||
* can call (NULL)->FixIteratorChain().
|
|
||||||
*/
|
|
||||||
void FixIteratorChain(FuncIter &other)
|
|
||||||
{
|
|
||||||
FuncIteratorGuard *guard = this;
|
|
||||||
while (guard != NULL)
|
|
||||||
{
|
|
||||||
if (*guard->iter == other)
|
|
||||||
{
|
|
||||||
*(guard->iter) = ++(*(guard->iter));
|
|
||||||
guard->triggered = true;
|
|
||||||
}
|
|
||||||
guard = guard->next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class CForward : public IChangeableForward
|
class CForward : public IChangeableForward
|
||||||
{
|
{
|
||||||
public: //ICallable
|
public: //ICallable
|
||||||
@ -124,12 +80,8 @@ private:
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
protected:
|
protected:
|
||||||
/* :TODO: I want a caching list type here.
|
mutable ReentrantList<IPluginFunction *> m_functions;
|
||||||
* Destroying these things and using new/delete for their members feels bad.
|
mutable ReentrantList<IPluginFunction *> m_paused;
|
||||||
*/
|
|
||||||
mutable ke::LinkedList<IPluginFunction *> m_functions;
|
|
||||||
mutable ke::LinkedList<IPluginFunction *> m_paused;
|
|
||||||
FuncIteratorGuard *m_IterGuard;
|
|
||||||
|
|
||||||
/* Type and name information */
|
/* Type and name information */
|
||||||
FwdParamInfo m_params[SP_MAX_EXEC_PARAMS];
|
FwdParamInfo m_params[SP_MAX_EXEC_PARAMS];
|
||||||
@ -170,8 +122,10 @@ public: //IPluginsListener
|
|||||||
public: //SMGlobalClass
|
public: //SMGlobalClass
|
||||||
void OnSourceModAllInitialized();
|
void OnSourceModAllInitialized();
|
||||||
private:
|
private:
|
||||||
ke::LinkedList<CForward *> m_managed;
|
ReentrantList<CForward *> m_managed;
|
||||||
ke::LinkedList<CForward *> m_unmanaged;
|
ReentrantList<CForward *> m_unmanaged;
|
||||||
|
|
||||||
|
typedef ReentrantList<CForward *>::iterator ForwardIter;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern CForwardManager g_Forwards;
|
extern CForwardManager g_Forwards;
|
||||||
|
Loading…
Reference in New Issue
Block a user