WeakHashtable.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / whidbey / netfxsp / ndp / fx / src / Misc / WeakHashtable.cs / 4 / WeakHashtable.cs

                            //------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 

namespace System.ComponentModel { 
 
    using System;
    using System.Collections; 
    using System.Security.Permissions;

    /// 
    ///     This is a hashtable that stores object keys as weak references. 
    ///     It monitors memory usage and will periodically scavenge the
    ///     hash table to clean out dead references. 
    ///  
    [HostProtection(SharedState = true)]
    internal sealed class WeakHashtable : Hashtable 
    {
        private static IEqualityComparer _comparer = new WeakKeyComparer();

        private long     _lastGlobalMem; 
        private int      _lastHashCount;
 
        internal WeakHashtable() : base(_comparer) 
        {
        } 

        /// 
        ///     Override of clear that performs a scavenge.
        ///  
        public override void Clear()
        { 
            base.Clear(); 
        }
 
        /// 
        ///     Override of remove that performs a scavenge.
        /// 
        public override void Remove(object key) 
        {
            base.Remove(key); 
        } 

        ///  
        ///     Override of Item that wraps a weak reference around the
        ///     key and performs a scavenge.
        /// 
        public void SetWeak(object key, object value) 
        {
            ScavengeKeys(); 
            this[new EqualityWeakReference(key)] = value; 
        }
 
        /// 
        ///     This method checks to see if it is necessary to
        ///     scavenge keys, and if it is it performs a scan
        ///     of all keys to see which ones are no longer valid. 
        ///     To determine if we need to scavenge keys we need to
        ///     try to track the current GC memory.  Our rule of 
        ///     thumb is that if GC memory is decreasing and our 
        ///     key count is constant we need to scavenge.  We
        ///     will need to see if this is too often for extreme 
        ///     use cases like the CompactFramework (they add
        ///     custom type data for every object at design time).
        /// 
        private void ScavengeKeys() 
        {
            int hashCount = Count; 
 
            if (hashCount == 0)
            { 
                return;
            }

            if (_lastHashCount == 0) 
            {
                _lastHashCount = hashCount; 
                return; 
            }
 
            long globalMem = GC.GetTotalMemory(false);

            if (_lastGlobalMem == 0)
            { 
                _lastGlobalMem = globalMem;
                return; 
            } 

            float memDelta = (float)(globalMem - _lastGlobalMem) / (float)_lastGlobalMem; 
            float hashDelta = (float)(hashCount - _lastHashCount) / (float)_lastHashCount;

            if (memDelta < 0 && hashDelta >= 0)
            { 
                // Perform a scavenge through our keys, looking
                // for dead references. 
                // 
                ArrayList cleanupList = null;
                foreach(object o in Keys) 
                {
                    WeakReference wr = o as WeakReference;
                    if (wr != null && !wr.IsAlive)
                    { 
                        if (cleanupList == null)
                        { 
                            cleanupList = new ArrayList(); 
                        }
 
                        cleanupList.Add(wr);
                    }
                }
 
                if (cleanupList != null)
                { 
                    foreach(object o in cleanupList) 
                    {
                        Remove(o); 
                    }
                }
            }
 
            _lastGlobalMem = globalMem;
            _lastHashCount = hashCount; 
        } 

        private class WeakKeyComparer : IEqualityComparer 
        {
            bool IEqualityComparer.Equals(Object x, Object y)
            {
                if (x == null) 
                {
                    return y == null; 
                } 
                if (y != null && x.GetHashCode() == y.GetHashCode())
                { 
                    WeakReference wX = x as WeakReference;
                    WeakReference wY = y as WeakReference;

                    if (wX != null) 
                    {
                        if (!wX.IsAlive) 
                        { 
                            return false;
                        } 
                        x = wX.Target;
                    }

                    if (wY != null) 
                    {
                        if (!wY.IsAlive) 
                        { 
                            return false;
                        } 
                        y = wY.Target;
                    }

                    return object.ReferenceEquals(x, y); 
                }
 
                return false; 
            }
 
            int IEqualityComparer.GetHashCode (Object obj)
            {
                return obj.GetHashCode();
            } 
        }
 
        ///  
        ///     A subclass of WeakReference that overrides GetHashCode and
        ///     Equals so that the weak reference returns the same equality 
        ///     semantics as the object it wraps.  This will always return
        ///     the object's hash code and will return True for a Equals
        ///     comparison of the object it is wrapping.  If the object
        ///     it is wrapping has finalized, Equals always returns false. 
        /// 
        private sealed class EqualityWeakReference : WeakReference 
        { 
            private int _hashCode;
            internal EqualityWeakReference(object o) : base(o) 
            {
                _hashCode = o.GetHashCode();
            }
 
            public override bool Equals(object o)
            { 
                if (o == null) 
                {
                    return false; 
                }

                if (o.GetHashCode() != _hashCode)
                { 
                    return false;
                } 
 
                if (o == this || (IsAlive && object.ReferenceEquals(o, Target)))
                { 
                    return true;
                }

                return false; 
            }
 
            public override int GetHashCode() 
            {
                return _hashCode; 
            }
        }

 
        /* The folowing code has been removed to prevent FXCOP violation
           It is left here incase it needs to be resurected 
        ///  
        ///     Override of add that wraps a weak reference around the
        ///     key and performs a scavenge. 
        /// 
        public void AddWeak(object key, object value)
        {
            ScavengeKeys(); 
            base.Add(new EqualityWeakReference(key), value);
        } 
        */ 
    }
} 


// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 

namespace System.ComponentModel { 
 
    using System;
    using System.Collections; 
    using System.Security.Permissions;

    /// 
    ///     This is a hashtable that stores object keys as weak references. 
    ///     It monitors memory usage and will periodically scavenge the
    ///     hash table to clean out dead references. 
    ///  
    [HostProtection(SharedState = true)]
    internal sealed class WeakHashtable : Hashtable 
    {
        private static IEqualityComparer _comparer = new WeakKeyComparer();

        private long     _lastGlobalMem; 
        private int      _lastHashCount;
 
        internal WeakHashtable() : base(_comparer) 
        {
        } 

        /// 
        ///     Override of clear that performs a scavenge.
        ///  
        public override void Clear()
        { 
            base.Clear(); 
        }
 
        /// 
        ///     Override of remove that performs a scavenge.
        /// 
        public override void Remove(object key) 
        {
            base.Remove(key); 
        } 

        ///  
        ///     Override of Item that wraps a weak reference around the
        ///     key and performs a scavenge.
        /// 
        public void SetWeak(object key, object value) 
        {
            ScavengeKeys(); 
            this[new EqualityWeakReference(key)] = value; 
        }
 
        /// 
        ///     This method checks to see if it is necessary to
        ///     scavenge keys, and if it is it performs a scan
        ///     of all keys to see which ones are no longer valid. 
        ///     To determine if we need to scavenge keys we need to
        ///     try to track the current GC memory.  Our rule of 
        ///     thumb is that if GC memory is decreasing and our 
        ///     key count is constant we need to scavenge.  We
        ///     will need to see if this is too often for extreme 
        ///     use cases like the CompactFramework (they add
        ///     custom type data for every object at design time).
        /// 
        private void ScavengeKeys() 
        {
            int hashCount = Count; 
 
            if (hashCount == 0)
            { 
                return;
            }

            if (_lastHashCount == 0) 
            {
                _lastHashCount = hashCount; 
                return; 
            }
 
            long globalMem = GC.GetTotalMemory(false);

            if (_lastGlobalMem == 0)
            { 
                _lastGlobalMem = globalMem;
                return; 
            } 

            float memDelta = (float)(globalMem - _lastGlobalMem) / (float)_lastGlobalMem; 
            float hashDelta = (float)(hashCount - _lastHashCount) / (float)_lastHashCount;

            if (memDelta < 0 && hashDelta >= 0)
            { 
                // Perform a scavenge through our keys, looking
                // for dead references. 
                // 
                ArrayList cleanupList = null;
                foreach(object o in Keys) 
                {
                    WeakReference wr = o as WeakReference;
                    if (wr != null && !wr.IsAlive)
                    { 
                        if (cleanupList == null)
                        { 
                            cleanupList = new ArrayList(); 
                        }
 
                        cleanupList.Add(wr);
                    }
                }
 
                if (cleanupList != null)
                { 
                    foreach(object o in cleanupList) 
                    {
                        Remove(o); 
                    }
                }
            }
 
            _lastGlobalMem = globalMem;
            _lastHashCount = hashCount; 
        } 

        private class WeakKeyComparer : IEqualityComparer 
        {
            bool IEqualityComparer.Equals(Object x, Object y)
            {
                if (x == null) 
                {
                    return y == null; 
                } 
                if (y != null && x.GetHashCode() == y.GetHashCode())
                { 
                    WeakReference wX = x as WeakReference;
                    WeakReference wY = y as WeakReference;

                    if (wX != null) 
                    {
                        if (!wX.IsAlive) 
                        { 
                            return false;
                        } 
                        x = wX.Target;
                    }

                    if (wY != null) 
                    {
                        if (!wY.IsAlive) 
                        { 
                            return false;
                        } 
                        y = wY.Target;
                    }

                    return object.ReferenceEquals(x, y); 
                }
 
                return false; 
            }
 
            int IEqualityComparer.GetHashCode (Object obj)
            {
                return obj.GetHashCode();
            } 
        }
 
        ///  
        ///     A subclass of WeakReference that overrides GetHashCode and
        ///     Equals so that the weak reference returns the same equality 
        ///     semantics as the object it wraps.  This will always return
        ///     the object's hash code and will return True for a Equals
        ///     comparison of the object it is wrapping.  If the object
        ///     it is wrapping has finalized, Equals always returns false. 
        /// 
        private sealed class EqualityWeakReference : WeakReference 
        { 
            private int _hashCode;
            internal EqualityWeakReference(object o) : base(o) 
            {
                _hashCode = o.GetHashCode();
            }
 
            public override bool Equals(object o)
            { 
                if (o == null) 
                {
                    return false; 
                }

                if (o.GetHashCode() != _hashCode)
                { 
                    return false;
                } 
 
                if (o == this || (IsAlive && object.ReferenceEquals(o, Target)))
                { 
                    return true;
                }

                return false; 
            }
 
            public override int GetHashCode() 
            {
                return _hashCode; 
            }
        }

 
        /* The folowing code has been removed to prevent FXCOP violation
           It is left here incase it needs to be resurected 
        ///  
        ///     Override of add that wraps a weak reference around the
        ///     key and performs a scavenge. 
        /// 
        public void AddWeak(object key, object value)
        {
            ScavengeKeys(); 
            base.Add(new EqualityWeakReference(key), value);
        } 
        */ 
    }
} 


// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK