Use Refcounted to manage to NativeEntry (bug 5852 part 4, r=ds).
--HG-- extra : rebase_source : 2e08816db6819c9d9957a0e0ade9cd1aa420fd54
This commit is contained in:
		
							parent
							
								
									3da646f913
								
							
						
					
					
						commit
						4500964394
					
				
							
								
								
									
										98
									
								
								core/logic/Native.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										98
									
								
								core/logic/Native.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,98 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * vim: set ts=4 sw=4 tw=99 noet :
 | 
				
			||||||
 | 
					 * =============================================================================
 | 
				
			||||||
 | 
					 * SourceMod
 | 
				
			||||||
 | 
					 * Copyright (C) 2004-2008 AlliedModders LLC.  All rights reserved.
 | 
				
			||||||
 | 
					 * =============================================================================
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify it under
 | 
				
			||||||
 | 
					 * the terms of the GNU General Public License, version 3.0, as published by the
 | 
				
			||||||
 | 
					 * Free Software Foundation.
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * This program is distributed in the hope that it will be useful, but WITHOUT
 | 
				
			||||||
 | 
					 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 | 
				
			||||||
 | 
					 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 | 
				
			||||||
 | 
					 * details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License along with
 | 
				
			||||||
 | 
					 * this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * As a special exception, AlliedModders LLC gives you permission to link the
 | 
				
			||||||
 | 
					 * code of this program (as well as its derivative works) to "Half-Life 2," the
 | 
				
			||||||
 | 
					 * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
 | 
				
			||||||
 | 
					 * by the Valve Corporation.  You must obey the GNU General Public License in
 | 
				
			||||||
 | 
					 * all respects for all other code used.  Additionally, AlliedModders LLC grants
 | 
				
			||||||
 | 
					 * this exception to all derivative works.  AlliedModders LLC defines further
 | 
				
			||||||
 | 
					 * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
 | 
				
			||||||
 | 
					 * or <http://www.sourcemod.net/license.php>.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Version: $Id$
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#ifndef _include_sourcemod_native_h_
 | 
				
			||||||
 | 
					#define _include_sourcemod_native_h_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <IShareSys.h>
 | 
				
			||||||
 | 
					#include <IHandleSys.h>
 | 
				
			||||||
 | 
					#include <am-string.h>
 | 
				
			||||||
 | 
					#include <am-utility.h>
 | 
				
			||||||
 | 
					#include <am-refcounting.h>
 | 
				
			||||||
 | 
					#include "common_logic.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct FakeNative
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						FakeNative(const char *name, IPluginFunction *fun)
 | 
				
			||||||
 | 
							: name(name),
 | 
				
			||||||
 | 
							  ctx(fun->GetParentContext()),
 | 
				
			||||||
 | 
							  call(fun),
 | 
				
			||||||
 | 
							  gate(NULL)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						~FakeNative();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ke::AString name;
 | 
				
			||||||
 | 
						IPluginContext *ctx;
 | 
				
			||||||
 | 
						IPluginFunction *call;
 | 
				
			||||||
 | 
						SPVM_NATIVE_FUNC gate;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct Native : public ke::Refcounted<Native>
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						Native(CNativeOwner *owner, const sp_nativeinfo_t *native)
 | 
				
			||||||
 | 
							: owner(owner),
 | 
				
			||||||
 | 
							  native(native),
 | 
				
			||||||
 | 
							  fake(NULL)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						Native(CNativeOwner *owner, FakeNative *fake)
 | 
				
			||||||
 | 
							: owner(owner),
 | 
				
			||||||
 | 
							  native(NULL),
 | 
				
			||||||
 | 
							  fake(fake)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						CNativeOwner *owner;
 | 
				
			||||||
 | 
						const sp_nativeinfo_t *native;
 | 
				
			||||||
 | 
						ke::AutoPtr<FakeNative> fake;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						SPVM_NATIVE_FUNC func() const
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							if (native)
 | 
				
			||||||
 | 
								return native->func;
 | 
				
			||||||
 | 
							return fake->gate;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						const char *name() const
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							if (native)
 | 
				
			||||||
 | 
								return native->name;
 | 
				
			||||||
 | 
							return fake->name.chars();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						static inline bool matches(const char *name, const ke::Ref<Native> &entry)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							return strcmp(name, entry->name()) == 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif // _include_sourcemod_native_h_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -69,11 +69,11 @@ INativeInvoker *NativeInterface::CreateInvoker()
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
bool NativeInvoker::Start(IPluginContext *pContext, const char *name)
 | 
					bool NativeInvoker::Start(IPluginContext *pContext, const char *name)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	NativeEntry *entry = g_ShareSys.FindNative(name);
 | 
						ke::Ref<Native> entry = g_ShareSys.FindNative(name);
 | 
				
			||||||
	if (!entry)
 | 
						if (!entry)
 | 
				
			||||||
		return false;
 | 
							return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!entry->owner || !entry->func())
 | 
						if (!entry->owner)
 | 
				
			||||||
		return false;
 | 
							return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	native_ = entry->func();
 | 
						native_ = entry->func();
 | 
				
			||||||
 | 
				
			|||||||
