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
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
1.1 --- a/core/systems/ExtensionSys.cpp Wed Aug 29 05:22:47 2007 +0000
1.2 +++ b/core/systems/ExtensionSys.cpp Wed Aug 29 05:44:29 2007 +0000
1.3 @@ -566,51 +566,54 @@
1.4
1.5 void CExtensionManager::BindAllNativesToPlugin(IPlugin *pPlugin)
1.6 {
1.7 - List<CExtension *>::iterator iter;
1.8 - CExtension *pExt;
1.9 IPluginContext *pContext = pPlugin->GetBaseContext();
1.10 - for (iter=m_Libs.begin(); iter!=m_Libs.end(); iter++)
1.11 +
1.12 + List<CExtension *> exts;
1.13 +
1.14 + uint32_t natives = pContext->GetNativesNum();
1.15 + sp_native_t *native;
1.16 + sm_extnative_t *x_native;
1.17 + for (uint32_t i=0; i<natives; i++)
1.18 {
1.19 - pExt = (*iter);
1.20 - if (!pExt->IsLoaded())
1.21 + /* Make sure the native is valid */
1.22 + if (pContext->GetNativeByIndex(i, &native) != SP_ERROR_NONE)
1.23 {
1.24 continue;
1.25 }
1.26 - if (!pExt->m_Natives.size())
1.27 + /* Make sure the native is not already bound */
1.28 + if (native->status == SP_NATIVE_BOUND)
1.29 + {
1.30 + continue;
1.31 + }
1.32 + /* See if we've got this native in our cache */
1.33 + if ((x_native = m_ExtNatives.retrieve(native->name)) == NULL)
1.34 {
1.35 continue;
1.36 }
1.37 - bool set = false;
1.38 - List<const sp_nativeinfo_t *>::iterator n_iter;
1.39 - const sp_nativeinfo_t *natives;
1.40 - for (n_iter = pExt->m_Natives.begin();
1.41 - n_iter != pExt->m_Natives.end();
1.42 - n_iter++)
1.43 + /* Try and bind it */
1.44 + if (pContext->BindNativeToIndex(i, x_native->info->func) != SP_ERROR_NONE)
1.45 + {
1.46 + continue;
1.47 + }
1.48 + /* See if it's optional */
1.49 + if (native->flags & SP_NTVFLAG_OPTIONAL)
1.50 {
1.51 - natives = (*n_iter);
1.52 - uint32_t idx;
1.53 - unsigned int i=0;
1.54 - while (natives[i].func != NULL && natives[i].name != NULL)
1.55 - {
1.56 - if (pContext->BindNative(&natives[i]) == SP_ERROR_NONE)
1.57 - {
1.58 - pContext->FindNativeByName(natives[i].name, &idx);
1.59 - if (!(pContext->GetContext()->natives[idx].flags & SP_NTVFLAG_OPTIONAL))
1.60 - {
1.61 - set = true;
1.62 - } else {
1.63 - WeakNative wkn = WeakNative((CPlugin *)pPlugin, idx);
1.64 - pExt->m_WeakNatives.push_back(wkn);
1.65 - }
1.66 - }
1.67 - i++;
1.68 - }
1.69 + WeakNative wkn = WeakNative((CPlugin *)pPlugin, i);
1.70 + x_native->owner->m_WeakNatives.push_back(wkn);
1.71 + } else if (exts.find(x_native->owner) == exts.end()) {
1.72 + exts.push_back(x_native->owner);
1.73 }
1.74 - if (set && (pExt->m_Plugins.find(pPlugin) == pExt->m_Plugins.end()))
1.75 + }
1.76 +
1.77 + List<CExtension *>::iterator iter;
1.78 + for (iter = exts.begin(); iter != exts.end(); iter++)
1.79 + {
1.80 + CExtension *pExt = (*iter);
1.81 + if (pExt->m_Plugins.find(pPlugin) != pExt->m_Plugins.end())
1.82 {
1.83 - /* For now, mark this plugin as a requirement. Later we'll introduce native filtering. */
1.84 - pExt->m_Plugins.push_back(pPlugin);
1.85 + continue;
1.86 }
1.87 + pExt->m_Plugins.push_back(pPlugin);
1.88 }
1.89 }
1.90
1.91 @@ -704,6 +707,26 @@
1.92 }
1.93 }
1.94
1.95 + /* Unbind our natives from Core */
1.96 + List<const sp_nativeinfo_t *>::iterator native_iter;
1.97 + for (native_iter = pExt->m_Natives.begin();
1.98 + native_iter != pExt->m_Natives.end();
1.99 + native_iter++)
1.100 + {
1.101 + const sp_nativeinfo_t *natives = (*native_iter);
1.102 + sm_extnative_t *x_native;
1.103 + for (unsigned int n = 0;
1.104 + natives[n].name != NULL && natives[n].func != NULL;
1.105 + n++)
1.106 + {
1.107 + x_native = m_ExtNatives.retrieve(natives[n].name);
1.108 + if (x_native && x_native->owner == pExt)
1.109 + {
1.110 + m_ExtNatives.remove(natives[n].name);
1.111 + }
1.112 + }
1.113 + }
1.114 +
1.115 /* Tell it to unload */
1.116 pAPI = pExt->GetAPI();
1.117 pAPI->OnExtensionUnload();
1.118 @@ -743,6 +766,18 @@
1.119 CExtension *pExt = (CExtension *)pOwner;
1.120
1.121 pExt->m_Natives.push_back(natives);
1.122 +
1.123 + for (unsigned int i = 0; natives[i].func != NULL && natives[i].name != NULL; i++)
1.124 + {
1.125 + if (m_ExtNatives.retrieve(natives[i].name) != NULL)
1.126 + {
1.127 + continue;
1.128 + }
1.129 + sm_extnative_t x_native;
1.130 + x_native.info = &natives[i];
1.131 + x_native.owner = pExt;
1.132 + m_ExtNatives.insert(natives[i].name, x_native);
1.133 + }
1.134 }
1.135
1.136 void CExtensionManager::MarkAllLoaded()
1.137 @@ -1028,3 +1063,11 @@
1.138
1.139 return NULL;
1.140 }
1.141 +
1.142 +CExtensionManager::CExtensionManager()
1.143 +{
1.144 +}
1.145 +
1.146 +CExtensionManager::~CExtensionManager()
1.147 +{
1.148 +}
2.1 --- a/core/systems/ExtensionSys.h Wed Aug 29 05:22:47 2007 +0000
2.2 +++ b/core/systems/ExtensionSys.h Wed Aug 29 05:44:29 2007 +0000
2.3 @@ -36,6 +36,7 @@
2.4 #include <ILibrarySys.h>
2.5 #include <sh_list.h>
2.6 #include <sh_string.h>
2.7 +#include <sm_trie_tpl.h>
2.8 #include "sm_globals.h"
2.9 #include "ShareSys.h"
2.10 #include <ISmmAPI.h>
2.11 @@ -46,6 +47,14 @@
2.12 using namespace SourceMod;
2.13 using namespace SourceHook;
2.14
2.15 +class CExtension;
2.16 +
2.17 +struct sm_extnative_t
2.18 +{
2.19 + CExtension *owner;
2.20 + const sp_nativeinfo_t *info;
2.21 +};
2.22 +
2.23 class CExtension : public IExtension
2.24 {
2.25 friend class CExtensionManager;
2.26 @@ -95,6 +104,9 @@
2.27 public IPluginsListener,
2.28 public IRootConsoleCommand
2.29 {
2.30 +public:
2.31 + CExtensionManager();
2.32 + ~CExtensionManager();
2.33 public: //SMGlobalClass
2.34 void OnSourceModAllInitialized();
2.35 void OnSourceModShutdown();
2.36 @@ -127,6 +139,7 @@
2.37 CExtension *FindByOrder(unsigned int num);
2.38 private:
2.39 List<CExtension *> m_Libs;
2.40 + KTrie<sm_extnative_t> m_ExtNatives;
2.41 };
2.42
2.43 extern CExtensionManager g_Extensions;
3.1 --- a/public/IShareSys.h Wed Aug 29 05:22:47 2007 +0000
3.2 +++ b/public/IShareSys.h Wed Aug 29 05:44:29 2007 +0000
3.3 @@ -118,12 +118,18 @@
3.4 SMInterface **pIface) =0;
3.5
3.6 /**
3.7 - * @brief Adds a list of natives to the global native pool, to be bound on plugin load.
3.8 - * NOTE: Adding natives currently does not bind them to any loaded plugins.
3.9 - * You must manually bind late natives.
3.10 + * @brief Adds a list of natives to the global native pool, to be
3.11 + * bound on plugin load.
3.12 + *
3.13 + * Adding natives does not bind them to any loaded plugins; the
3.14 + * plugins must be reloaded for new natives to take effect.
3.15 *
3.16 * @param myself Identity token of parent object.
3.17 - * @param natives Array of natives to add. The last entry must have NULL members.
3.18 + * @param natives Array of natives to add. The last entry in
3.19 + * the array must be filled with NULLs to
3.20 + * terminate the array. The array must be static
3.21 + * as Core will cache the pointer for the
3.22 + * lifetime of the extension.
3.23 */
3.24 virtual void AddNatives(IExtension *myself, const sp_nativeinfo_t *natives) =0;
3.25