Reduce the copies C4Set makes

Mostly by changing functions to take a const reference, but also by using
move constructors. This helps with C4String leak debugging by reducing the
reference count changes.
floating-point
Günther Brammer 2012-07-26 01:21:15 +02:00
parent 576edc1e23
commit 91a6c309a9
4 changed files with 70 additions and 37 deletions

View File

@ -392,7 +392,7 @@ C4Effect * C4PropList::GetEffect()
template<> template<>
unsigned int C4Set<C4Property>::Hash<C4String *>(C4String * e)
unsigned int C4Set<C4Property>::Hash<C4String *>(C4String * const & e)
{
assert(e);
unsigned int hash = 4, tmp;
@ -411,13 +411,13 @@ unsigned int C4Set<C4Property>::Hash<C4String *>(C4String * e)
}
template<> template<>
bool C4Set<C4Property>::Equals<C4String *>(C4Property a, C4String * b)
bool C4Set<C4Property>::Equals<C4String *>(C4Property const & a, C4String * const & b)
{
return a.Key == b;
}
template<> template<>
unsigned int C4Set<C4Property>::Hash<C4Property>(C4Property p)
unsigned int C4Set<C4Property>::Hash<C4Property>(C4Property const & p)
{
return C4Set<C4Property>::Hash(p.Key);
}
@ -589,8 +589,9 @@ void C4PropList::SetPropertyByS(C4String * k, const C4Value & to)
}
else
{
C4Property p(k, to);
Properties.Add(p);
//C4Property p(k, to);
//Properties.Add(p);
Properties.Add(C4Property(k, to));
}
}
@ -600,7 +601,7 @@ void C4PropList::ResetProperty(C4String * k)
}
template<> template<>
unsigned int C4Set<C4PropListNumbered *>::Hash<int>(int e)
unsigned int C4Set<C4PropListNumbered *>::Hash<int>(int const & e)
{
unsigned int hash = 4, tmp;
hash += e >> 16;
@ -617,31 +618,31 @@ unsigned int C4Set<C4PropListNumbered *>::Hash<int>(int e)
}
template<> template<>
unsigned int C4Set<C4PropListNumbered *>::Hash<C4PropList *>(C4PropList * e)
unsigned int C4Set<C4PropListNumbered *>::Hash<C4PropList *>(C4PropList * const & e)
{
return Hash(e->GetPropListNumbered()->Number);
}
template<> template<>
unsigned int C4Set<C4PropListNumbered *>::Hash<C4PropListNumbered *>(C4PropListNumbered * e)
unsigned int C4Set<C4PropListNumbered *>::Hash<C4PropListNumbered *>(C4PropListNumbered * const & e)
{
return Hash(e->Number);
}
template<> template<>
bool C4Set<C4PropListNumbered *>::Equals<int>(C4PropListNumbered * a, int b)
bool C4Set<C4PropListNumbered *>::Equals<int>(C4PropListNumbered * const & a, int const & b)
{
return a->Number == b;
}
template<> template<>
bool C4Set<C4PropListNumbered *>::Equals<C4PropList *>(C4PropListNumbered * a, C4PropList * b)
bool C4Set<C4PropListNumbered *>::Equals<C4PropList *>(C4PropListNumbered * const & a, C4PropList * const & b)
{
return a == b;
}
template<> template<>
unsigned int C4Set<C4PropList *>::Hash<C4PropList *>(C4PropList * e)
unsigned int C4Set<C4PropList *>::Hash<C4PropList *>(C4PropList * const & e)
{
return C4Set<C4PropListNumbered *>::Hash(static_cast<int>(reinterpret_cast<intptr_t>(e)));
}

View File

@ -38,6 +38,11 @@ public:
C4Property(const C4Property &o) : Key(o.Key), Value(o.Value) { if (Key) Key->IncRef(); }
C4Property & operator = (const C4Property &o)
{ assert(o.Key); o.Key->IncRef(); if (Key) Key->DecRef(); Key = o.Key; Value = o.Value; return *this; }
#ifdef HAVE_RVALUE_REF
C4Property(C4Property && o) : Key(o.Key), Value(std::move(o.Value)) { o.Key = 0; }
C4Property & operator = (C4Property && o)
{ assert(o.Key); if (Key) Key->DecRef(); Key = o.Key; o.Key = 0; Value = std::move(o.Value); return *this; }
#endif
~C4Property() { if (Key) Key->DecRef(); }
void CompileFunc(StdCompiler *pComp, C4ValueNumbers *);
C4String * Key;

