Exemplo n.º 1
0
        /// <summary>
        /// Remove dead entries from the data for the given source.   Returns true if
        /// some entries were actually removed.
        /// </summary>
        protected override bool Purge(object source, object data, bool purgeAll)
        {
            bool foundDirt = false;

            HybridDictionary dict = (HybridDictionary)data;

            // copy the keys into a separate array, so that later on
            // we can change the dictionary while iterating over the keys
            ICollection ic = dict.Keys;

            PropertyDescriptor[] keys = new PropertyDescriptor[ic.Count];
            ic.CopyTo(keys, 0);

            for (int i = keys.Length - 1; i >= 0; --i)
            {
                // for each key, remove dead entries in its list
                bool removeList = purgeAll || source == null;

                ValueChangedRecord record = (ValueChangedRecord)dict[keys[i]];

                if (!removeList)
                {
                    if (record.Purge())
                    {
                        foundDirt = true;
                    }

                    removeList = record.IsEmpty;
                }

                // if there are no more entries, remove the key
                if (removeList)
                {
                    record.StopListening();
                    if (!purgeAll)
                    {
                        dict.Remove(keys[i]);
                    }
                }
            }

            // if there are no more listeners at all, remove the entry from
            // the main table
            if (dict.Count == 0)
            {
                foundDirt = true;
                if (source != null)     // source may have been GC'd
                {
                    this.Remove(source);
                }
            }

            return(foundDirt);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Remove dead entries from the data for the given source.   Returns true if
        /// some entries were actually removed.
        /// </summary>
        protected override bool Purge(object source, object data, bool purgeAll)
        {
            bool foundDirt = false;

            HybridDictionary dict = (HybridDictionary)data;

            if (!MS.Internal.BaseAppContextSwitches.EnableWeakEventMemoryImprovements)
            {
                // copy the keys into a separate array, so that later on
                // we can change the dictionary while iterating over the keys
                ICollection          ic   = dict.Keys;
                PropertyDescriptor[] keys = new PropertyDescriptor[ic.Count];
                ic.CopyTo(keys, 0);

                for (int i = keys.Length - 1; i >= 0; --i)
                {
                    // for each key, remove dead entries in its list
                    bool removeList = purgeAll || source == null;

                    ValueChangedRecord record = (ValueChangedRecord)dict[keys[i]];

                    if (!removeList)
                    {
                        if (record.Purge())
                        {
                            foundDirt = true;
                        }

                        removeList = record.IsEmpty;
                    }

                    // if there are no more entries, remove the key
                    if (removeList)
                    {
                        record.StopListening();
                        if (!purgeAll)
                        {
                            dict.Remove(keys[i]);
                        }
                    }
                }

#if WeakEventTelemetry
                LogAllocation(ic.GetType(), 1, 12);                     // dict.Keys - Hashtable+KeyCollection
                LogAllocation(typeof(String[]), 1, 12 + ic.Count * 4);  // keys
#endif
            }
            else
            {
                Debug.Assert(_toRemove.Count == 0, "to-remove list should be empty");

                // enumerate the dictionary using IDE explicitly rather than
                // foreach, to avoid allocating temporary DictionaryEntry objects
                IDictionaryEnumerator ide = dict.GetEnumerator() as IDictionaryEnumerator;
                while (ide.MoveNext())
                {
                    // for each key, remove dead entries in its list
                    bool removeList = purgeAll || source == null;

                    ValueChangedRecord record = (ValueChangedRecord)ide.Value;

                    if (!removeList)
                    {
                        if (record.Purge())
                        {
                            foundDirt = true;
                        }

                        removeList = record.IsEmpty;
                    }

                    // if there are no more entries, remove the key
                    if (removeList)
                    {
                        record.StopListening();
                        if (!purgeAll)
                        {
                            _toRemove.Add((PropertyDescriptor)ide.Key);
                        }
                    }
                }

                // do the actual removal (outside the dictionary iteration)
                if (_toRemove.Count > 0)
                {
                    foreach (PropertyDescriptor key in _toRemove)
                    {
                        dict.Remove(key);
                    }
                    _toRemove.Clear();
                    _toRemove.TrimExcess();
                }

#if WeakEventTelemetry
                Type enumeratorType = ide.GetType();
                if (enumeratorType.Name.IndexOf("NodeEnumerator") >= 0)
                {
                    LogAllocation(enumeratorType, 1, 24);                    // ListDictionary+NodeEnumerator
                }
                else
                {
                    LogAllocation(enumeratorType, 1, 36);                    // Hashtable+HashtableEnumerator
                }
#endif
            }


            // if there are no more listeners at all, remove the entry from
            // the main table
            if (dict.Count == 0)
            {
                foundDirt = true;
                if (source != null)     // source may have been GC'd
                {
                    this.Remove(source);
                }
            }

            return(foundDirt);
        }