Use public ConditionalWeakTable iterator (dotnet/coreclr#12564)
authorJan Kotas <jkotas@microsoft.com>
Fri, 30 Jun 2017 04:40:04 +0000 (21:40 -0700)
committerGitHub <noreply@github.com>
Fri, 30 Jun 2017 04:40:04 +0000 (21:40 -0700)
Port https://github.com/dotnet/corert/pull/4030/commits/dotnet/coreclr@a3837f7fc60a1b7db872cfef6463f74fb1ffeafb to CoreCLR

Commit migrated from https://github.com/dotnet/coreclr/commit/8279ba85a79c5293aa06b56a4ff8de67971a43c4

src/coreclr/src/mscorlib/src/System/Runtime/CompilerServices/ConditionalWeakTable.cs
src/coreclr/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/WindowsRuntimeMarshal.cs
src/coreclr/src/mscorlib/src/System/Threading/Tasks/TaskScheduler.cs

index 6c6f6ee..d3548b9 100644 (file)
@@ -428,55 +428,6 @@ namespace System.Runtime.CompilerServices
 
         #endregion
 
-        #region Internal members
-
-        //--------------------------------------------------------------------------------------------
-        // Find a key that equals (value equality) with the given key - don't use in perf critical path
-        // Note that it calls out to Object.Equals which may calls the override version of Equals
-        // and that may take locks and leads to deadlock
-        // Currently it is only used by WinRT event code and you should only use this function
-        // if you know for sure that either you won't run into dead locks or you need to live with the
-        // possiblity
-        //--------------------------------------------------------------------------------------------
-        [FriendAccessAllowed]
-        internal TKey FindEquivalentKeyUnsafe(TKey key, out TValue value)
-        {
-            lock (_lock)
-            {
-                return _container.FindEquivalentKeyUnsafe(key, out value);
-            }
-        }
-
-        //--------------------------------------------------------------------------------------------
-        // Returns a collection of keys - don't use in perf critical path
-        //--------------------------------------------------------------------------------------------
-        internal ICollection<TKey> Keys
-        {
-            get
-            {
-                lock (_lock)
-                {
-                    return _container.Keys;
-                }
-            }
-        }
-
-        //--------------------------------------------------------------------------------------------
-        // Returns a collection of values - don't use in perf critical path
-        //--------------------------------------------------------------------------------------------
-        internal ICollection<TValue> Values
-        {
-            get
-            {
-                lock (_lock)
-                {
-                    return _container.Values;
-                }
-            }
-        }
-
-        #endregion
-
         #region Private Members
 
         //----------------------------------------------------------------------------------------
@@ -882,84 +833,6 @@ namespace System.Runtime.CompilerServices
                 return newContainer;
             }
 
-            internal ICollection<TKey> Keys
-            {
-                get
-                {
-                    var list = new List<TKey>();
-
-                    for (int bucket = 0; bucket < _buckets.Length; ++bucket)
-                    {
-                        for (int entriesIndex = _buckets[bucket]; entriesIndex != -1; entriesIndex = _entries[entriesIndex].Next)
-                        {
-                            TKey thisKey = JitHelpers.UnsafeCast<TKey>(_entries[entriesIndex].depHnd.GetPrimary());
-                            if (thisKey != null)
-                            {
-                                list.Add(thisKey);
-                            }
-                        }
-                    }
-
-                    GC.KeepAlive(this); // ensure we don't get finalized while accessing DependentHandles.
-                    return list;
-                }
-            }
-
-            internal ICollection<TValue> Values
-            {
-                get
-                {
-                    var list = new List<TValue>();
-
-                    for (int bucket = 0; bucket < _buckets.Length; ++bucket)
-                    {
-                        for (int entriesIndex = _buckets[bucket]; entriesIndex != -1; entriesIndex = _entries[entriesIndex].Next)
-                        {
-                            object primary, secondary;
-                            primary = _entries[entriesIndex].depHnd.GetPrimaryAndSecondary(out secondary);
-
-                            // Now that we've secured a strong reference to the secondary, must check the primary again
-                            // to ensure it didn't expire (otherwise, we open a race where TryGetValue misreports an
-                            // expired key as a live key with a null value.)
-                            if (primary != null)
-                            {
-                                list.Add(JitHelpers.UnsafeCast<TValue>(secondary));
-                            }
-                        }
-                    }
-
-                    GC.KeepAlive(this); // ensure we don't get finalized while accessing DependentHandles.
-                    return list;
-                }
-            }
-
-            internal TKey FindEquivalentKeyUnsafe(TKey key, out TValue value)
-            {
-                for (int bucket = 0; bucket < _buckets.Length; ++bucket)
-                {
-                    for (int entriesIndex = _buckets[bucket]; entriesIndex != -1; entriesIndex = _entries[entriesIndex].Next)
-                    {
-                        if (_entries[entriesIndex].HashCode == -1)
-                        {
-                            continue;   // removed entry whose handle is awaiting condemnation by the finalizer.
-                        }
-
-                        object thisKey, thisValue;
-                        thisKey = _entries[entriesIndex].depHnd.GetPrimaryAndSecondary(out thisValue);
-                        if (Equals(thisKey, key))
-                        {
-                            GC.KeepAlive(this); // ensure we don't get finalized while accessing DependentHandles.
-                            value = JitHelpers.UnsafeCast<TValue>(thisValue);
-                            return JitHelpers.UnsafeCast<TKey>(thisKey);
-                        }
-                    }
-                }
-
-                GC.KeepAlive(this); // ensure we don't get finalized while accessing DependentHandles.
-                value = default(TValue);
-                return null;
-            }
-
             //----------------------------------------------------------------------------------------
             // Precondition:
             //     Must hold _lock.
