Adding API ConditionalWeakTable.AddOrUpdate (#8490)
authorSantiago Fernandez Madero <safern@microsoft.com>
Sat, 10 Dec 2016 05:11:05 +0000 (21:11 -0800)
committerJan Kotas <jkotas@microsoft.com>
Sat, 10 Dec 2016 05:11:05 +0000 (21:11 -0800)
* Added ConditionalWeakTable.AddOrUpdate

src/mscorlib/model.xml
src/mscorlib/src/System/Runtime/CompilerServices/ConditionalWeakTable.cs
src/vm/comdependenthandle.cpp
src/vm/comdependenthandle.h
src/vm/ecalllist.h

index 441df0d..c221d6c 100644 (file)
     <Type Name="System.Runtime.CompilerServices.ConditionalWeakTable&lt;TKey,TValue&gt;">
       <Member Name="#ctor" />
       <Member Name="Add(TKey,TValue)" />
+      <Member Name="AddOrUpdate(TKey,TValue)" />
       <Member Name="Remove(TKey)" />
       <Member Name="TryGetValue(TKey,TValue@)" />
       <Member Name="GetValue(TKey,System.Runtime.CompilerServices.ConditionalWeakTable+CreateValueCallback)" />
index 932bbd1..5e6a3f4 100644 (file)
@@ -138,6 +138,37 @@ namespace System.Runtime.CompilerServices
         }
 
         //--------------------------------------------------------------------------------------------
+        // key: key to add or update. May not be null.
+        // value: value to associate with key.
+        //
+        // If the key is already entered into the dictionary, this method will update the value associated with key.
+        //--------------------------------------------------------------------------------------------
+        public void AddOrUpdate(TKey key, TValue value)
+        {
+            if (key == null)
+            {
+                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
+            }
+
+            lock (_lock)
+            {
+                object otherValue;
+                int entryIndex = _container.FindEntry(key, out otherValue);
+
+                // if we found a key we should just update, if no we should create a new entry.
+                if (entryIndex != -1)
+                {
+                    _container.UpdateValue(entryIndex, value);
+                }
+                else
+                {
+                    CreateEntry(key, value);
+                }
+
+            }
+        }
+
+        //--------------------------------------------------------------------------------------------
         // key: key to remove. May not be null.
         //
         // Returns true if the key is found and removed. Returns false if the key was not in the dictionary.
@@ -495,6 +526,19 @@ namespace System.Runtime.CompilerServices
                 return false;
             }
 
+
+            internal void UpdateValue(int entryIndex, TValue newValue)
+            {
+                Debug.Assert(entryIndex != -1);
+
+                VerifyIntegrity();
+                _invalid = true;
+
+                _entries[entryIndex].depHnd.SetSecondary(newValue);
+
+                _invalid = false;
+            }
+
             //----------------------------------------------------------------------------------------
             // This does two things: resize and scrub expired keys off bucket lists.
             //
@@ -796,6 +840,11 @@ namespace System.Runtime.CompilerServices
             nGetPrimaryAndSecondary(_handle, out primary, out secondary);
         }
 
+        public void SetSecondary(object secondary)
+        {
+            nSetSecondary(_handle, secondary);
+        }
+
         //----------------------------------------------------------------------
         // Forces dependentHandle back to non-allocated state (if not already there)
         // and frees the handle if needed.
@@ -822,6 +871,9 @@ namespace System.Runtime.CompilerServices
         private static extern void nGetPrimaryAndSecondary(IntPtr dependentHandle, out object primary, out object secondary);
 
         [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void nSetSecondary(IntPtr dependentHandle, object secondary);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
         private static extern void nFree(IntPtr dependentHandle);
         #endregion
 
index 0d2cac5..7a46f69 100644 (file)
@@ -74,3 +74,13 @@ FCIMPL3(VOID, DependentHandle::nGetPrimaryAndSecondary, OBJECTHANDLE handle, Obj
 }
 FCIMPLEND
 
+FCIMPL2(VOID, DependentHandle::nSetSecondary, OBJECTHANDLE handle, Object *_secondary)
+{
+    FCALL_CONTRACT;
+
+    _ASSERTE(handle != NULL && _secondary != NULL);
+
+    OBJECTREF secondary(_secondary);
+    SetDependentHandleSecondary(handle, secondary);
+}
+FCIMPLEND
index 7cf5a1e..29110c1 100644 (file)
@@ -45,6 +45,7 @@ public:
     static FCDECL2(VOID,   nGetPrimary, OBJECTHANDLE handle, Object **outPrimary);
     static FCDECL3(VOID,   nGetPrimaryAndSecondary, OBJECTHANDLE handle, Object **outPrimary, Object **outSecondary);
     static FCDECL1(VOID,   nFree, OBJECTHANDLE handle);
+    static FCDECL2(VOID,   nSetSecondary, OBJECTHANDLE handle, Object *secondary);
 };
 
 #endif
index f87fafc..03b675f 100644 (file)
@@ -108,6 +108,7 @@ FCFuncStart(gDependentHandleFuncs)
     FCFuncElement("nGetPrimary",             DependentHandle::nGetPrimary)
     FCFuncElement("nGetPrimaryAndSecondary", DependentHandle::nGetPrimaryAndSecondary)
     FCFuncElement("nFree",                   DependentHandle::nFree)
+    FCFuncElement("nSetSecondary",           DependentHandle::nSetSecondary)
 FCFuncEnd()
 
 #ifndef FEATURE_CORECLR