@ -85,26 +85,14 @@ void CNativeOwner::UnbindWeakRef(const WeakNative & ref)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	pContext = ref.pl->GetBaseContext();
 | 
						pContext = ref.pl->GetBaseContext();
 | 
				
			||||||
	if ((pContext->GetNativeByIndex(ref.idx, &native)) == SP_ERROR_NONE)
 | 
						if ((pContext->GetNativeByIndex(ref.idx, &native)) == SP_ERROR_NONE)
 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		/* If there is no reference, the native must be unbound */
 | 
					 | 
				
			||||||
		if (ref.entry == NULL)
 | 
					 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		native->status = SP_NATIVE_UNBOUND;
 | 
							native->status = SP_NATIVE_UNBOUND;
 | 
				
			||||||
		native->pfn = NULL;
 | 
							native->pfn = NULL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
		/* If we've cached a reference, it's a core native we can 
 | 
					 | 
				
			||||||
		 * rebind back to its original (this was a replacement).
 | 
					 | 
				
			||||||
		 */
 | 
					 | 
				
			||||||
		else
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			native->pfn = ref.entry->func();
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void CNativeOwner::DropEverything()
 | 
					void CNativeOwner::DropEverything()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	NativeEntry *pEntry;
 | 
					 | 
				
			||||||
	List<WeakNative>::iterator iter;
 | 
						List<WeakNative>::iterator iter;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Unbind and remove all weak references to us */
 | 
						/* Unbind and remove all weak references to us */
 | 
				
			||||||
@ -121,13 +109,11 @@ void CNativeOwner::DropEverything()
 | 
				
			|||||||
		for (const sp_nativeinfo_t *native = natives; native->func && native->name; native++)
 | 
							for (const sp_nativeinfo_t *native = natives; native->func && native->name; native++)
 | 
				
			||||||
			g_ShareSys.ClearNativeFromCache(this, native->name);
 | 
								g_ShareSys.ClearNativeFromCache(this, native->name);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						m_natives.clear();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	List<NativeEntry *>::iterator ntv_iter = m_Natives.begin();
 | 
						for (size_t i = 0; i < m_fakes.length(); i++)
 | 
				
			||||||
	while (ntv_iter != m_Natives.end())
 | 
							g_ShareSys.ClearNativeFromCache(this, m_fakes[i]->name());
 | 
				
			||||||
	{
 | 
						m_fakes.clear();
 | 
				
			||||||
		g_ShareSys.ClearNativeFromCache(this, (*ntv_iter)->name());
 | 
					 | 
				
			||||||
		ntv_iter = m_Natives.erase(ntv_iter);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void CNativeOwner::DropWeakRefsTo(CPlugin *pPlugin)
 | 
					void CNativeOwner::DropWeakRefsTo(CPlugin *pPlugin)
 | 
				
			||||||
 | 
				
			|||||||
@ -33,10 +33,12 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include <sp_vm_types.h>
 | 
					#include <sp_vm_types.h>
 | 
				
			||||||
#include <sh_list.h>
 | 
					#include <sh_list.h>
 | 
				
			||||||
 | 
					#include <am-linkedlist.h>
 | 
				
			||||||
#include <am-vector.h>
 | 
					#include <am-vector.h>
 | 
				
			||||||
#include "common_logic.h"
 | 
					#include "common_logic.h"
 | 
				
			||||||
 | 
					#include "Native.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct NativeEntry;
 | 
					struct Native;
 | 
				
			||||||
class CPlugin;
 | 
					class CPlugin;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
using namespace SourceMod;
 | 
					using namespace SourceMod;
 | 
				
			||||||
@ -44,20 +46,13 @@ using namespace SourceMod;
 | 
				
			|||||||
struct WeakNative
 | 
					struct WeakNative
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	WeakNative(IPlugin *plugin, uint32_t index) : 
 | 
						WeakNative(IPlugin *plugin, uint32_t index) : 
 | 
				
			||||||
		pl(plugin), idx(index), entry(NULL)
 | 
							pl(plugin), idx(index)
 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		pl = plugin;
 | 
					 | 
				
			||||||
		idx = index;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	WeakNative(IPlugin *plugin, uint32_t index, NativeEntry *pEntry) : 
 | 
					 | 
				
			||||||
		pl(plugin), idx(index), entry(pEntry)
 | 
					 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		pl = plugin;
 | 
							pl = plugin;
 | 
				
			||||||
		idx = index;
 | 
							idx = index;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	IPlugin *pl;
 | 
						IPlugin *pl;
 | 
				
			||||||
	uint32_t idx;
 | 
						uint32_t idx;
 | 
				
			||||||
	NativeEntry *entry;
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
using namespace SourceHook;
 | 
					using namespace SourceHook;
 | 
				
			||||||
@ -86,7 +81,7 @@ protected:
 | 
				
			|||||||
	unsigned int m_nMarkSerial;
 | 
						unsigned int m_nMarkSerial;
 | 
				
			||||||
	List<WeakNative> m_WeakRefs;
 | 
						List<WeakNative> m_WeakRefs;
 | 
				
			||||||
	ke::Vector<const sp_nativeinfo_t *> m_natives;
 | 
						ke::Vector<const sp_nativeinfo_t *> m_natives;
 | 
				
			||||||
	List<NativeEntry *> m_Natives;
 | 
						ke::Vector<ke::Ref<Native> > m_fakes;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern CNativeOwner g_CoreNatives;
 | 
					extern CNativeOwner g_CoreNatives;
 | 
				
			||||||
 | 
				
			|||||||
@ -596,9 +596,7 @@ IPhraseCollection *CPlugin::GetPhrases()
 | 
				
			|||||||
void CPlugin::DependencyDropped(CPlugin *pOwner)
 | 
					void CPlugin::DependencyDropped(CPlugin *pOwner)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (!m_pRuntime)
 | 
						if (!m_pRuntime)
 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	List<String>::iterator reqlib_iter;
 | 
						List<String>::iterator reqlib_iter;
 | 
				
			||||||
	List<String>::iterator lib_iter;
 | 
						List<String>::iterator lib_iter;
 | 
				
			||||||
@ -607,30 +605,22 @@ void CPlugin::DependencyDropped(CPlugin *pOwner)
 | 
				
			|||||||
		for (reqlib_iter=m_RequiredLibs.begin(); reqlib_iter!=m_RequiredLibs.end(); reqlib_iter++)
 | 
							for (reqlib_iter=m_RequiredLibs.begin(); reqlib_iter!=m_RequiredLibs.end(); reqlib_iter++)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			if ((*reqlib_iter) == (*lib_iter))
 | 
								if ((*reqlib_iter) == (*lib_iter))
 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				m_LibraryMissing = true;
 | 
									m_LibraryMissing = true;
 | 
				
			||||||
		}	
 | 
							}	
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	List<NativeEntry *>::iterator iter;
 | 
					 | 
				
			||||||
	NativeEntry *pNative;
 | 
					 | 
				
			||||||
	sp_native_t *native;
 | 
					 | 
				
			||||||
	uint32_t idx;
 | 
					 | 
				
			||||||
	unsigned int unbound = 0;
 | 
						unsigned int unbound = 0;
 | 
				
			||||||
 | 
						for (size_t i = 0; i < pOwner->m_fakes.length(); i++)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							ke::Ref<Native> entry(pOwner->m_fakes[i]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (iter = pOwner->m_Natives.begin();
 | 
							uint32_t idx;
 | 
				
			||||||
		 iter != pOwner->m_Natives.end();
 | 
							if (m_pRuntime->FindNativeByName(entry->name(), &idx) != SP_ERROR_NONE)
 | 
				
			||||||
		 iter++)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		pNative = (*iter);
 | 
					 | 
				
			||||||
		/* Find this native! */
 | 
					 | 
				
			||||||
		if (m_pRuntime->FindNativeByName(pNative->name(), &idx) != SP_ERROR_NONE)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
		}
 | 
					
 | 
				
			||||||
		/* Unbind it */
 | 
							sp_native_t *native;
 | 
				
			||||||
		m_pRuntime->GetNativeByIndex(idx, &native);
 | 
							m_pRuntime->GetNativeByIndex(idx, &native);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		native->pfn = NULL;
 | 
							native->pfn = NULL;
 | 
				
			||||||
		native->status = SP_NATIVE_UNBOUND;
 | 
							native->status = SP_NATIVE_UNBOUND;
 | 
				
			||||||
		unbound++;
 | 
							unbound++;
 | 
				
			||||||
