Eliminate Newborn/NoAddRef (bug 5907, r=ds).

This commit is contained in:
David Anderson 2014-08-22 22:50:25 -07:00
parent 0cf8eb2854
commit 9267d0c803
7 changed files with 53 additions and 23 deletions

View File

@ -383,7 +383,7 @@ bool ConCmdManager::AddAdminCommand(IPluginFunction *pFunction,
{ {
if (!m_CmdGrps.add(i, group)) if (!m_CmdGrps.add(i, group))
return false; return false;
i->value = NoAddRef(new CommandGroup()); i->value = new CommandGroup();
} }
Ref<CommandGroup> cmdgroup = i->value; Ref<CommandGroup> cmdgroup = i->value;

View File

@ -1082,6 +1082,7 @@ bool GameConfigManager::LoadGameConfigFile(const char *file, IGameConfig **_pCon
} }
pConfig = new CGameConfig(file); pConfig = new CGameConfig(file);
pConfig->AddRef();
/* :HACKHACK: Don't parse the main config file */ /* :HACKHACK: Don't parse the main config file */
bool retval = true; bool retval = true;

View File

@ -375,7 +375,7 @@ PassRef<Native> ShareSystem::AddNativeToCache(CNativeOwner *pOwner, const sp_nat
if (i.found()) if (i.found())
return NULL; return NULL;
Ref<Native> entry = Newborn<Native>(new Native(pOwner, ntv)); Ref<Native> entry = new Native(pOwner, ntv);
m_NtvCache.insert(ntv->name, entry); m_NtvCache.insert(ntv->name, entry);
return entry; return entry;
} }
@ -415,7 +415,7 @@ PassRef<Native> ShareSystem::AddFakeNative(IPluginFunction *pFunc, const char *n
CNativeOwner *owner = g_PluginSys.GetPluginByCtx(fake->ctx->GetContext()); CNativeOwner *owner = g_PluginSys.GetPluginByCtx(fake->ctx->GetContext());
entry = Newborn<Native>(new Native(owner, fake.take())); entry = new Native(owner, fake.take());
m_NtvCache.insert(name, entry); m_NtvCache.insert(name, entry);
return entry; return entry;

View File

@ -163,7 +163,7 @@ private:
cell_t data_; cell_t data_;
}; };
struct CellTrie : public ke::Refcounted<CellTrie> struct CellTrie
{ {
StringHashMap<Entry> map; StringHashMap<Entry> map;
}; };
@ -204,8 +204,7 @@ public: //IHandleTypeDispatch
{ {
if (type == htCellTrie) if (type == htCellTrie)
{ {
CellTrie *pTrie = (CellTrie *)object; delete (CellTrie *)object;
pTrie->Release();
} else { } else {
TrieSnapshot *snapshot = (TrieSnapshot *)object; TrieSnapshot *snapshot = (TrieSnapshot *)object;
delete snapshot; delete snapshot;

View File

@ -219,7 +219,7 @@ void ClientPrefs::DatabaseConnect()
char error[256]; char error[256];
int errCode = 0; int errCode = 0;
Database = Newborn<IDatabase>(Driver->Connect(DBInfo, true, error, sizeof(error))); Database = AdoptRef(Driver->Connect(DBInfo, true, error, sizeof(error)));
if (!Database) if (!Database)
{ {

View File

@ -35,12 +35,15 @@
namespace ke { namespace ke {
// See the comment above Refcounted<T> for more information. This class is
// identical, except changing the reference count is guaranteed to be atomic
// with respect to other threads changing the reference count.
template <typename T> template <typename T>
class RefcountedThreadsafe class RefcountedThreadsafe
{ {
public: public:
RefcountedThreadsafe() RefcountedThreadsafe()
: refcount_(1) : refcount_(0)
{ {
} }

View File

@ -37,18 +37,28 @@ namespace ke {
template <typename T> class Ref; template <typename T> class Ref;
// Holds a refcounted T without addrefing it. This is similar to PassRef<> // Objects in AMTL inheriting from Refcounted will have an initial refcount
// below, but is intended only for freshly allocated objects which start // of 0. However, in some systems (such as COM), the initial refcount is 1,
// with reference count 1, and we don't want to add an extra ref just by // or functions may return raw pointers that have been AddRef'd. In these
// assigning to PassRef<> or Ref<>. // cases it would be a mistake to use Ref<> or PassRef<>, since the object
// would leak an extra reference.
//
// This container holds a refcounted object without addrefing it. This is
// intended only for interacting with functions which return an object that
// has been manually AddRef'd. Note that this will perform a Release(), so
// so it is necessary to assign it to retain the object.
template <typename T> template <typename T>
class Newborn class AlreadyRefed
{ {
public: public:
Newborn(T *t) AlreadyRefed(T *t)
: thing_(t) : thing_(t)
{ {
} }
~AlreadyRefed() {
if (thing_)
thing_->Release();
}
T *release() const { T *release() const {
return ReturnAndVoid(thing_); return ReturnAndVoid(thing_);
@ -59,10 +69,10 @@ class Newborn
}; };
template <typename T> template <typename T>
static inline Newborn<T> static inline AlreadyRefed<T>
NoAddRef(T *t) AdoptRef(T *t)
{ {
return Newborn<T>(t); return AlreadyRefed<T>(t);
} }
// When returning a value, we'd rather not be needlessly changing the refcount, // When returning a value, we'd rather not be needlessly changing the refcount,
@ -81,7 +91,14 @@ class PassRef
{ {
} }
PassRef(const Newborn<T *> &other) PassRef(const AlreadyRefed<T *> &other)
: thing_(other.release())
{
// Don't addref, newborn means already addref'd.
}
template <typename S>
PassRef(const AlreadyRefed<S *> &other)
: thing_(other.release()) : thing_(other.release())
{ {
// Don't addref, newborn means already addref'd. // Don't addref, newborn means already addref'd.
@ -134,7 +151,7 @@ class PassRef
private: private:
// Disallowed operators. // Disallowed operators.
PassRef &operator =(T *other); PassRef &operator =(T *other);
PassRef &operator =(Newborn<T> &other); PassRef &operator =(AlreadyRefed<T> &other);
void AddRef() { void AddRef() {
if (thing_) if (thing_)
@ -149,13 +166,18 @@ class PassRef
mutable T *thing_; mutable T *thing_;
}; };
// Classes which are refcounted should inherit from this. // Classes which are refcounted should inherit from this. Note that reference
// counts start at 0 in AMTL, rather than 1. This avoids the complexity of
// having to adopt the initial ref upon allocation. However, this also means
// invoking Release() on a newly allocated object is illegal. Newborn objects
// must either be assigned to a Ref or PassRef (NOT an AdoptRef/AlreadyRefed),
// or must be deleted using |delete|.
template <typename T> template <typename T>
class Refcounted class Refcounted
{ {
public: public:
Refcounted() Refcounted()
: refcount_(1) : refcount_(0)
{ {
} }
@ -217,7 +239,12 @@ class Ref
: thing_(other.release()) : thing_(other.release())
{ {
} }
Ref(const Newborn<T> &other) Ref(const AlreadyRefed<T> &other)
: thing_(other.release())
{
}
template <typename S>
Ref(const AlreadyRefed<S> &other)
: thing_(other.release()) : thing_(other.release())
{ {
} }
@ -255,7 +282,7 @@ class Ref
} }
template <typename S> template <typename S>
Ref &operator =(const Newborn<S> &other) { Ref &operator =(const AlreadyRefed<S> &other) {
Release(); Release();
thing_ = other.release(); thing_ = other.release();
return *this; return *this;