WeakKeyDictionary.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / NetFx40 / Tools / System.Activities.Presentation / System / Activities / Presentation / Model / WeakKeyDictionary.cs / 1305376 / WeakKeyDictionary.cs

                            //---------------------------------------------------------------- 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//---------------------------------------------------------------
namespace System.Activities.Presentation.Model
{ 

    using System; 
    using System.Collections; 
    using System.Collections.Generic;
    using System.Diagnostics.CodeAnalysis; 
    using System.Text;
    using System.Runtime.InteropServices;

    internal class WeakKeyDictionary : IDictionary 
    {
 
        private Dictionary _internalDictionary; 
        private object _[....] = new object();
        private bool _finalized; 

        public WeakKeyDictionary()
        {
            _internalDictionary = new Dictionary(new WeakComparer()); 
        }
 
        public WeakKeyDictionary(int capacity) 
        {
            _internalDictionary = new Dictionary(capacity, new WeakComparer()); 
        }

        public WeakKeyDictionary(IEqualityComparer comparer)
        { 
            _internalDictionary = new Dictionary(new WeakComparer(comparer));
        } 
 
        public WeakKeyDictionary(int capacity, IEqualityComparer comparer)
        { 
            _internalDictionary = new Dictionary(capacity, new WeakComparer(comparer));
        }

        // FXCop: this is not empty; we need to mark this so we know if a key 
        // still has an active dictionary at its finalization.
        [SuppressMessage("Microsoft.Performance", "CA1821:RemoveEmptyFinalizers")] 
        ~WeakKeyDictionary() 
        {
            _finalized = true; 
        }

        public ICollection Keys
        { 
            get
            { 
                List list = new List(); 
                lock (_[....])
                { 
                    foreach (WeakKey key in _internalDictionary.Keys)
                    {
                        object k = key.Target;
                        if (k != null) 
                        {
                            list.Add((K)k); 
                        } 
                    }
                } 
                return list;
            }
        }
 
        public ICollection Values
        { 
            get { 
                lock (_[....]) {
                    return _internalDictionary.Values; 
                }
            }
        }
 
        public int Count
        { 
            get 
            {
                // Ensure a fairly accurate count. 
                ScavangeLostKeys();
                lock (_[....])
                {
                    return _internalDictionary.Count; 
                }
            } 
        } 

        public bool IsReadOnly 
        {
            get {
                return false;
            } 
        }
 
        [SuppressMessage("Microsoft.Usage", "CA1806:DoNotIgnoreMethodResults", Justification = "LostKeyFinder's purpose is to get garbage collected as soon as posible")] 
        public V this[K key]
        { 
            get {
                lock (_[....]) {
                    return _internalDictionary[new WeakKey(key)];
                } 
            }
            set 
            { 
                WeakKey k = new WeakKey(key);
                lock (_[....]) 
                {
                    _internalDictionary[k] = value;
                }
                // This looks a bit weird but the purpose of the lost key finder is to execute 
                // code in some future garbage collection phase so we immediately create some garbage.
                new LostKeyFinder(this, k); 
            } 
        }
 



 
        public bool TryGetValue(K key, out V value)
        { 
            WeakKey k = new WeakKey(key); 
            lock (_[....])
            { 
                return _internalDictionary.TryGetValue(k, out value);
            }
        }
 

        [SuppressMessage("Microsoft.Usage", "CA1806:DoNotIgnoreMethodResults", Justification = "LostKeyFinder's purpose is to get garbage collected as soon as posible")] 
        public void Add(K key, V value) 
        {
            WeakKey k = new WeakKey(key); 
            lock (_[....])
            {
                _internalDictionary.Add(k, value);
            } 
            // This looks a bit weird but the purpose of the lost key finder is to execute
            // code in some future garbage collection phase so we immediately create some garbage. 
            new LostKeyFinder(this, k); 

        } 

        public bool ContainsKey(K key)
        {
            return _internalDictionary.ContainsKey(new WeakKey(key)); 
        }
 
        public bool Remove(K key) 
        {
            lock (_[....]) 
            {
                return _internalDictionary.Remove(new WeakKey(key));
            }
        } 

        public void Add(KeyValuePair item) 
        { 
            Add(item.Key, item.Value);
        } 

        public void Clear()
        {
            lock (_[....]) 
            {
                _internalDictionary.Clear(); 
            } 
        }
 
        public bool Contains(KeyValuePair item)
        {
            V value;
            bool result; 
            lock (_[....])
            { 
                result = _internalDictionary.TryGetValue(new WeakKey(item.Key), out value); 
            }
            if (result) 
            {
                return value.Equals(item.Value);
            }
            else 
            {
                return false; 
            } 
        }
 