@ -722,15 +712,11 @@ void CPlugin::DropEverything()
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
bool CPlugin::AddFakeNative(IPluginFunction *pFunc, const char *name, SPVM_FAKENATIVE_FUNC func)
 | 
					bool CPlugin::AddFakeNative(IPluginFunction *pFunc, const char *name, SPVM_FAKENATIVE_FUNC func)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	NativeEntry *pEntry;
 | 
						ke::Ref<Native> entry = g_ShareSys.AddFakeNative(pFunc, name, func);
 | 
				
			||||||
 | 
						if (!entry)
 | 
				
			||||||
	if ((pEntry = g_ShareSys.AddFakeNative(pFunc, name, func)) == NULL)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		return false;
 | 
							return false;
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	m_Natives.push_back(pEntry);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						m_fakes.append(entry);
 | 
				
			||||||
	return true;
 | 
						return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1383,15 +1369,14 @@ bool CPluginManager::RunSecondPass(CPlugin *pPlugin, char *error, size_t maxleng
 | 
				
			|||||||
	pPlugin->Call_OnPluginStart();
 | 
						pPlugin->Call_OnPluginStart();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Now, if we have fake natives, go through all plugins that might need rebinding */
 | 
						/* Now, if we have fake natives, go through all plugins that might need rebinding */
 | 
				
			||||||
	if (pPlugin->GetStatus() <= Plugin_Paused && pPlugin->m_Natives.size())
 | 
						if (pPlugin->GetStatus() <= Plugin_Paused && pPlugin->m_fakes.length())
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		List<CPlugin *>::iterator pl_iter;
 | 
							List<CPlugin *>::iterator pl_iter;
 | 
				
			||||||
		CPlugin *pOther;
 | 
					 | 
				
			||||||
		for (pl_iter = m_plugins.begin();
 | 
							for (pl_iter = m_plugins.begin();
 | 
				
			||||||
			 pl_iter != m_plugins.end();
 | 
								 pl_iter != m_plugins.end();
 | 
				
			||||||
			 pl_iter++)
 | 
								 pl_iter++)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			pOther = (*pl_iter);
 | 
								CPlugin *pOther = (*pl_iter);
 | 
				
			||||||
			if ((pOther->GetStatus() == Plugin_Error
 | 
								if ((pOther->GetStatus() == Plugin_Error
 | 
				
			||||||
				&& (pOther->m_FakeNativesMissing || pOther->m_LibraryMissing))
 | 
									&& (pOther->m_FakeNativesMissing || pOther->m_LibraryMissing))
 | 
				
			||||||
				|| pOther->m_FakeNativesMissing)
 | 
									|| pOther->m_FakeNativesMissing)
 | 
				
			||||||
@ -1402,13 +1387,8 @@ bool CPluginManager::RunSecondPass(CPlugin *pPlugin, char *error, size_t maxleng
 | 
				
			|||||||
					  || pOther->GetStatus() == Plugin_Paused)
 | 
										  || pOther->GetStatus() == Plugin_Paused)
 | 
				
			||||||
					 && pOther != pPlugin)
 | 
										 && pOther != pPlugin)
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				List<NativeEntry *>::iterator nv_iter;
 | 
									for (size_t i = 0; i < pPlugin->m_fakes.length(); i++)
 | 
				
			||||||
				for (nv_iter = pPlugin->m_Natives.begin();
 | 
										g_ShareSys.BindNativeToPlugin(pOther, pPlugin->m_fakes[i]);
 | 
				
			||||||
					 nv_iter != pPlugin->m_Natives.end();
 | 
					 | 
				
			||||||
					 nv_iter++)
 | 
					 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
					g_ShareSys.BindNativeToPlugin(pOther, (*nv_iter));
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
				
			|||||||
@ -37,6 +37,8 @@
 | 
				
			|||||||
#include "HandleSys.h"
 | 
					#include "HandleSys.h"
 | 
				
			||||||
#include <assert.h>
 | 
					#include <assert.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using namespace ke;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ShareSystem g_ShareSys;
 | 
					ShareSystem g_ShareSys;
 | 
				
			||||||
