Implement APIs for some threading metrics (CoreRT) (dotnet/corert#7066)
authorKoundinya Veluri <kouvel@users.noreply.github.com>
Tue, 23 Apr 2019 06:31:37 +0000 (23:31 -0700)
committerJan Kotas <jkotas@microsoft.com>
Tue, 23 Apr 2019 13:24:44 +0000 (06:24 -0700)
* Implement APIs for some threading metrics (CoreRT)

- API review: https://github.com/dotnet/corefx/issues/35500
- May depend on https://github.com/dotnet/coreclr/pull/22754

* Use thread-locals for counting, use finalizer instead of runtime to detect thread exit

* Don't let the count properties throw OOM

* Remove some flushes

Signed-off-by: dotnet-bot <dotnet-bot@microsoft.com>
src/System.Private.CoreLib/shared/System/Threading/ThreadLocal.cs

index 8c19903..276caed 100644 (file)
@@ -454,16 +454,16 @@ namespace System.Threading
         /// <summary>Gets all of the threads' values in a list.</summary>
         private List<T>? GetValuesAsList()
         {
-            List<T> valueList = new List<T>();
+            LinkedSlot? linkedSlot = _linkedSlot;
             int id = ~_idComplement;
-            if (id == -1)
+            if (id == -1 || linkedSlot == null)
             {
                 return null;
             }
 
             // Walk over the linked list of slots and gather the values associated with this ThreadLocal instance.
-            Debug.Assert(_linkedSlot != null, "Should only be null if the instance was disposed.");
-            for (LinkedSlot? linkedSlot = _linkedSlot._next; linkedSlot != null; linkedSlot = linkedSlot._next)
+            var valueList = new List<T>();
+            for (linkedSlot = linkedSlot._next; linkedSlot != null; linkedSlot = linkedSlot._next)
             {
                 // We can safely read linkedSlot.Value. Even if this ThreadLocal has been disposed in the meantime, the LinkedSlot
                 // objects will never be assigned to another ThreadLocal instance.
@@ -473,6 +473,32 @@ namespace System.Threading
             return valueList;
         }
 
+        internal IEnumerable<T> ValuesAsEnumerable
+        {
+            get
+            {
+                if (!_trackAllValues)
+                {
+                    throw new InvalidOperationException(SR.ThreadLocal_ValuesNotAvailable);
+                }
+
+                LinkedSlot? linkedSlot = _linkedSlot;
+                int id = ~_idComplement;
+                if (id == -1 || linkedSlot == null)
+                {
+                    throw new ObjectDisposedException(SR.ThreadLocal_Disposed);
+                }
+
+                // Walk over the linked list of slots and gather the values associated with this ThreadLocal instance.
+                for (linkedSlot = linkedSlot._next; linkedSlot != null; linkedSlot = linkedSlot._next)
+                {
+                    // We can safely read linkedSlot.Value. Even if this ThreadLocal has been disposed in the meantime, the LinkedSlot
+                    // objects will never be assigned to another ThreadLocal instance.
+                    yield return linkedSlot._value;
+                }
+            }
+        }
+
         /// <summary>Gets the number of threads that have data in this instance.</summary>
         private int ValuesCountForDebugDisplay
         {