        public void CopyTo(KeyValuePair[] array, int arrayIndex)
        {
            lock (_[....])
            { 
                foreach (KeyValuePair item in _internalDictionary)
                { 
                    KeyValuePair kv = new KeyValuePair((K)item.Key.Target, item.Value); 
                    array[arrayIndex] = kv;
                    arrayIndex++; 
                }
            }
        }
 
        public bool Remove(KeyValuePair item)
        { 
            WeakKey key = new WeakKey(item.Key); 
            lock (_[....])
            { 
                return _internalDictionary.Remove(key);
            }
        }
 

 
 

        public IEnumerator> GetEnumerator() 
        {
            List lostKeys = null;
            lock (_[....])
            { 
                foreach (KeyValuePair item in _internalDictionary)
                { 
                    object k = item.Key.Target; 
                    if (k != null)
                    { 
                        yield return new KeyValuePair((K)k, item.Value);
                    }
                    else
                    { 
                        if (lostKeys == null)
                        { 
                            lostKeys = new List(); 
                        }
                        lostKeys.Add(item.Key); 
                    }
                }
            }
            // Recover any lost keys. 
            if (lostKeys != null)
            { 
                lock (_[....]) 
                {
                    foreach (WeakKey key in lostKeys) 
                    {
                        _internalDictionary.Remove(key);
                    }
                } 
            }
        } 
 

 

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator(); 
        }
 
 

        private void ScavangeLostKeys() 
        {
            List lostKeys = null;
            lock (_[....])
            { 
                foreach (WeakKey key in _internalDictionary.Keys)
                { 
                    if (!key.IsAlive) 
                    {
                        if (lostKeys == null) 
                        {
                            lostKeys = new List();
                        }
                        lostKeys.Add(key); 
                    }
                } 
            } 
            if (lostKeys != null)
            { 
                lock (_[....])
                {
                    foreach (WeakKey key in lostKeys)
                    { 
                        _internalDictionary.Remove(key);
                    } 
                } 
            }
        } 

        private class WeakKey : WeakReference
        {
            private int _hashCode; 
            // private GCHandle _gcHandle;
 
            public WeakKey(K key) 
                : base(key, true)
            { 
                _hashCode = key.GetHashCode();
                // Keep the key alive until it is explicitly collected
                // _gcHandle = GCHandle.Alloc(this);
            } 

            internal void Release() 
            { 
                // _gcHandle.Free();
            } 

            public override int GetHashCode()
            {
                return _hashCode; 
            }
 
            public override bool Equals(object obj) 
            {
                if (obj == null) 
                {
                    return false;
                }
                if (obj.GetHashCode() != _hashCode) 
                {
                    return false; 
                } 
                if (obj != this && (!IsAlive || !obj.Equals(Target)))
                { 
                    return false;
                }
                return true;
            } 
        }
 
        private class WeakComparer : IEqualityComparer 
        {
 
            private IEqualityComparer _comparer;
            public WeakComparer()
            {
            } 

            public WeakComparer(IEqualityComparer comparer) 
            { 
                _comparer = comparer;
            } 

            public bool Equals(WeakKey x, WeakKey y)
            {
                if (x.GetHashCode() != y.GetHashCode()) 
                {
                    return false; 
                } 
                if (object.ReferenceEquals(x, y))
                { 
                    return true;
                }
                object ref1 = x.Target;
                if (ref1 == null) 
                {
                    return false; 
                } 
                object ref2 = y.Target;
                if (ref2 == null) 
                {
                    return false;
                }
 
                if (_comparer != null)
                { 
                    return _comparer.Equals((K)ref1, (K)ref2); 
                }
                else 
                {
                    return ref1.Equals(ref2);
                }
            } 

            public int GetHashCode(WeakKey obj) 
            { 
                return obj.GetHashCode();
            } 
        }

        private class LostKeyFinder
        { 
            WeakKeyDictionary _dictionary;
            WeakKey _key; 
 
            public LostKeyFinder(WeakKeyDictionary dictionary, WeakKey key)
            { 
                _dictionary = dictionary;
                _key = key;
            }
 
            ~LostKeyFinder()
            { 
                if (_dictionary._finalized || _key == null) 
                {
                    if (_key != null) 
                    {
                        _key.Release();
                        _key = null;
                    } 
                    return;
                } 
                // if (!_key.IsAlive) { 
                if (_key.Target == null)
                { 
                    lock (_dictionary._[....])
                    {
                        _dictionary._internalDictionary.Remove(_key);
                    } 
                    _key.Release();
                    _key = null; 
                } 
                else if (_dictionary._internalDictionary.ContainsKey(_key))
                { 
                    GC.ReRegisterForFinalize(this);
                }
            }
        } 
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//---------------------------------------------------------------- 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//---------------------------------------------------------------
namespace System.Activities.Presentation.Model
{ 

