| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent a18e872 commit 0a9d482
6 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1,4 +1,5 @@ | |||
| 1 | 1 | using System; | |
| 2 | + using System.Collections.Concurrent; | ||
| 2 | 3 | using System.Collections.Generic; | |
| 3 | 4 | using System.Diagnostics; | |
| 4 | 5 | using System.Linq; | |
@@ -37,8 +38,8 @@ internal class ClassManager | |||
| 37 | 38 | // `cache` — only fully-initialised types; safe to read without the lock. | |
| 38 | 39 | // `_inProgressCache` — partial types being built inside the lock; visible only | |
| 39 | 40 | // to the building thread (for self-referential definitions). | |
| 40 | - internal static System.Collections.Concurrent.ConcurrentDictionary<MaybeType, ReflectedClrType> cache = new(); | ||
| 41 | - internal static readonly System.Collections.Concurrent.ConcurrentDictionary<MaybeType, ReflectedClrType> _inProgressCache = new(); | ||
| 41 | + internal static ConcurrentDictionary<MaybeType, ReflectedClrType> cache = new(); | ||
| 42 | + internal static readonly ConcurrentDictionary<MaybeType, ReflectedClrType> _inProgressCache = new(); | ||
| 42 | 43 | internal static readonly object _cacheCreateLock = new(); | |
| 43 | 44 | private static readonly Type dtype; | |
| 44 | 45 | ||
@@ -115,7 +116,7 @@ internal static ClassManagerState SaveRuntimeData() | |||
| 115 | 116 | ||
| 116 | 117 | internal static void RestoreRuntimeData(ClassManagerState storage) | |
| 117 | 118 | { | |
| 118 | - cache = new System.Collections.Concurrent.ConcurrentDictionary<MaybeType, ReflectedClrType>(storage.Cache); | ||
| 119 | + cache = new ConcurrentDictionary<MaybeType, ReflectedClrType>(storage.Cache); | ||
| 119 | 120 | var invalidClasses = new List<KeyValuePair<MaybeType, ReflectedClrType>>(); | |
| 120 | 121 | var contexts = storage.Contexts; | |
| 121 | 122 | foreach (var pair in cache) | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1,4 +1,5 @@ | |||
| 1 | 1 | using System; | |
| 2 | + using System.Collections.Concurrent; | ||
| 2 | 3 | using System.Collections.Generic; | |
| 3 | 4 | using System.Diagnostics; | |
| 4 | 5 | using System.Linq; | |
@@ -104,7 +105,10 @@ public enum TypeFlags: long | |||
| 104 | 105 | ||
| 105 | 106 | internal class Interop | |
| 106 | 107 | { | |
| 107 | - static readonly Dictionary<MethodInfo, Type> delegateTypes = new(); | ||
| 108 | + // Hit on every type-slot installation; thread-safe for free-threaded Python. | ||
| 109 | + // Two threads racing past TryGetValue with the old plain Dictionary would | ||
| 110 | + // throw on Add ("duplicate key") instead of silently picking one winner. | ||
| 111 | + static readonly ConcurrentDictionary<MethodInfo, Type> delegateTypes = new(); | ||
| 108 | 112 | ||
| 109 | 113 | internal static Type GetPrototype(MethodInfo method) | |
| 110 | 114 | { | |
@@ -131,7 +135,7 @@ internal static Type GetPrototype(MethodInfo method) | |||
| 131 | 135 | ||
| 132 | 136 | if (invoke.ReturnType != method.ReturnType) continue; | |
| 133 | 137 | ||
| 134 | - delegateTypes.Add(method, candidate); | ||
| 138 | + delegateTypes.TryAdd(method, candidate); | ||
| 135 | 139 | return candidate; | |
| 136 | 140 | } | |
| 137 | 141 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1,4 +1,5 @@ | |||
| 1 | 1 | using System; | |
| 2 | + using System.Collections.Concurrent; | ||
| 2 | 3 | using System.Collections.Generic; | |
| 3 | 4 | using System.Linq; | |
| 4 | 5 | using System.Reflection; | |
@@ -27,7 +28,7 @@ internal class TypeManager | |||
| 27 | 28 | ||
| 28 | 29 | private const BindingFlags tbFlags = BindingFlags.Public | BindingFlags.Static; | |
| 29 | 30 | // Thread-safe cache; multi-step creation in GetType is serialised via _cacheCreateLock. | |
| 30 | - internal static readonly System.Collections.Concurrent.ConcurrentDictionary<MaybeType, PyType> cache = new(); | ||
| 31 | + internal static readonly ConcurrentDictionary<MaybeType, PyType> cache = new(); | ||
| 31 | 32 | internal static readonly object _cacheCreateLock = new(); | |
| 32 | 33 | ||
| 33 | 34 | static readonly Dictionary<PyType, SlotsHolder> _slotsHolders = new(PythonReferenceComparer.Instance); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1,5 +1,6 @@ | |||
| 1 | 1 | using System; | |
| 2 | 2 | using System.Collections; | |
| 3 | + using System.Collections.Concurrent; | ||
| 3 | 4 | using System.Collections.Generic; | |
| 4 | 5 | using System.Diagnostics; | |
| 5 | 6 | using System.Linq; | |
@@ -374,7 +375,9 @@ public static int tp_clear(BorrowedReference ob) | |||
| 374 | 375 | return 0; | |
| 375 | 376 | } | |
| 376 | 377 | ||
| 377 | - static readonly HashSet<IntPtr> ClearVisited = new(); | ||
| 378 | + // Re-entrancy guard for tp_clear. Thread-safe so concurrent tp_clear from | ||
| 379 | + // different threads (free-threaded or finalizer-thread) cannot tear the set. | ||
| 380 | + static readonly ConcurrentDictionary<IntPtr, byte> ClearVisited = new(); | ||
| 378 | 381 | ||
| 379 | 382 | internal static unsafe int BaseUnmanagedClear(BorrowedReference ob) | |
| 380 | 383 | { | |
@@ -390,11 +393,11 @@ internal static unsafe int BaseUnmanagedClear(BorrowedReference ob) | |||
| 390 | 393 | if (clearPtr == TypeManager.subtype_clear) | |
| 391 | 394 | { | |
| 392 | 395 | var addr = ob.DangerousGetAddress(); | |
| 393 | - if (!ClearVisited.Add(addr)) | ||
| 396 | + if (!ClearVisited.TryAdd(addr, 0)) | ||
| 394 | 397 | return 0; | |
| 395 | 398 | ||
| 396 | 399 | int res = clear(ob); | |
| 397 | - ClearVisited.Remove(addr); | ||
| 400 | + ClearVisited.TryRemove(addr, out _); | ||
| 398 | 401 | return res; | |
| 399 | 402 | } | |
| 400 | 403 | else | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1,4 +1,5 @@ | |||
| 1 | 1 | using System; | |
| 2 | + using System.Collections.Concurrent; | ||
| 2 | 3 | using System.Collections.Generic; | |
| 3 | 4 | using System.Diagnostics; | |
| 4 | 5 | using System.Runtime.InteropServices; | |
@@ -44,7 +45,7 @@ public virtual NewReference Alloc() | |||
| 44 | 45 | ||
| 45 | 46 | // "borrowed" references; thread-safe to survive free-threaded Python and | |
| 46 | 47 | // .NET finalizer-thread races. | |
| 47 | - internal static readonly System.Collections.Concurrent.ConcurrentDictionary<IntPtr, byte> loadedExtensions = new(); | ||
| 48 | + internal static readonly ConcurrentDictionary<IntPtr, byte> loadedExtensions = new(); | ||
| 48 | 49 | void SetupGc (BorrowedReference ob, BorrowedReference tp) | |
| 49 | 50 | { | |
| 50 | 51 | GCHandle gc = GCHandle.Alloc(this); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1,4 +1,5 @@ | |||
| 1 | 1 | using System; | |
| 2 | + using System.Collections.Concurrent; | ||
| 2 | 3 | using System.Collections.Generic; | |
| 3 | 4 | using System.Diagnostics; | |
| 4 | 5 | using System.Linq; | |
@@ -13,13 +14,14 @@ namespace Python.Runtime | |||
| 13 | 14 | [Serializable] | |
| 14 | 15 | internal class ModuleObject : ExtensionType | |
| 15 | 16 | { | |
| 16 | - private readonly Dictionary<string, PyObject> cache = new(); | ||
| 17 | + // Hot path on every `Module.Attr` access; thread-safe for free-threaded Python. | ||
| 18 | + private readonly ConcurrentDictionary<string, PyObject> cache = new(); | ||
| 17 | 19 | ||
| 18 | 20 | internal string moduleName; | |
| 19 | 21 | internal PyDict dict; | |
| 20 | 22 | protected string _namespace; | |
| 21 | 23 | private readonly PyList __all__ = new (); | |
| 22 | - private readonly HashSet<string> allNames = new(); | ||
| 24 | + private readonly ConcurrentDictionary<string, byte> allNames = new(); | ||
| 23 | 25 | ||
| 24 | 26 | // Attributes to be set on the module according to PEP302 and 451 | |
| 25 | 27 | // by the import machinery. | |
@@ -193,7 +195,7 @@ public void LoadNames() | |||
| 193 | 195 | hasValidAttribute = !attrVal.IsNull(); | |
| 194 | 196 | } | |
| 195 | 197 | ||
| 196 | - if (hasValidAttribute && allNames.Add(name)) | ||
| 198 | + if (hasValidAttribute && allNames.TryAdd(name, 0)) | ||
| 197 | 199 | { | |
| 198 | 200 | // if it's a valid attribute, add it to __all__ once. | |
| 199 | 201 | using var pyname = Runtime.PyString_FromString(name); | |
@@ -267,7 +269,7 @@ internal void ResetModuleMembers() | |||
| 267 | 269 | } | |
| 268 | 270 | Runtime.PyErr_Clear(); | |
| 269 | 271 | } | |
| 270 | - cache.Remove(memberName); | ||
| 272 | + cache.TryRemove(memberName, out _); | ||
| 271 | 273 | } | |
| 272 | 274 | } | |
| 273 | 275 | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments