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) | void CExtensionManager::BindAllNativesToPlugin(IPlugin *pPlugin) | ||||||
| { | { | ||||||
| 	List<CExtension *>::iterator iter; |  | ||||||
| 	CExtension *pExt; |  | ||||||
| 	IPluginContext *pContext = pPlugin->GetBaseContext(); | 	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); | 		/* Make sure the native is valid */ | ||||||
| 		if (!pExt->IsLoaded()) | 		if (pContext->GetNativeByIndex(i, &native) != SP_ERROR_NONE) | ||||||
| 		{ | 		{ | ||||||
| 			continue; | 			continue; | ||||||
| 		} | 		} | ||||||
| 		if (!pExt->m_Natives.size()) | 		/* Make sure the native is not already bound */ | ||||||
|  | 		if (native->status == SP_NATIVE_BOUND) | ||||||
| 		{ | 		{ | ||||||
| 			continue; | 			continue; | ||||||
| 		} | 		} | ||||||
| 		bool set = false; | 		/* See if we've got this native in our cache */ | ||||||
| 		List<const sp_nativeinfo_t *>::iterator n_iter; | 		if ((x_native = m_ExtNatives.retrieve(native->name)) == NULL) | ||||||
| 		const sp_nativeinfo_t *natives; |  | ||||||
| 		for (n_iter = pExt->m_Natives.begin(); |  | ||||||
| 			 n_iter != pExt->m_Natives.end(); |  | ||||||
| 			 n_iter++) |  | ||||||
| 		{ | 		{ | ||||||
| 			natives = (*n_iter); | 			continue; | ||||||
| 			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++; |  | ||||||
| 			} |  | ||||||
| 		} | 		} | ||||||
| 		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. */ | 			continue; | ||||||
| 			pExt->m_Plugins.push_back(pPlugin); |  | ||||||
| 		} | 		} | ||||||
|  | 		/* 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 */ | 		/* Tell it to unload */ | ||||||
| 		pAPI = pExt->GetAPI(); | 		pAPI = pExt->GetAPI(); | ||||||
| 		pAPI->OnExtensionUnload(); | 		pAPI->OnExtensionUnload(); | ||||||
| @ -743,6 +766,18 @@ void CExtensionManager::AddNatives(IExtension *pOwner, const sp_nativeinfo_t *na | |||||||
| 	CExtension *pExt = (CExtension *)pOwner; | 	CExtension *pExt = (CExtension *)pOwner; | ||||||
| 
 | 
 | ||||||
| 	pExt->m_Natives.push_back(natives); | 	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() | void CExtensionManager::MarkAllLoaded() | ||||||
| @ -1028,3 +1063,11 @@ CExtension *CExtensionManager::GetExtensionFromIdent(IdentityToken_t *ptr) | |||||||
| 
 | 
 | ||||||
| 	return NULL; | 	return NULL; | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | CExtensionManager::CExtensionManager() | ||||||
|  | { | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | CExtensionManager::~CExtensionManager() | ||||||
|  | { | ||||||
|  | } | ||||||
|  | |||||||
| @ -36,6 +36,7 @@ | |||||||
| #include <ILibrarySys.h> | #include <ILibrarySys.h> | ||||||
| #include <sh_list.h> | #include <sh_list.h> | ||||||
| #include <sh_string.h> | #include <sh_string.h> | ||||||
|  | #include <sm_trie_tpl.h> | ||||||
| #include "sm_globals.h" | #include "sm_globals.h" | ||||||
| #include "ShareSys.h" | #include "ShareSys.h" | ||||||
| #include <ISmmAPI.h> | #include <ISmmAPI.h> | ||||||
| @ -46,6 +47,14 @@ | |||||||
| using namespace SourceMod; | using namespace SourceMod; | ||||||
| using namespace SourceHook; | using namespace SourceHook; | ||||||
| 
 | 
 | ||||||
|  | class CExtension; | ||||||
|  | 
 | ||||||
|  | struct sm_extnative_t | ||||||
|  | { | ||||||
|  | 	CExtension *owner; | ||||||
|  | 	const sp_nativeinfo_t *info; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| class CExtension : public IExtension | class CExtension : public IExtension | ||||||
| { | { | ||||||
| 	friend class CExtensionManager; | 	friend class CExtensionManager; | ||||||
| @ -95,6 +104,9 @@ class CExtensionManager : | |||||||
| 	public IPluginsListener, | 	public IPluginsListener, | ||||||
| 	public IRootConsoleCommand | 	public IRootConsoleCommand | ||||||
| { | { | ||||||
|  | public: | ||||||
|  | 	CExtensionManager(); | ||||||
|  | 	~CExtensionManager(); | ||||||
| public: //SMGlobalClass
 | public: //SMGlobalClass
 | ||||||
| 	void OnSourceModAllInitialized(); | 	void OnSourceModAllInitialized(); | ||||||
| 	void OnSourceModShutdown(); | 	void OnSourceModShutdown(); | ||||||
| @ -127,6 +139,7 @@ private: | |||||||
| 	CExtension *FindByOrder(unsigned int num); | 	CExtension *FindByOrder(unsigned int num); | ||||||
| private: | private: | ||||||
| 	List<CExtension *> m_Libs; | 	List<CExtension *> m_Libs; | ||||||
|  | 	KTrie<sm_extnative_t> m_ExtNatives; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| extern CExtensionManager g_Extensions; | extern CExtensionManager g_Extensions; | ||||||
|  | |||||||
| @ -118,12 +118,18 @@ namespace SourceMod | |||||||
| 										SMInterface **pIface) =0; | 										SMInterface **pIface) =0; | ||||||
| 
 | 
 | ||||||
| 		/**
 | 		/**
 | ||||||
| 		 * @brief Adds a list of natives to the global native pool, to be bound on plugin load. | 		 * @brief Adds a list of natives to the global native pool, to be  | ||||||
| 		 * NOTE: Adding natives currently does not bind them to any loaded plugins. | 		 * bound on plugin load. | ||||||
| 		 * You must manually bind late natives. | 		 * | ||||||
|  | 		 * 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 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; | 		virtual void AddNatives(IExtension *myself, const sp_nativeinfo_t *natives) =0; | ||||||
| 
 | 
 | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user