    using System; 
    using System.Collections; 
    using System.Collections.Generic;
    using System.Diagnostics.CodeAnalysis; 
    using System.Text;
    using System.Runtime.InteropServices;

    internal class WeakKeyDictionary : IDictionary 
    {
 
        private Dictionary _internalDictionary; 
        private object _[....] = new object();
        private bool _finalized; 

        public WeakKeyDictionary()
        {
            _internalDictionary = new Dictionary(new WeakComparer()); 
        }
 
        public WeakKeyDictionary(int capacity) 
        {
            _internalDictionary = new Dictionary(capacity, new WeakComparer()); 
        }

        public WeakKeyDictionary(IEqualityComparer comparer)
        { 
            _internalDictionary = new Dictionary(new WeakComparer(comparer));
        } 
 
        public WeakKeyDictionary(int capacity, IEqualityComparer comparer)
        { 
            _internalDictionary = new Dictionary(capacity, new WeakComparer(comparer));
        }

        // FXCop: this is not empty; we need to mark this so we know if a key 
        // still has an active dictionary at its finalization.
        [SuppressMessage("Microsoft.Performance", "CA1821:RemoveEmptyFinalizers")] 
        ~WeakKeyDictionary() 
        {
            _finalized = true; 
        }

        public ICollection Keys
        { 
            get
            { 
                List list = new List(); 
                lock (_[....])
                { 
                    foreach (WeakKey key in _internalDictionary.Keys)
                    {
                        object k = key.Target;
                        if (k != null) 
                        {
                            list.Add((K)k); 
                        } 
                    }
                } 
                return list;
            }
        }
 
        public ICollection Values
        { 
            get { 
                lock (_[....]) {
                    return _internalDictionary.Values; 
                }
            }
        }
 
        public int Count
        { 
            get 
            {
                // Ensure a fairly accurate count. 
                ScavangeLostKeys();
                lock (_[....])
                {
                    return _internalDictionary.Count; 
                }
            } 
        } 

        public bool IsReadOnly 
        {
            get {
                return false;
            } 
        }
 
        [SuppressMessage("Microsoft.Usage", "CA1806:DoNotIgnoreMethodResults", Justification = "LostKeyFinder's purpose is to get garbage collected as soon as posible")] 
        public V this[K key]
        { 
            get {
                lock (_[....]) {
                    return _internalDictionary[new WeakKey(key)];
                } 
            }
            set 
            { 
                WeakKey k = new WeakKey(key);
                lock (_[....]) 
                {
                    _internalDictionary[k] = value;
                }
                // This looks a bit weird but the purpose of the lost key finder is to execute 
                // code in some future garbage collection phase so we immediately create some garbage.
                new LostKeyFinder(this, k); 
            } 
        }
 



 
        public bool TryGetValue(K key, out V value)
        { 
            WeakKey k = new WeakKey(key); 
            lock (_[....])
            { 
                return _internalDictionary.TryGetValue(k, out value);
            }
        }
 

        [SuppressMessage("Microsoft.Usage", "CA1806:DoNotIgnoreMethodResults", Justification = "LostKeyFinder's purpose is to get garbage collected as soon as posible")] 
        public void Add(K key, V value) 
        {
            WeakKey k = new WeakKey(key); 
            lock (_[....])
            {
                _internalDictionary.Add(k, value);
            } 
            // This looks a bit weird but the purpose of the lost key finder is to execute
            // code in some future garbage collection phase so we immediately create some garbage. 
            new LostKeyFinder(this, k); 

        } 

        public bool ContainsKey(K key)
        {
            return _internalDictionary.ContainsKey(new WeakKey(key)); 
        }
 
        public bool Remove(K key) 
        {
            lock (_[....]) 
            {
                return _internalDictionary.Remove(new WeakKey(key));
            }
        } 

        public void Add(KeyValuePair item) 
        { 
            Add(item.Key, item.Value);
        } 

        public void Clear()
        {
            lock (_[....]) 
            {
                _internalDictionary.Clear(); 
            } 
        }
 
        public bool Contains(KeyValuePair item)
        {
            V value;
            bool result; 
            lock (_[....])
            { 
                result = _internalDictionary.TryGetValue(new WeakKey(item.Key), out value); 
            }
            if (result) 
            {
                return value.Equals(item.Value);
            }
            else 
            {
                return false; 
            } 
        }
 