index 0b7ba10..6c87739 100644 (file)
@@ -105,7 +105,8 @@ namespace System.Runtime.InteropServices.WindowsRuntime
             {
                 lock (ManagedEventRegistrationImpl.s_eventRegistrations)
                 {
-                    count += ManagedEventRegistrationImpl.s_eventRegistrations.Keys.Count;
+                    foreach (var item in ManagedEventRegistrationImpl.s_eventRegistrations)
+                        count++;
                 }
             }
 
@@ -537,6 +538,20 @@ namespace System.Runtime.InteropServices.WindowsRuntime
                 return (object)Marshal.GetRawIUnknownForComObjectNoAddRef(target);
             }
 
+            private static object FindEquivalentKeyUnsafe(ConditionalWeakTable<object, EventRegistrationTokenListWithCount> registrationTable, object handler, out EventRegistrationTokenListWithCount tokens)
+            {
+                foreach (KeyValuePair<object, EventRegistrationTokenListWithCount> item in registrationTable)
+                {
+                    if (Object.Equals(item.Key, handler))
+                    {
+                        tokens = item.Value;
+                        return item.Key;
+                    }
+                }
+                tokens = null;
+                return null;
+            }
+
             internal static void AddEventHandler<T>(Func<T, EventRegistrationToken> addMethod,
                                                   Action<EventRegistrationToken> removeMethod,
                                                   T handler)
@@ -581,7 +596,7 @@ namespace System.Runtime.InteropServices.WindowsRuntime
                             // will be added into B's token list, but once we unsubscribe B, we might end up removing
                             // the last token in C, and that may lead to crash.
                             //
-                            object key = registrationTokens.FindEquivalentKeyUnsafe(handler, out tokens);
+                            object key = FindEquivalentKeyUnsafe(registrationTokens, handler, out tokens);
                             if (key == null)
                             {
                                 tokens = new EventRegistrationTokenListWithCount(tokenListCount, token);
@@ -705,7 +720,7 @@ namespace System.Runtime.InteropServices.WindowsRuntime
                         // It actually doesn't matter which delegate - as long as it matches
                         // Note that inside TryGetValueWithValueEquality we assumes that any delegate 
                         // with the same value equality would have the same hash code
-                        object key = registrationTokens.FindEquivalentKeyUnsafe(handler, out tokens);
+                        object key = FindEquivalentKeyUnsafe(registrationTokens, handler, out tokens);
                         Debug.Assert((key != null && tokens != null) || (key == null && tokens == null),
                                         "key and tokens must be both null or non-null");
                         if (tokens == null)
@@ -773,9 +788,9 @@ namespace System.Runtime.InteropServices.WindowsRuntime
                     {
                         // Copy all tokens to tokensToRemove array which later we'll call removeMethod on
                         // outside this lock
-                        foreach (EventRegistrationTokenListWithCount tokens in registrationTokens.Values)
+                        foreach (KeyValuePair<object, EventRegistrationTokenListWithCount> item in registrationTokens)
                         {
-                            tokens.CopyTo(tokensToRemove);
+                            item.Value.CopyTo(tokensToRemove);
                         }
 
                         // Clear the table - at this point all event handlers are no longer in the cache
index 45d398f..666a192 100644 (file)
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
 
@@ -565,7 +565,12 @@ namespace System.Threading.Tasks
                 return new TaskScheduler[] { s_defaultTaskScheduler };
             }
 
-            ICollection<TaskScheduler> schedulers = s_activeTaskSchedulers.Keys;
+            List<TaskScheduler> schedulers = new List<TaskScheduler>();
+            foreach (var item in s_activeTaskSchedulers)
+            {
+                schedulers.Add(item.Key);
+            }
+
             if (!schedulers.Contains(s_defaultTaskScheduler))
             {
                 // Make sure the default is included, in case the debugger attached
@@ -573,8 +578,7 @@ namespace System.Threading.Tasks
                 schedulers.Add(s_defaultTaskScheduler);
             }
 
-            var arr = new TaskScheduler[schedulers.Count];
-            schedulers.CopyTo(arr, 0);
+            var arr = schedulers.ToArray();
             foreach (var scheduler in arr)
             {
                 Debug.Assert(scheduler != null, "Table returned an incorrect Count or CopyTo failed");