Use Refcounted to manage to NativeEntry (bug 5852 part 4, r=ds).

--HG--
extra : rebase_source : 2e08816db6819c9d9957a0e0ade9cd1aa420fd54
This commit is contained in:
David Anderson 2013-08-30 10:16:28 -07:00
parent 3da646f913
commit 4500964394
9 changed files with 227 additions and 208 deletions

98
core/logic/Native.h Normal file
View 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_

View File

@ -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();

View File

@ -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)

View File

@ -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;

View File

@ -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));
}
} }
} }
} }

View File

@ -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;
} }

View File

@ -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;
}; };

View File

@ -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_)

View File

@ -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();