static unsigned int g_mark_serial = 0;
 | 
					static unsigned int g_mark_serial = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -259,12 +261,12 @@ void ShareSystem::OverrideNatives(IExtension *myself, const sp_nativeinfo_t *nat
 | 
				
			|||||||
	assert(false);
 | 
						assert(false);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
NativeEntry *ShareSystem::FindNative(const char *name)
 | 
					PassRef<Native> ShareSystem::FindNative(const char *name)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	NativeEntry *entry;
 | 
						NativeCache::Result r = m_NtvCache.find(name);
 | 
				
			||||||
	if (!m_NtvCache.retrieve(name, &entry))
 | 
						if (!r.found())
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
	return entry;
 | 
						return *r;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void ShareSystem::BindNativesToPlugin(CPlugin *pPlugin, bool bCoreOnly)
 | 
					void ShareSystem::BindNativesToPlugin(CPlugin *pPlugin, bool bCoreOnly)
 | 
				
			||||||
@ -290,7 +292,7 @@ void ShareSystem::BindNativesToPlugin(CPlugin *pPlugin, bool bCoreOnly)
 | 
				
			|||||||
			continue;
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* Otherwise, the native must be in our cache. */
 | 
							/* Otherwise, the native must be in our cache. */
 | 
				
			||||||
		NativeEntry *pEntry = FindNative(native->name);
 | 
							Ref<Native> pEntry = FindNative(native->name);
 | 
				
			||||||
		if (!pEntry)
 | 
							if (!pEntry)
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -301,41 +303,32 @@ void ShareSystem::BindNativesToPlugin(CPlugin *pPlugin, bool bCoreOnly)
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void ShareSystem::BindNativeToPlugin(CPlugin *pPlugin, NativeEntry *pEntry)
 | 
					void ShareSystem::BindNativeToPlugin(CPlugin *pPlugin, const Ref<Native> &entry)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						if (!entry->owner)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						IPluginContext *pContext = pPlugin->GetBaseContext();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	uint32_t i;
 | 
						uint32_t i;
 | 
				
			||||||
 | 
						if (pContext->FindNativeByName(entry->name(), &i) != SP_ERROR_NONE)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sp_native_t *native;
 | 
						sp_native_t *native;
 | 
				
			||||||
	IPluginContext *pContext;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	pContext = pPlugin->GetBaseContext();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (pContext->FindNativeByName(pEntry->name(), &i) != SP_ERROR_NONE)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		return;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if (pContext->GetNativeByIndex(i, &native) != SP_ERROR_NONE)
 | 
						if (pContext->GetNativeByIndex(i, &native) != SP_ERROR_NONE)
 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (native->status == SP_NATIVE_BOUND)
 | 
						if (native->status == SP_NATIVE_BOUND)
 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						BindNativeToPlugin(pPlugin, native, i, entry);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	BindNativeToPlugin(pPlugin, native, i, pEntry);
 | 
					void ShareSystem::BindNativeToPlugin(CPlugin *pPlugin, sp_native_t *native, uint32_t index,
 | 
				
			||||||
}
 | 
					                                     const Ref<Native> &pEntry)
 | 
				
			||||||
 | 
					 | 
				
			||||||
void ShareSystem::BindNativeToPlugin(CPlugin *pPlugin, 
 | 
					 | 
				
			||||||
									 sp_native_t *native,
 | 
					 | 
				
			||||||
									 uint32_t index,
 | 
					 | 
				
			||||||
									 NativeEntry *pEntry)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	/* Mark as bound... we do the rest next. */
 | 
						/* Mark as bound... we do the rest next. */
 | 
				
			||||||
	native->status = SP_NATIVE_BOUND;
 | 
						native->status = SP_NATIVE_BOUND;
 | 
				
			||||||
	native->user = pEntry;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Perform a bind. */
 | 
					 | 
				
			||||||
	native->pfn = pEntry->func();
 | 
						native->pfn = pEntry->func();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* We don't bother with dependency crap if the owner is Core. */
 | 
						/* We don't bother with dependency crap if the owner is Core. */
 | 
				
			||||||
