I have a GC testing application that uses
System.Reflection.Cache.TypeNameCache.  It puts
a value into the cache (via RuntimeType.FullName),
does a GC (using a new GC), then tries to extract
the value from the cache (also using RuntimeType.FullName).

Extracting the value from the cache crashes Rotor as
the GC has deleted TypeNameCache.m_cache, TypeNameCache.m_data,
etc.  It deletes these because m_cache isn't listed as a
root by GcScanRoots() or GcScanHandles().  However, I
copied this class into my application program file and
accessed it directly, instead of through the RuntimeType,
and it works fine.

Any thoughts on why copying the class would make it behave
differently with respect to the GC?  Is it some sort of
appdomain or namespace issue?

Below is my little testing program.

thanks,

Todd

---------------------------------------------------------------

using System;
using System.Reflection;

public class Sixteen {
    public int v1;
    public int v2;
    public int v3;
    public int v4;
}

public class StaticTest {
//    static public Sixteen m_sixstat;
    static private StaticTest m_st=null;
    static public StaticTest GetInstance() {
        if(m_st == null) {
            m_st = new StaticTest();
        }
        return m_st;
    }
    public Sixteen[] m_sixstat;
}

internal struct TypeNameStruct {
    internal int HashKey;
    internal String TypeName;
}

internal class TypeNameCache {
    private static TypeNameCache m_cache = null;
    
    private TypeNameStruct[] m_data;
    
    internal const int CacheSize = 919;
    
    internal TypeNameCache() {
        m_data = new TypeNameStruct[CacheSize];
    }
    
    internal static int CalculateHash(int hashKey) {
        //We know that the bottom two bits of a 32-bit pointer are going to be zero, so
        //let's not include them in the value that we hash.
#if WIN32
        return unchecked((int)((((uint)(int)hashKey)>>2)%(uint)CacheSize));
#else
        return unchecked((int)((((ulong)(long)hashKey)>>3)%(ulong)CacheSize));
#endif
    }
    
    internal String GetTypeName(int hashKey) {
        int iPos = CalculateHash(hashKey);
        
        TypeNameStruct t;
        t.HashKey = m_data[iPos].HashKey;
        t.TypeName = m_data[iPos].TypeName;
        
        if (t.HashKey==hashKey && m_data[iPos].HashKey==t.HashKey) {
            return t.TypeName;
        }
        return null;
    }
    
    internal void AddValue(int hashKey, String typeName) {
        int iPos = CalculateHash(hashKey);
        
        lock(typeof(TypeNameCache)) {
            m_data[iPos].HashKey = 0; //Invalidate the bucket.
            m_data[iPos].TypeName = typeName;   //Set the type name.
            m_data[iPos].HashKey = hashKey;     //Revalidate the bucket.
        }
    }
    
    internal static TypeNameCache GetCache() {
        if (m_cache==null) {
            lock (typeof(TypeNameCache)) {
                if (m_cache==null) {
                    m_cache = new TypeNameCache();
                }
            }
        }
        return m_cache;
    }
}

public class Test
{
    public static void Main()
    {
        System.Console.WriteLine("Starting GC tester");

        StaticTest st1 = StaticTest.GetInstance();
        st1.m_sixstat = new Sixteen[5];

        // Uncomment the following line and the other commented line below
        // and the program will crash when using my GC.
        //      System.Console.WriteLine(st1.m_sixstat.GetType().FullName);
        TypeNameCache tnc = TypeNameCache.GetCache();
        String s = "blah blah";
        tnc.AddValue(13,s);

        st1.m_sixstat[0] = new Sixteen();
        st1.m_sixstat[0].v1 = 7;
        st1.m_sixstat[0].v2 = 11;
        st1.m_sixstat[0].v3 = 13;
        st1.m_sixstat[0].v4 = 17;
        st1.m_sixstat[1] = new Sixteen();
        st1.m_sixstat[2] = new Sixteen();
        st1.m_sixstat[3] = new Sixteen();

        System.Console.WriteLine(st1.m_sixstat[0].v1);
        System.Console.WriteLine(st1.m_sixstat[0].v2);
        System.Console.WriteLine(st1.m_sixstat[0].v3);
        System.Console.WriteLine(st1.m_sixstat[0].v4);

        GC.Collect();

        st1 = StaticTest.GetInstance();
        System.Console.WriteLine(st1.m_sixstat[0].v1);
        tnc = TypeNameCache.GetCache();
        s = tnc.GetTypeName(13);
        System.Console.WriteLine(s);
        // Uncomment the following line and the other commented line above
        // and the program will crash when using my GC.
        //      System.Console.WriteLine(st1.m_sixstat.GetType().FullName);

        System.Console.WriteLine("Finished GC tester");
    }
}

===================================
This list is hosted by DevelopMentorŪ  http://www.develop.com
NEW! ASP.NET courses you may be interested in:

2 Days of ASP.NET, 29 Sept 2003, in Redmond
http://www.develop.com/courses/2daspdotnet

Guerrilla ASP.NET, 13 Oct 2003, in Boston
http://www.develop.com/courses/gaspdotnet

View archives and manage your subscription(s) at http://discuss.develop.com

Reply via email to