        public void CopyTo(KeyValuePair[] array, int arrayIndex)
        {
            lock (_[....])
            { 
                foreach (KeyValuePair item in _internalDictionary)
                { 
                    KeyValuePair kv = new KeyValuePair((K)item.Key.Target, item.Value); 
                    array[arrayIndex] = kv;
                    arrayIndex++; 
                }
            }
        }
 
        public bool Remove(KeyValuePair item)
        { 
            WeakKey key = new WeakKey(item.Key); 
            lock (_[....])
            { 
                return _internalDictionary.Remove(key);
            }
        }
 

 
 

        public IEnumerator> GetEnumerator() 
        {
            List lostKeys = null;
            lock (_[....])
            { 
                foreach (KeyValuePair item in _internalDictionary)
                { 
                    object k = item.Key.Target; 
                    if (k != null)
                    { 
                        yield return new KeyValuePair((K)k, item.Value);
                    }
                    else
                    { 
                        if (lostKeys == null)
                        { 
                            lostKeys = new List(); 
                        }
                        lostKeys.Add(item.Key); 
                    }
                }
            }
            // Recover any lost keys. 
            if (lostKeys != null)
            { 
                lock (_[....]) 
                {
                    foreach (WeakKey key in lostKeys) 
                    {
                        _internalDictionary.Remove(key);
                    }
                } 
            }
        } 
 

 

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator(); 
        }
 
 

        private void ScavangeLostKeys() 
        {
            List lostKeys = null;
            lock (_[....])
            { 
                foreach (WeakKey key in _internalDictionary.Keys)
                { 
                    if (!key.IsAlive) 
                    {
                        if (lostKeys == null) 
                        {
                            lostKeys = new List();
                        }
                        lostKeys.Add(key); 
                    }
                } 
            } 
            if (lostKeys != null)
            { 
                lock (_[....])
                {
                    foreach (WeakKey key in lostKeys)
                    { 
                        _internalDictionary.Remove(key);
                    } 
                } 
            }
        } 

        private class WeakKey : WeakReference
        {
            private int _hashCode; 
            // private GCHandle _gcHandle;
 
            public WeakKey(K key) 
                : base(key, true)
            { 
                _hashCode = key.GetHashCode();
                // Keep the key alive until it is explicitly collected
                // _gcHandle = GCHandle.Alloc(this);
            } 

            internal void Release() 
            { 
                // _gcHandle.Free();
            } 

            public override int GetHashCode()
            {
                return _hashCode; 
            }
 
            public override bool Equals(object obj) 
            {
                if (obj == null) 
                {
                    return false;
                }
                if (obj.GetHashCode() != _hashCode) 
                {
                    return false; 
                } 
                if (obj != this && (!IsAlive || !obj.Equals(Target)))
                { 
                    return false;
                }
                return true;
            } 
        }
 
        private class WeakComparer : IEqualityComparer 
        {
 
            private IEqualityComparer _comparer;
            public WeakComparer()
            {
            } 

            public WeakComparer(IEqualityComparer comparer) 
            { 
                _comparer = comparer;
            } 

            public bool Equals(WeakKey x, WeakKey y)
            {
                if (x.GetHashCode() != y.GetHashCode()) 
                {
                    return false; 
                } 
                if (object.ReferenceEquals(x, y))
                { 
                    return true;
                }
                object ref1 = x.Target;
                if (ref1 == null) 
                {
                    return false; 
                } 
                object ref2 = y.Target;
                if (ref2 == null) 
                {
                    return false;
                }
 
                if (_comparer != null)
                { 
                    return _comparer.Equals((K)ref1, (K)ref2); 
                }
                else 
                {
                    return ref1.Equals(ref2);
                }
            } 

            public int GetHashCode(WeakKey obj) 
            { 
                return obj.GetHashCode();
            } 
        }

        private class LostKeyFinder
        { 
            WeakKeyDictionary _dictionary;
            WeakKey _key; 
 
            public LostKeyFinder(WeakKeyDictionary dictionary, WeakKey key)
            { 
                _dictionary = dictionary;
                _key = key;
            }
 
            ~LostKeyFinder()
            { 
                if (_dictionary._finalized || _key == null) 
                {
                    if (_key != null) 
                    {
                        _key.Release();
                        _key = null;
                    } 
                    return;
                } 
                // if (!_key.IsAlive) { 
                if (_key.Target == null)
                { 
                    lock (_dictionary._[....])
                    {
                        _dictionary._internalDictionary.Remove(_key);
                    } 
                    _key.Release();
                    _key = null; 
                } 
                else if (_dictionary._internalDictionary.ContainsKey(_key))
                { 
                    GC.ReRegisterForFinalize(this);
                }
            }
        } 
    }
} 

// 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