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