@ -345,15 +338,11 @@ void ShareSystem::BindNativeToPlugin(CPlugin *pPlugin,
 | 
				
			|||||||
		if ((native->flags & SP_NTVFLAG_OPTIONAL) == SP_NTVFLAG_OPTIONAL)
 | 
							if ((native->flags & SP_NTVFLAG_OPTIONAL) == SP_NTVFLAG_OPTIONAL)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			/* Only add if there is a valid owner. */
 | 
								/* Only add if there is a valid owner. */
 | 
				
			||||||
			if (pEntry->owner != NULL)
 | 
								if (pEntry->owner)
 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				pEntry->owner->AddWeakRef(WeakNative(pPlugin, index));
 | 
									pEntry->owner->AddWeakRef(WeakNative(pPlugin, index));
 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			else
 | 
								else
 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				native->status = SP_NATIVE_UNBOUND;
 | 
									native->status = SP_NATIVE_UNBOUND;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		/* Otherwise, we're a strong dependent and not a weak one */
 | 
							/* Otherwise, we're a strong dependent and not a weak one */
 | 
				
			||||||
		else
 | 
							else
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
@ -373,23 +362,15 @@ void ShareSystem::BindNativeToPlugin(CPlugin *pPlugin,
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
NativeEntry *ShareSystem::AddNativeToCache(CNativeOwner *pOwner, const sp_nativeinfo_t *ntv)
 | 
					PassRef<Native> ShareSystem::AddNativeToCache(CNativeOwner *pOwner, const sp_nativeinfo_t *ntv)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	NativeEntry *pEntry;
 | 
						NativeCache::Insert i = m_NtvCache.findForAdd(ntv->name);
 | 
				
			||||||
 | 
						if (i.found())
 | 
				
			||||||
	if ((pEntry = FindNative(ntv->name)) == NULL)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		pEntry = new NativeEntry(pOwner, ntv);
 | 
					 | 
				
			||||||
		m_NtvCache.insert(ntv->name, pEntry);
 | 
					 | 
				
			||||||
		return pEntry;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (pEntry->owner != NULL)
 | 
					 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pEntry->owner = pOwner;
 | 
						Ref<Native> entry = Newborn<Native>(new Native(pOwner, ntv));
 | 
				
			||||||
	pEntry->native = NULL;
 | 
						m_NtvCache.insert(ntv->name, entry);
 | 
				
			||||||
	return pEntry;
 | 
						return entry;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
FakeNative::~FakeNative()
 | 
					FakeNative::~FakeNative()
 | 
				
			||||||
@ -399,27 +380,27 @@ FakeNative::~FakeNative()
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
void ShareSystem::ClearNativeFromCache(CNativeOwner *pOwner, const char *name)
 | 
					void ShareSystem::ClearNativeFromCache(CNativeOwner *pOwner, const char *name)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	NativeEntry *pEntry;
 | 
						NativeCache::Result r = m_NtvCache.find(name);
 | 
				
			||||||
 | 
						if (!r.found())
 | 
				
			||||||
	if ((pEntry = FindNative(name)) == NULL)
 | 
					 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (pEntry->owner != pOwner)
 | 
						Ref<Native> entry(*r);
 | 
				
			||||||
 | 
						if (entry->owner != pOwner)
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pEntry->fake = NULL;
 | 
						// Clear out the owner bit as a sanity measure.
 | 
				
			||||||
	pEntry->native = NULL;
 | 
						entry->owner = NULL;
 | 
				
			||||||
	pEntry->owner = NULL;
 | 
					
 | 
				
			||||||
 | 
						m_NtvCache.remove(r);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
NativeEntry *ShareSystem::AddFakeNative(IPluginFunction *pFunc, const char *name, SPVM_FAKENATIVE_FUNC func)
 | 
					PassRef<Native> ShareSystem::AddFakeNative(IPluginFunction *pFunc, const char *name, SPVM_FAKENATIVE_FUNC func)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	NativeEntry *pEntry;
 | 
						Ref<Native> entry(FindNative(name));
 | 
				
			||||||
 | 
						if (entry)
 | 
				
			||||||
	if ((pEntry = FindNative(name)) != NULL && pEntry->owner != NULL)
 | 
					 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ke::AutoPtr<FakeNative> fake(new FakeNative(name, pFunc));
 | 
						AutoPtr<FakeNative> fake(new FakeNative(name, pFunc));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fake->gate = g_pSourcePawn2->CreateFakeNative(func, fake);
 | 
						fake->gate = g_pSourcePawn2->CreateFakeNative(func, fake);
 | 
				
			||||||
	if (!fake->gate)
 | 
						if (!fake->gate)
 | 
				
			||||||
@ -427,16 +408,10 @@ NativeEntry *ShareSystem::AddFakeNative(IPluginFunction *pFunc, const char *name
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	CNativeOwner *owner = g_PluginSys.GetPluginByCtx(fake->ctx->GetContext());
 | 
						CNativeOwner *owner = g_PluginSys.GetPluginByCtx(fake->ctx->GetContext());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!pEntry)
 | 
						entry = Newborn<Native>(new Native(owner, fake.take()));
 | 
				
			||||||
	{
 | 
						m_NtvCache.insert(name, entry);
 | 
				
			||||||
		pEntry = new NativeEntry(owner, fake.take());
 | 
					 | 
				
			||||||
		m_NtvCache.insert(name, pEntry);
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		pEntry->owner = owner;
 | 
					 | 
				
			||||||
		pEntry->fake = fake.take();
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return pEntry;
 | 
						return entry;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void ShareSystem::AddCapabilityProvider(IExtension *myself, IFeatureProvider *provider,
 | 
					void ShareSystem::AddCapabilityProvider(IExtension *myself, IFeatureProvider *provider,
 | 
				
			||||||
@ -496,13 +471,10 @@ FeatureStatus ShareSystem::TestNative(IPluginRuntime *pRuntime, const char *name
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	NativeEntry *entry = FindNative(name);
 | 
						Ref<Native> entry = FindNative(name);
 | 
				
			||||||
	if (!entry)
 | 
						if (!entry)
 | 
				
			||||||
		return FeatureStatus_Unknown;
 | 
							return FeatureStatus_Unknown;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (entry->owner)
 | 
					 | 
				
			||||||
		return FeatureStatus_Available;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return FeatureStatus_Unavailable;
 | 
						return FeatureStatus_Unavailable;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -36,10 +36,12 @@
 | 
				
			|||||||
#include <IHandleSys.h>
 | 
					#include <IHandleSys.h>
 | 
				
			||||||
#include <am-string.h>
 | 
					#include <am-string.h>
 | 
				
			||||||
#include <am-utility.h>
 | 
					#include <am-utility.h>
 | 
				
			||||||
 | 
					#include <am-refcounting.h>
 | 
				
			||||||
#include <sh_list.h>
 | 
					#include <sh_list.h>
 | 
				
			||||||
#include <sm_stringhashmap.h>
 | 
					#include <sm_stringhashmap.h>
 | 
				
			||||||
#include <sm_namehashset.h>
 | 
					#include <sm_namehashset.h>
 | 
				
			||||||
#include "common_logic.h"
 | 
					#include "common_logic.h"
 | 
				
			||||||
 | 
					#include "Native.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
using namespace SourceHook;
 | 
					using namespace SourceHook;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -64,68 +66,8 @@ struct IfaceInfo
 | 
				
			|||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class CNativeOwner;
 | 
					class CNativeOwner;
 | 
				
			||||||
struct NativeEntry;
 | 
					 | 
				
			||||||
class CPlugin;
 | 
					class CPlugin;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct FakeNative
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	FakeNative(const char *name, IPluginFunction *fun)
 | 
					 | 
				
			||||||
		: name(name),
 | 
					 | 
				
			||||||
		  ctx(fun->GetParentContext()),
 | 
					 | 
				
			||||||
		  call(fun),
 | 
					 | 
				
			||||||
		  gate(NULL)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	~FakeNative();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ke::AString name;
 | 
					 | 
				
			||||||
	IPluginContext *ctx;
 | 
					 | 
				
			||||||
	IPluginFunction *call;
 | 
					 | 
				
			||||||
	SPVM_NATIVE_FUNC gate;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct NativeEntry
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	NativeEntry(CNativeOwner *owner, const sp_nativeinfo_t *native)
 | 
					 | 
				
			||||||
		: owner(owner),
 | 
					 | 
				
			||||||
		  native(native),
 | 
					 | 
				
			||||||
		  fake(NULL)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	NativeEntry(CNativeOwner *owner, FakeNative *fake)
 | 
					 | 
				
			||||||
		: owner(owner),
 | 
					 | 
				
			||||||
		  native(NULL),
 | 
					 | 
				
			||||||
		  fake(fake)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	CNativeOwner *owner;
 | 
					 | 
				
			||||||
	const sp_nativeinfo_t *native;
 | 
					 | 
				
			||||||
	ke::AutoPtr<FakeNative> fake;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	SPVM_NATIVE_FUNC func() const
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		if (native)
 | 
					 | 
				
			||||||
			return native->func;
 | 
					 | 
				
			||||||
		if (fake)
 | 
					 | 
				
			||||||
			return fake->gate;
 | 
					 | 
				
			||||||
		return NULL;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	const char *name() const
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		if (native)
 | 
					 | 
				
			||||||
			return native->name;
 | 
					 | 
				
			||||||
		if (fake)
 | 
					 | 
				
			||||||
			return fake->name.chars();
 | 
					 | 
				
			||||||
		return NULL;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	static inline bool matches(const char *name, const NativeEntry *entry)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		return strcmp(name, entry->name()) == 0;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct Capability
 | 
					struct Capability
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	IExtension *ext;
 | 
						IExtension *ext;
 | 
				
			||||||
@ -178,23 +120,22 @@ public:
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
	void BindNativesToPlugin(CPlugin *pPlugin, bool bCoreOnly);
 | 
						void BindNativesToPlugin(CPlugin *pPlugin, bool bCoreOnly);
 | 
				
			||||||
	void BindNativeToPlugin(CPlugin *pPlugin, NativeEntry *pEntry);
 | 
						void BindNativeToPlugin(CPlugin *pPlugin, const ke::Ref<Native> &pEntry);
 | 
				
			||||||
	NativeEntry *AddFakeNative(IPluginFunction *pFunc, const char *name, SPVM_FAKENATIVE_FUNC func);
 | 
						ke::PassRef<Native> AddFakeNative(IPluginFunction *pFunc, const char *name, SPVM_FAKENATIVE_FUNC func);
 | 
				
			||||||
	NativeEntry *FindNative(const char *name);
 | 
						ke::PassRef<Native> FindNative(const char *name);
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
	NativeEntry *AddNativeToCache(CNativeOwner *pOwner, const sp_nativeinfo_t *ntv);
 | 
						ke::PassRef<Native> AddNativeToCache(CNativeOwner *pOwner, const sp_nativeinfo_t *ntv);
 | 
				
			||||||
	void ClearNativeFromCache(CNativeOwner *pOwner, const char *name);
 | 
						void ClearNativeFromCache(CNativeOwner *pOwner, const char *name);
 | 
				
			||||||
	void BindNativeToPlugin(CPlugin *pPlugin, 
 | 
						void BindNativeToPlugin(CPlugin *pPlugin, sp_native_t *ntv,  uint32_t index, const ke::Ref<Native> &pEntry);
 | 
				
			||||||
		sp_native_t *ntv, 
 | 
					 | 
				
			||||||
		uint32_t index, 
 | 
					 | 
				
			||||||
		NativeEntry *pEntry);
 | 
					 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
 | 
						typedef NameHashSet<ke::Ref<Native>, Native> NativeCache;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	List<IfaceInfo> m_Interfaces;
 | 
						List<IfaceInfo> m_Interfaces;
 | 
				
			||||||
	HandleType_t m_TypeRoot;
 | 
						HandleType_t m_TypeRoot;
 | 
				
			||||||
	IdentityToken_t m_IdentRoot;
 | 
						IdentityToken_t m_IdentRoot;
 | 
				
			||||||
	HandleType_t m_IfaceType;
 | 
						HandleType_t m_IfaceType;
 | 
				
			||||||
	IdentityType_t m_CoreType;
 | 
						IdentityType_t m_CoreType;
 | 
				
			||||||
	NameHashSet<NativeEntry *> m_NtvCache;
 | 
						NativeCache m_NtvCache;
 | 
				
			||||||
	StringHashMap<Capability> m_caps;
 | 
						StringHashMap<Capability> m_caps;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,4 @@
 | 
				
			|||||||
// vim: set sts=8 ts=2 sw=2 tw=99 et:
 | 
					// vim: set sts=8 ts=4 sw=4 tw=99 et:
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
// Copyright (C) 2013, David Anderson and AlliedModders LLC
 | 
					// Copyright (C) 2013, David Anderson and AlliedModders LLC
 | 
				
			||||||
// All rights reserved.
 | 
					// All rights reserved.
 | 
				
			||||||
@ -31,6 +31,7 @@
 | 
				
			|||||||
#define _include_amtl_refcounting_h_
 | 
					#define _include_amtl_refcounting_h_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <am-utility.h>
 | 
					#include <am-utility.h>
 | 
				
			||||||
 | 
					#include <am-moveable.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace ke {
 | 
					namespace ke {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -189,6 +190,11 @@ class Ref
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        AddRef();
 | 
					        AddRef();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    Ref(Moveable<Ref> other)
 | 
				
			||||||
 | 
					      : thing_(other->thing_)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        other->thing_ = NULL;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    template <typename S>
 | 
					    template <typename S>
 | 
				
			||||||
    Ref(const Ref<S> &other)
 | 
					    Ref(const Ref<S> &other)
 | 
				
			||||||
      : thing_(*other)
 | 
					      : thing_(*other)
 | 
				
			||||||
@ -255,6 +261,13 @@ class Ref
 | 
				
			|||||||
        return *this;
 | 
					        return *this;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Ref &operator =(Moveable<Ref> other) {
 | 
				
			||||||
 | 
					        Release();
 | 
				
			||||||
 | 
					        thing_ = other->thing_;
 | 
				
			||||||
 | 
					        other->thing_ = NULL;
 | 
				
			||||||
 | 
					        return *this;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private:
 | 
					  private:
 | 
				
			||||||
    void AddRef() {
 | 
					    void AddRef() {
 | 
				
			||||||
        if (thing_)
 | 
					        if (thing_)
 | 
				
			||||||
 | 
				
			|||||||
@ -107,6 +107,26 @@ public:
 | 
				
			|||||||
	typedef typename Internal::Insert Insert;
 | 
						typedef typename Internal::Insert Insert;
 | 
				
			||||||
	typedef typename Internal::iterator iterator;
 | 
						typedef typename Internal::iterator iterator;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Result find(const char *aKey)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							return table_.find(aKey);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Insert findForAdd(const char *aKey)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							return table_.findForAdd(aKey);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						void add(Insert &i, const T &value)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							return table_.add(i, value);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						void add(Insert &i, ke::Moveable<T> value)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							return table_.add(i, value);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool retrieve(const char *aKey, T *value)
 | 
						bool retrieve(const char *aKey, T *value)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		CharsAndLength key(aKey);
 | 
							CharsAndLength key(aKey);
 | 
				
			||||||
@ -126,6 +146,15 @@ public:
 | 
				
			|||||||
		return table_.add(i, value);
 | 
							return table_.add(i, value);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bool insert(const char *aKey, ke::Moveable<T> value)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							CharsAndLength key(aKey);
 | 
				
			||||||
 | 
							Insert i = table_.findForAdd(key);
 | 
				
			||||||
 | 
							if (i.found())
 | 
				
			||||||
 | 
								return false;
 | 
				
			||||||
 | 
							return table_.add(i, value);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool contains(const char *aKey)
 | 
						bool contains(const char *aKey)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		CharsAndLength key(aKey);
 | 
							CharsAndLength key(aKey);
 | 
				
			||||||
@ -143,6 +172,11 @@ public:
 | 
				
			|||||||
		return true;
 | 
							return true;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						void remove(Result &r)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							table_.remove(r);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void clear()
 | 
						void clear()
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		table_.clear();
 | 
							table_.clear();
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user