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();
|
||||||
|
@ -78,7 +78,7 @@ void CNativeOwner::PropagateMarkSerial(unsigned int serial)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CNativeOwner::UnbindWeakRef(const WeakNative & ref)
|
void CNativeOwner::UnbindWeakRef(const WeakNative &ref)
|
||||||
{
|
{
|
||||||
sp_native_t *native;
|
sp_native_t *native;
|
||||||
IPluginContext *pContext;
|
IPluginContext *pContext;
|
||||||
@ -86,25 +86,13 @@ 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 */
|
native->status = SP_NATIVE_UNBOUND;
|
||||||
if (ref.entry == NULL)
|
native->pfn = NULL;
|
||||||
{
|
|
||||||
native->status = SP_NATIVE_UNBOUND;
|
|
||||||
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++)
|
||||||
for (iter = pOwner->m_Natives.begin();
|
|
||||||
iter != pOwner->m_Natives.end();
|
|
||||||
iter++)
|
|
||||||
{
|
{
|
||||||
pNative = (*iter);
|
ke::Ref<Native> entry(pOwner->m_fakes[i]);
|
||||||
/* Find this native! */
|
|
||||||
if (m_pRuntime->FindNativeByName(pNative->name(), &idx) != SP_ERROR_NONE)
|
uint32_t idx;
|
||||||
{
|
if (m_pRuntime->FindNativeByName(entry->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, pEntry);
|
BindNativeToPlugin(pPlugin, native, i, entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShareSystem::BindNativeToPlugin(CPlugin *pPlugin,
|
void ShareSystem::BindNativeToPlugin(CPlugin *pPlugin, sp_native_t *native, uint32_t index,
|
||||||
sp_native_t *native,
|
const Ref<Native> &pEntry)
|
||||||
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,14 +338,10 @@ 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