Permalink
Browse files

changed type info compare to no longer depend on string compares. fix…

…ed some issues in hashmap
  • Loading branch information...
1 parent e08a20b commit 05c440b0322d39cf98425f50172c468c6659efb8 @Ingrater committed Jul 14, 2012
View
@@ -89,7 +89,6 @@ class TypeInfo
{
enum Type {
Info,
- Native,
Vector,
Typedef,
Enum,
@@ -100,15 +99,39 @@ class TypeInfo
Function,
Delegate,
Class,
+ Obj,
Interface,
Struct,
Tuple,
Const,
Immutable,
Shared,
- Inout
+ Inout,
+ Byte,
+ UByte,
+ Short,
+ UShort,
+ Int,
+ UInt,
+ Long,
+ ULong,
+ Float,
+ IFloat,
+ CFloat,
+ Double,
+ IDouble,
+ CDouble,
+ Real,
+ IReal,
+ CReal,
+ Char,
+ WChar,
+ DChar,
+ Void,
+ Bool
}
+ string GetName() nothrow pure; //name, only implemented for structs, interfaces, classes, typedef, enum
hash_t getHash(in void* p);
equals_t equals(in void* p1, in void* p2);
int compare(in void* p1, in void* p2);
View
@@ -150,11 +150,17 @@ class StdAllocator : IAdvancedAllocator
alias g_stdAllocator globalInstance;
enum size_t alignment = 4; //default alignment 4 byte
+ enum BlockFlags
+ {
+ IsClass = 0x01
+ }
+
static struct MemoryBlockInfo
{
size_t size;
- long[10] backtrace;
- int backtraceSize;
+ size_t[10] backtrace;
+ byte backtraceSize;
+ ubyte flags; //combination of BlockFlags
this(size_t size)
{
@@ -245,7 +251,12 @@ class StdAllocator : IAdvancedAllocator
leakSum += leak.size;
if( !traceCache.exists(leak) )
{
- auto trace = StackTrace.resolveAddresses(leak.backtrace[0..leak.backtraceSize]);
+ long[10] backtrace;
+ for(int i=0; i<leak.backtraceSize; i++)
+ {
+ backtrace[i] = leak.backtrace[i];
+ }
+ auto trace = StackTrace.resolveAddresses(backtrace[0..leak.backtraceSize]);
TraceInfo traceinfo;
traceinfo.count = 1;
int i=0;
@@ -337,6 +348,36 @@ class StdAllocator : IAdvancedAllocator
if(log !is null) fprintf(log, "%s\n",info.trace[i].ptr);
}
}
+ if( leak.flags & BlockFlags.IsClass )
+ {
+ Object obj = cast(Object)addr;
+ TypeInfo t = obj.classinfo;
+ if(t is null)
+ {
+ printf("Already destroyed object");
+ if(log !is null) fprintf(log, "Already destroyed object");
+ }
+ else
+ {
+ string name = t.GetName();
+ printf("Object of type '");
+ if(log !is null) fprintf(log, "Object of type '");
+ for(int i=0; i<name.length; i++)
+ {
+ printf("%c", name[i]);
+ if(log !is null) fprintf(log, "%c", name[i]);
+ }
+ printf("'\n");
+ if(log !is null) fprintf(log, "'\n");
+ }
+
+ RefCounted refCounted = cast(RefCounted)obj;
+ if(refCounted !is null)
+ {
+ printf("Reference counted object: ref-count = %d\n", refCounted.refcount);
+ if(log !is null) fprintf(log, "Reference counted object: ref-count = %d\n", refCounted.refcount);
+ }
+ }
}
}
@@ -359,10 +400,18 @@ class StdAllocator : IAdvancedAllocator
Delete(g_trackingAllocator);
}
}
+
+ public void SetIsClass(void* mem)
+ {
+ if(m_memoryMap !is null && m_memoryMap.exists(mem))
+ {
+ m_memoryMap[mem].flags |= BlockFlags.IsClass;
+ }
+ }
final void[] AllocateMemory(size_t size)
{
- void* mem = (OnFreeMemoryCallback is null) ? null : OnAllocateMemoryCallback(size,alignment);
+ void* mem = (OnAllocateMemoryCallback is null) ? null : OnAllocateMemoryCallback(size,alignment);
if(mem is null)
{
version(DUMA)
@@ -381,7 +430,12 @@ class StdAllocator : IAdvancedAllocator
// TODO implement for linux / osx
version(Windows)
{
- info.backtraceSize = StackTrace.traceAddresses(info.backtrace,false,3).length;
+ long backtrace[10];
+ info.backtraceSize = cast(byte)StackTrace.traceAddresses(backtrace,false,3).length;
+ for(int i=0; i<info.backtraceSize; i++)
+ {
+ info.backtrace[i] = cast(size_t)backtrace[i];
+ }
}
auto map = m_memoryMap;
map[mem] = info;
@@ -437,7 +491,12 @@ class StdAllocator : IAdvancedAllocator
// TODO implement for linux / osx
version(Windows)
{
- info.backtraceSize = StackTrace.traceAddresses(info.backtrace,false,0).length;
+ long backtrace[10];
+ info.backtraceSize = cast(byte)StackTrace.traceAddresses(backtrace,false,3).length;
+ for(int i=0; i<info.backtraceSize; i++)
+ {
+ info.backtrace[i] = cast(size_t)backtrace[i];
+ }
}
//printf("realloc adding %x(%d)\n",mem,size);
@@ -551,13 +610,19 @@ auto AllocatorNew(T,AT,ARGS...)(AT allocator, ARGS args)
"Don't know how to initialize an object of type "
~ T.stringof ~ " with arguments:\n" ~ ARGS.stringof ~ "\nAvailable ctors:\n" ~ ListAvailableCtors!T() );
}
+
+ static if(is(AT == StdAllocator))
+ {
+ allocator.SetIsClass(mem.ptr);
+ }
static if(is(T : RefCounted))
{
result.SetAllocator(allocator);
- return SmartPtr!T(result);
+ return ReturnRefCounted!T(result);
}
- else {
+ else
+ {
return result;
}
}
@@ -669,6 +734,10 @@ struct composite(T)
void AllocatorDelete(T,AT)(AT allocator, T obj)
{
static assert(!is(T U == composite!U), "can not delete composited instance");
+ static if(is(T : RefCounted))
+ {
+ assert(obj.refcount == 0, "trying to delete reference counted object which is still referenced");
+ }
static if(is(T == class))
{
if(obj is null)
@@ -700,6 +769,10 @@ void AllocatorDelete(T,AT)(AT allocator, T obj)
callDtor(obj);
allocator.FreeMemory(cast(void*)obj.ptr);
}
+ else
+ {
+ static assert(0, "Can not delete " ~ T.stringof);
+ }
}
void AllocatorFree(T,AT)(AT allocator, T obj)
View
@@ -157,6 +157,13 @@ class Hashmap(K,V,HP = StdHashPolicy, AT = StdAllocator)
{
if(m_Data.ptr !is null)
{
+ foreach(ref p; m_Data)
+ {
+ if(p.state == State.Data)
+ {
+ callDtor(&p);
+ }
+ }
m_allocator.FreeMemory(m_Data.ptr);
m_Data = [];
}
@@ -176,6 +183,16 @@ class Hashmap(K,V,HP = StdHashPolicy, AT = StdAllocator)
memset(&m_Data[index], 0, Pair.sizeof);
m_Data[index].__ctor(key, value, State.Data);
}
+
+ private void move(ref Pair data)
+ {
+ size_t index = HP.Hash(data.key) % m_Data.length;
+ while(m_Data[index].state == State.Data)
+ {
+ index = (index + 1) % m_Data.length;
+ }
+ memcpy(m_Data.ptr + index, &data, Pair.sizeof);
+ }
void opIndexAssign(V value, K key)
{
@@ -196,7 +213,7 @@ class Hashmap(K,V,HP = StdHashPolicy, AT = StdAllocator)
foreach(ref entry; oldData)
{
if(entry.state == State.Data)
- insert(entry.key,entry.value);
+ move(entry);
}
m_allocator.FreeMemory(oldData.ptr);
}
View
@@ -74,6 +74,23 @@ public:
}
}
+/**
+ * Wrapper object without implicit conversion so the user recognizes he just allocated a reference counted object
+ */
+struct ReturnRefCounted(T)
+{
+ static assert(is(T : RefCounted),T.stringof ~ " is not a reference counted object");
+ T ptr;
+
+ this(T obj)
+ {
+ ptr = obj;
+ }
+}
+
+/**
+ * Smart pointer to safely hold reference counted objects
+ */
struct SmartPtr(T)
{
static assert(is(T : RefCounted),T.stringof ~ " is not a reference counted object");
@@ -93,6 +110,14 @@ struct SmartPtr(T)
if(ptr !is null)
ptr.AddReference();
}
+
+ this(ReturnRefCounted!T rh)
+ {
+ ptr = rh.ptr;
+ if(ptr !is null)
+ ptr.AddReference();
+ rh.ptr = null;
+ }
~this()
{
@@ -142,6 +167,27 @@ struct SmartPtr(T)
if(ptr !is null)
ptr.AddReference();
}
+
+ void opAssign(ReturnRefCounted!T rh)
+ {
+ if(ptr !is null)
+ ptr.RemoveReference();
+ ptr = rh.ptr;
+ if(ptr !is null)
+ ptr.AddReference();
+ rh.ptr = null;
+ }
+
+ //TODO reenable when bug 8295 is fixed
+ /*void opAssign(shared(ReturnRefCounted!T) rh) shared
+ {
+ if(ptr !is null)
+ ptr.RemoveReference();
+ ptr = rh.ptr;
+ if(ptr !is null)
+ ptr.AddReference();
+ rh.ptr = null;
+ }*/
}
final class RCArrayData(T, AT = StdAllocator) : RefCounted
@@ -191,6 +237,10 @@ public:
//call default ctor
result.__ctor(allocator);
+ static if(is(Allocator == StdAllocator))
+ {
+ allocator.SetIsClass(mem);
+ }
final switch(meminit)
{
@@ -533,6 +583,7 @@ struct RCArray(T,AT = StdAllocator)
ref T opIndexAssign(T value, size_t index)
{
m_Data[index] = value;
+ return m_Data[index];
}
void opIndexAssign(T value, size_t from, size_t to)
Oops, something went wrong.

0 comments on commit 05c440b

Please sign in to comment.