View File

@ -24,17 +24,18 @@
// *** C4Set
template<> template<>
unsigned int C4Set<C4String *>::Hash<const char *>(const char * s)
unsigned int C4Set<C4String *>::Hash<const char *>(const char * const & s)
{
// Fowler/Noll/Vo hash
unsigned int h = 2166136261u;
while (*s)
h = (h ^ *(s++)) * 16777619;
const char * p = s;
while (*p)
h = (h ^ *(p++)) * 16777619;
return h;
}
template<> template<>
bool C4Set<C4String *>::Equals<const char *>(C4String * a, const char * b)
bool C4Set<C4String *>::Equals<const char *>(C4String * const & a, const char * const & b)
{
return a->GetData() == b;
}

View File

@ -104,7 +104,7 @@ template<typename T> class C4Set
unsigned int Capacity;
unsigned int Size;
T * Table;
T * AddInternal(T e)
T * GetPlaceFor(T const & e)
{
unsigned int h = Hash(e);
T * p = &Table[h % Capacity];
@ -112,13 +112,43 @@ template<typename T> class C4Set
{
p = &Table[++h % Capacity];
}
return p;
}
T * AddInternal(T const & e)
{
T * p = GetPlaceFor(e);
*p = e;
return p;
}
#ifdef HAVE_RVALUE_REF
T * AddInternal(T && e)
{
T * p = GetPlaceFor(e);
*p = std::move(e);
return p;
}
#endif
void MaintainCapacity()
{
if (Capacity - Size < Max(2u, Capacity / 4))
{
unsigned int OCapacity = Capacity;
Capacity *= 2;
T * OTable = Table;
Table = new T[Capacity];
Clear();
for (unsigned int i = 0; i < OCapacity; ++i)
{
if (OTable[i])
AddInternal(std::move(OTable[i]));
}
delete [] OTable;
}
}
public:
template<typename H> static unsigned int Hash(H);
template<typename H> static bool Equals(T, H);
static bool Equals(T a, T b) { return a == b; }
template<typename H> static unsigned int Hash(const H &);
template<typename H> static bool Equals(const T &, const H &);
static bool Equals(const T & a, const T & b) { return a == b; }
C4Set(): Capacity(2), Size(0), Table(new T[Capacity])
{
Clear();
@ -167,26 +197,22 @@ public:
return !!*r;
}
unsigned int GetSize() const { return Size; }
T * Add(T e)
T * Add(T const & e)
{
if (Capacity - Size < Max(2u, Capacity / 4))
{
unsigned int OCapacity = Capacity;
Capacity *= 2;
T * OTable = Table;
Table = new T[Capacity];
Clear();
for (unsigned int i = 0; i < OCapacity; ++i)
{
if (OTable[i])
AddInternal(OTable[i]);
}
delete [] OTable;
}
MaintainCapacity();
T * r = AddInternal(e);
++Size;
return r;
}
#ifdef HAVE_RVALUE_REF
T * Add(T && e)
{
MaintainCapacity();
T * r = AddInternal(std::move(e));
++Size;
return r;
}
#endif
template<typename H> void Remove(H e)
{
unsigned int h = Hash(e);
@ -203,7 +229,7 @@ public:
{
T m = *r;
*r = 0;
AddInternal(m);
AddInternal(std::move(m));
}
}
T const * First() const { return Next(Table - 1); }
@ -230,12 +256,12 @@ public:
};
template<> template<>
inline unsigned int C4Set<C4String *>::Hash<const C4String *>(const C4String * e)
inline unsigned int C4Set<C4String *>::Hash<const C4String *>(const C4String * const & e)
{
return e->Hash;
}
template<> template<>
inline unsigned int C4Set<C4String *>::Hash<C4String *>(C4String * e)
inline unsigned int C4Set<C4String *>::Hash<C4String *>(C4String * const & e)
{
return e->Hash;
}