mirrored earlier core native binding optimization to extensions as well. clarified note about pointer lifetime in AddNatives(), as it will be gaining a second version soon
--HG-- extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%401397
This commit is contained in:
parent
77cc895151
commit
e5d81cf621
@ -566,51 +566,54 @@ CExtension *CExtensionManager::FindByOrder(unsigned int num)
|
||||
|
||||
void CExtensionManager::BindAllNativesToPlugin(IPlugin *pPlugin)
|
||||
{
|
||||
List<CExtension *>::iterator iter;
|
||||
CExtension *pExt;
|
||||
IPluginContext *pContext = pPlugin->GetBaseContext();
|
||||
for (iter=m_Libs.begin(); iter!=m_Libs.end(); iter++)
|
||||
|
||||
List<CExtension *> exts;
|
||||
|
||||
uint32_t natives = pContext->GetNativesNum();
|
||||
sp_native_t *native;
|
||||
sm_extnative_t *x_native;
|
||||
for (uint32_t i=0; i<natives; i++)
|
||||
{
|
||||
pExt = (*iter);
|
||||
if (!pExt->IsLoaded())
|
||||
/* Make sure the native is valid */
|
||||
if (pContext->GetNativeByIndex(i, &native) != SP_ERROR_NONE)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (!pExt->m_Natives.size())
|
||||
/* Make sure the native is not already bound */
|
||||
if (native->status == SP_NATIVE_BOUND)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
bool set = false;
|
||||
List<const sp_nativeinfo_t *>::iterator n_iter;
|
||||
const sp_nativeinfo_t *natives;
|
||||
for (n_iter = pExt->m_Natives.begin();
|
||||
n_iter != pExt->m_Natives.end();
|
||||
n_iter++)
|
||||
/* See if we've got this native in our cache */
|
||||
if ((x_native = m_ExtNatives.retrieve(native->name)) == NULL)
|
||||
{
|
||||
natives = (*n_iter);
|
||||
uint32_t idx;
|
||||
unsigned int i=0;
|
||||
while (natives[i].func != NULL && natives[i].name != NULL)
|
||||
{
|
||||
if (pContext->BindNative(&natives[i]) == SP_ERROR_NONE)
|
||||
{
|
||||
pContext->FindNativeByName(natives[i].name, &idx);
|
||||
if (!(pContext->GetContext()->natives[idx].flags & SP_NTVFLAG_OPTIONAL))
|
||||
{
|
||||
set = true;
|
||||
} else {
|
||||
WeakNative wkn = WeakNative((CPlugin *)pPlugin, idx);
|
||||
pExt->m_WeakNatives.push_back(wkn);
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (set && (pExt->m_Plugins.find(pPlugin) == pExt->m_Plugins.end()))
|
||||
/* Try and bind it */
|
||||
if (pContext->BindNativeToIndex(i, x_native->info->func) != SP_ERROR_NONE)
|
||||
{
|
||||
/* For now, mark this plugin as a requirement. Later we'll introduce native filtering. */
|
||||
pExt->m_Plugins.push_back(pPlugin);
|
||||
continue;
|
||||
}
|
||||
/* See if it's optional */
|
||||
if (native->flags & SP_NTVFLAG_OPTIONAL)
|
||||
{
|
||||
WeakNative wkn = WeakNative((CPlugin *)pPlugin, i);
|
||||
x_native->owner->m_WeakNatives.push_back(wkn);
|
||||
} else if (exts.find(x_native->owner) == exts.end()) {
|
||||
exts.push_back(x_native->owner);
|
||||
}
|
||||
}
|
||||
|
||||
List<CExtension *>::iterator iter;
|
||||
for (iter = exts.begin(); iter != exts.end(); iter++)
|
||||
{
|
||||
CExtension *pExt = (*iter);
|
||||
if (pExt->m_Plugins.find(pPlugin) != pExt->m_Plugins.end())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
pExt->m_Plugins.push_back(pPlugin);
|
||||
}
|
||||
}
|
||||
|
||||
@ -704,6 +707,26 @@ bool CExtensionManager::UnloadExtension(IExtension *_pExt)
|
||||
}
|
||||
}
|
||||
|
||||
/* Unbind our natives from Core */
|
||||
List<const sp_nativeinfo_t *>::iterator native_iter;
|
||||
for (native_iter = pExt->m_Natives.begin();
|
||||
native_iter != pExt->m_Natives.end();
|
||||
native_iter++)
|
||||
{
|
||||
const sp_nativeinfo_t *natives = (*native_iter);
|
||||
sm_extnative_t *x_native;
|
||||
for (unsigned int n = 0;
|
||||
natives[n].name != NULL && natives[n].func != NULL;
|
||||
n++)
|
||||
{
|
||||
x_native = m_ExtNatives.retrieve(natives[n].name);
|
||||
if (x_native && x_native->owner == pExt)
|
||||
{
|
||||
m_ExtNatives.remove(natives[n].name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Tell it to unload */
|
||||
pAPI = pExt->GetAPI();
|
||||
pAPI->OnExtensionUnload();
|
||||
@ -743,6 +766,18 @@ void CExtensionManager::AddNatives(IExtension *pOwner, const sp_nativeinfo_t *na
|
||||
CExtension *pExt = (CExtension *)pOwner;
|
||||
|
||||
pExt->m_Natives.push_back(natives);
|
||||
|
||||
for (unsigned int i = 0; natives[i].func != NULL && natives[i].name != NULL; i++)
|
||||
{
|
||||
if (m_ExtNatives.retrieve(natives[i].name) != NULL)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
sm_extnative_t x_native;
|
||||
x_native.info = &natives[i];
|
||||
x_native.owner = pExt;
|
||||
m_ExtNatives.insert(natives[i].name, x_native);
|
||||
}
|
||||
}
|
||||
|
||||
void CExtensionManager::MarkAllLoaded()
|
||||
@ -1028,3 +1063,11 @@ CExtension *CExtensionManager::GetExtensionFromIdent(IdentityToken_t *ptr)
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CExtensionManager::CExtensionManager()
|
||||
{
|
||||
}
|
||||
|
||||
CExtensionManager::~CExtensionManager()
|
||||
{
|
||||
}
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include <ILibrarySys.h>
|
||||
#include <sh_list.h>
|
||||
#include <sh_string.h>
|
||||
#include <sm_trie_tpl.h>
|
||||
#include "sm_globals.h"
|
||||
#include "ShareSys.h"
|
||||
#include <ISmmAPI.h>
|
||||
@ -46,6 +47,14 @@
|
||||
using namespace SourceMod;
|
||||
using namespace SourceHook;
|
||||
|
||||
class CExtension;
|
||||
|
||||
struct sm_extnative_t
|
||||
{
|
||||
CExtension *owner;
|
||||
const sp_nativeinfo_t *info;
|
||||
};
|
||||
|
||||
class CExtension : public IExtension
|
||||
{
|
||||
friend class CExtensionManager;
|
||||
@ -95,6 +104,9 @@ class CExtensionManager :
|
||||
public IPluginsListener,
|
||||
public IRootConsoleCommand
|
||||
{
|
||||
public:
|
||||
CExtensionManager();
|
||||
~CExtensionManager();
|
||||
public: //SMGlobalClass
|
||||
void OnSourceModAllInitialized();
|
||||
void OnSourceModShutdown();
|
||||
@ -127,6 +139,7 @@ private:
|
||||
CExtension *FindByOrder(unsigned int num);
|
||||
private:
|
||||
List<CExtension *> m_Libs;
|
||||
KTrie<sm_extnative_t> m_ExtNatives;
|
||||
};
|
||||
|
||||
extern CExtensionManager g_Extensions;
|
||||
|
@ -118,12 +118,18 @@ namespace SourceMod
|
||||
SMInterface **pIface) =0;
|
||||
|
||||
/**
|
||||
* @brief Adds a list of natives to the global native pool, to be bound on plugin load.
|
||||
* NOTE: Adding natives currently does not bind them to any loaded plugins.
|
||||
* You must manually bind late natives.
|
||||
* @brief Adds a list of natives to the global native pool, to be
|
||||
* bound on plugin load.
|
||||
*
|
||||
* Adding natives does not bind them to any loaded plugins; the
|
||||
* plugins must be reloaded for new natives to take effect.
|
||||
*
|
||||
* @param myself Identity token of parent object.
|
||||
* @param natives Array of natives to add. The last entry must have NULL members.
|
||||
* @param natives Array of natives to add. The last entry in
|
||||
* the array must be filled with NULLs to
|
||||
* terminate the array. The array must be static
|
||||
* as Core will cache the pointer for the
|
||||
* lifetime of the extension.
|
||||
*/
|
||||
virtual void AddNatives(IExtension *myself, const sp_nativeinfo_t *natives) =0;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user