From 8553f12d59f21b7d7177106d08604eee412e44b9 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Thu, 22 Feb 2007 02:05:50 +0000 Subject: [PATCH] Corrected an API design flaw with pausing. Contexts can now be flagged as paused, and IsRunnable() is moved from IBaseContext to IPluginFunction. While this allows for per-function pausing, it is not intended that way. --HG-- extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%40531 --- core/CConCmdManager.cpp | 12 ++++++++++++ core/systems/ForwardSys.cpp | 25 ++++++++----------------- core/systems/PluginSys.cpp | 17 +++++++++++------ core/vm/sp_vm_basecontext.cpp | 13 +------------ core/vm/sp_vm_basecontext.h | 3 --- core/vm/sp_vm_function.cpp | 19 +++++++++++++++++++ core/vm/sp_vm_function.h | 2 ++ public/sourcepawn/sp_vm_api.h | 14 +++++++------- public/sourcepawn/sp_vm_types.h | 1 + 9 files changed, 61 insertions(+), 45 deletions(-) diff --git a/core/CConCmdManager.cpp b/core/CConCmdManager.cpp index 546fe4be..2d19dad9 100644 --- a/core/CConCmdManager.cpp +++ b/core/CConCmdManager.cpp @@ -151,6 +151,10 @@ ResultType CConCmdManager::DispatchClientCommand(int client, ResultType type) iter++) { pHook = (*iter); + if (!pHook->pf->IsRunnable()) + { + continue; + } if (pHook->pAdmin && !CheckAccess(client, cmd, pHook->pAdmin)) { if (result < Pl_Handled) @@ -210,6 +214,10 @@ void CConCmdManager::InternalDispatch() iter++) { pHook = (*iter); + if (!pHook->pf->IsRunnable()) + { + continue; + } pHook->pf->PushCell(args); if (pHook->pf->Execute(&tempres) == SP_ERROR_NONE) { @@ -244,6 +252,10 @@ void CConCmdManager::InternalDispatch() iter++) { pHook = (*iter); + if (!pHook->pf->IsRunnable()) + { + continue; + } if (m_CmdClient && pHook->pAdmin && !CheckAccess(m_CmdClient, cmd, pHook->pAdmin)) diff --git a/core/systems/ForwardSys.cpp b/core/systems/ForwardSys.cpp index 70536027..3ce93a1e 100644 --- a/core/systems/ForwardSys.cpp +++ b/core/systems/ForwardSys.cpp @@ -304,6 +304,11 @@ int CForward::Execute(cell_t *result, IForwardFilter *filter) { func = (*iter); + if (!func->IsRunnable()) + { + continue; + } + for (unsigned int i=0; i *lst; - if (func->GetParentContext()->IsRunnable()) - { - lst = &m_functions; - } else { - lst = &m_paused; - } - - for (iter=lst->begin(); iter!=lst->end(); iter++) + for (iter=m_functions.begin(); iter!=m_functions.end(); iter++) { if ((*iter) == func) { found = true; - lst->erase(iter); + m_functions.erase(iter); break; } } @@ -689,13 +686,7 @@ bool CForward::AddFunction(IPluginFunction *func) return false; } - //:IDEA: eventually we will tell the plugin we're using it [?] - if (func->GetParentContext()->IsRunnable()) - { - m_functions.push_back(func); - } else { - m_paused.push_back(func); - } + m_functions.push_back(func); return true; } diff --git a/core/systems/PluginSys.cpp b/core/systems/PluginSys.cpp index 8651a455..5881a06e 100644 --- a/core/systems/PluginSys.cpp +++ b/core/systems/PluginSys.cpp @@ -202,7 +202,6 @@ bool CPlugin::FinishMyCompile(char *error, size_t maxlength) } m_ctx.base = new BaseContext(m_ctx.ctx); - m_ctx.base->SetRunnable(false); m_ctx.ctx->user[SM_CONTEXTVAR_MYSELF] = (void *)this; m_status = Plugin_Created; @@ -222,9 +221,9 @@ void CPlugin::SetErrorState(PluginStatus status, const char *error_fmt, ...) vsnprintf(m_errormsg, sizeof(m_errormsg), error_fmt, ap); va_end(ap); - if (m_ctx.base) + if (m_ctx.ctx) { - m_ctx.base->SetRunnable(false); + m_ctx.ctx->flags |= SPFLAG_PLUGIN_PAUSED; } } @@ -310,7 +309,6 @@ bool CPlugin::Call_AskPluginLoad(char *error, size_t maxlength) } m_status = Plugin_Loaded; - m_ctx.base->SetRunnable(true); int err; cell_t result; @@ -397,8 +395,6 @@ bool CPlugin::SetPauseState(bool paused) return false; } - m_status = (paused) ? Plugin_Paused : Plugin_Running; - IPluginFunction *pFunction = m_ctx.base->GetFunctionByName("OnPluginPauseChange"); if (pFunction) { @@ -407,6 +403,15 @@ bool CPlugin::SetPauseState(bool paused) pFunction->Execute(&result); } + if (paused) + { + m_status = Plugin_Paused; + m_ctx.ctx->flags |= SPFLAG_PLUGIN_PAUSED; + } else { + m_status = Plugin_Running; + m_ctx.ctx->flags &= ~SPFLAG_PLUGIN_PAUSED; + } + g_PluginSys._SetPauseState(this, paused); return true; diff --git a/core/vm/sp_vm_basecontext.cpp b/core/vm/sp_vm_basecontext.cpp index 302fb186..d6c4393e 100644 --- a/core/vm/sp_vm_basecontext.cpp +++ b/core/vm/sp_vm_basecontext.cpp @@ -40,7 +40,6 @@ BaseContext::BaseContext(sp_context_t *_ctx) ctx->dbreak = GlobalDebugBreak; m_InExec = false; m_CustomMsg = false; - m_Runnable = true; m_funcsnum = ctx->vmbase->FunctionCount(ctx); m_priv_funcs = NULL; m_pub_funcs = NULL; @@ -153,7 +152,7 @@ IPluginDebugInfo *BaseContext::GetDebugInfo() int BaseContext::Execute(uint32_t code_addr, cell_t *result) { - if (!m_Runnable) + if ((ctx->flags & SPFLAG_PLUGIN_PAUSED) == SPFLAG_PLUGIN_PAUSED) { return SP_ERROR_NOT_RUNNABLE; } @@ -928,14 +927,4 @@ void BaseContext::SetIdentity(SourceMod::IdentityToken_t *token) { m_pToken = token; } - -bool BaseContext::IsRunnable() -{ - return m_Runnable; -} - -void BaseContext::SetRunnable(bool runnable) -{ - m_Runnable = runnable; -} #endif diff --git a/core/vm/sp_vm_basecontext.h b/core/vm/sp_vm_basecontext.h index 4c001a54..68651e3f 100644 --- a/core/vm/sp_vm_basecontext.h +++ b/core/vm/sp_vm_basecontext.h @@ -68,8 +68,6 @@ namespace SourcePawn #if defined SOURCEMOD_BUILD virtual SourceMod::IdentityToken_t *GetIdentity(); void SetIdentity(SourceMod::IdentityToken_t *token); - bool IsRunnable(); - void SetRunnable(bool runnable); #endif public: //IPluginDebugInfo virtual int LookupFile(ucell_t addr, const char **filename); @@ -88,7 +86,6 @@ namespace SourcePawn char m_MsgCache[1024]; bool m_CustomMsg; bool m_InExec; - bool m_Runnable; unsigned int m_funcsnum; CFunction **m_priv_funcs; CFunction **m_pub_funcs; diff --git a/core/vm/sp_vm_function.cpp b/core/vm/sp_vm_function.cpp index c4fc339f..c7f3b5a6 100644 --- a/core/vm/sp_vm_function.cpp +++ b/core/vm/sp_vm_function.cpp @@ -26,10 +26,21 @@ void CFunction::Set(uint32_t code_addr, IPluginContext *plugin) m_curparam = 0; m_errorstate = SP_ERROR_NONE; m_Invalid = false; + m_pCtx = plugin ? plugin->GetContext() : NULL; +} + +bool CFunction::IsRunnable() +{ + return ((m_pCtx->flags & SPFLAG_PLUGIN_PAUSED) != SPFLAG_PLUGIN_PAUSED); } int CFunction::CallFunction(const cell_t *params, unsigned int num_params, cell_t *result) { + if (!IsRunnable()) + { + return SP_ERROR_NOT_RUNNABLE; + } + while (num_params--) { m_pContext->PushCell(params[num_params]); @@ -48,6 +59,10 @@ CFunction::CFunction(uint32_t code_addr, IPluginContext *plugin) : m_errorstate(SP_ERROR_NONE) { m_Invalid = false; + if (plugin) + { + m_pCtx = plugin->GetContext(); + } } int CFunction::PushCell(cell_t cell) @@ -201,6 +216,10 @@ void CFunction::Cancel() int CFunction::Execute(cell_t *result) { int err; + if (!IsRunnable()) + { + m_errorstate = SP_ERROR_NOT_RUNNABLE; + } if (m_errorstate != SP_ERROR_NONE) { err = m_errorstate; diff --git a/core/vm/sp_vm_function.h b/core/vm/sp_vm_function.h index 2eaaf229..4b13f66d 100644 --- a/core/vm/sp_vm_function.h +++ b/core/vm/sp_vm_function.h @@ -54,6 +54,7 @@ public: { m_Invalid = true; } + bool IsRunnable(); public: void Set(uint32_t code_addr, IPluginContext *plugin); private: @@ -66,6 +67,7 @@ private: private: uint32_t m_codeaddr; IPluginContext *m_pContext; + sp_context_t *m_pCtx; cell_t m_params[SP_MAX_EXEC_PARAMS]; ParamInfo m_info[SP_MAX_EXEC_PARAMS]; unsigned int m_curparam; diff --git a/public/sourcepawn/sp_vm_api.h b/public/sourcepawn/sp_vm_api.h index 99568264..cfdb5958 100644 --- a/public/sourcepawn/sp_vm_api.h +++ b/public/sourcepawn/sp_vm_api.h @@ -184,6 +184,13 @@ namespace SourcePawn * @return Address, or NULL if invalid parameter specified. */ virtual cell_t *GetAddressOfPushedParam(unsigned int param) =0; + + /** + * @brief Returns whether the parent plugin is paused. + * + * @return True if runnable, false otherwise. + */ + virtual bool IsRunnable() =0; }; @@ -534,13 +541,6 @@ namespace SourcePawn * @return Identity token. */ virtual SourceMod::IdentityToken_t *GetIdentity() =0; - - /** - * @brief Returns whether the identity is runnable. - * - * @return True if runnable, false otherwise. - */ - virtual bool IsRunnable() =0; #endif }; diff --git a/public/sourcepawn/sp_vm_types.h b/public/sourcepawn/sp_vm_types.h index 3440aa8a..9e04a143 100644 --- a/public/sourcepawn/sp_vm_types.h +++ b/public/sourcepawn/sp_vm_types.h @@ -229,6 +229,7 @@ typedef struct sp_debug_symbol_s typedef int (*SPVM_DEBUGBREAK)(struct sp_context_s *, uint32_t, uint32_t); #define SPFLAG_PLUGIN_DEBUG (1<<0) /**< plugin is in debug mode */ +#define SPFLAG_PLUGIN_PAUSED (1<<1) /**< plugin is "paused" (blocked from executing) */ /** * @brief This is the heart of the VM. It contains all of the runtime