pFad - Phone/Frame/Anonymizer/Declutterfier! Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

URL: http://github.com/pythonnet/pythonnet/commit/be5ba3473218927187d278f2b24877bee3165266

href="https://github.githubassets.com/assets/global-d18f184ea1a06a2c.css" /> Snapshot pypath, use ConcurrentDictionary for thunks and slot holders · pythonnet/pythonnet@be5ba34 · GitHub
Skip to content

Commit be5ba34

Browse files
greateggsgregfilmor
authored andcommitted
Snapshot pypath, use ConcurrentDictionary for thunks and slot holders
1 parent a30c84e commit be5ba34

5 files changed

Lines changed: 24 additions & 15 deletions

File tree

src/runtime/AssemblyManager.cs

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,9 @@ internal class AssemblyManager
3737

3838
// modified from event handlers below, potentially triggered from different .NET threads
3939
private static readonly ConcurrentQueue<Assembly> assemblies = new();
40-
internal static readonly List<string> pypath = new (capacity: 16);
40+
// Snapshot; UpdatePath swaps under lock, readers iterate the captured ref.
41+
internal static volatile IReadOnlyList<string> pypath = Array.Empty<string>();
42+
private static readonly object _pypathLock = new();
4143
private AssemblyManager()
4244
{
4345
}
@@ -49,7 +51,7 @@ private AssemblyManager()
4951
//github.com/ </summary>
5052
internal static void Initialize()
5153
{
52-
pypath.Clear();
54+
pypath = Array.Empty<string>();
5355

5456
AppDomain domain = AppDomain.CurrentDomain;
5557

@@ -154,19 +156,20 @@ internal static void UpdatePath()
154156
{
155157
BorrowedReference list = Runtime.PySys_GetObject("path");
156158
var count = Runtime.PyList_Size(list);
157-
if (count != pypath.Count)
159+
if (count == pypath.Count) return;
160+
161+
lock (_pypathLock)
158162
{
159-
pypath.Clear();
163+
if (count == pypath.Count) return;
164+
var fresh = new List<string>(checked((int)count));
160165
probed.Clear();
161166
for (var i = 0; i < count; i++)
162167
{
163168
BorrowedReference item = Runtime.PyList_GetItem(list, i);
164169
string? path = Runtime.GetManagedString(item);
165-
if (path != null)
166-
{
167-
pypath.Add(path);
168-
}
170+
if (path != null) fresh.Add(path);
169171
}
172+
pypath = fresh;
170173
}
171174
}
172175

@@ -196,7 +199,8 @@ public static string FindAssembly(string name)
196199

197200
static IEnumerable<string> FindAssemblyCandidates(string name)
198201
{
199-
foreach (string head in pypath)
202+
var paths = pypath;
203+
foreach (string head in paths)
200204
{
201205
string path;
202206
if (head == null || head.Length == 0)

src/runtime/Finalizer.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,8 @@ internal void ThrottledCollect()
115115
if (!started) throw new InvalidOperationException($"{nameof(PythonEngine)} is not initialized");
116116

117117
if (!Enable || Interlocked.Increment(ref _throttled) < Threshold) return;
118-
// Stale pointers on the queue would crash Py_DecRef during teardown.
118+
// Defends against externally-driven Py_Finalize (e.g. host's atexit):
119+
// queue pointers may already be freed, so skip the drain.
119120
if (Runtime._Py_IsFinalizing() == true) return;
120121
Interlocked.Exchange(ref _throttled, 0);
121122
this.Collect();
@@ -138,7 +139,7 @@ internal void AddFinalizedObject(ref IntPtr obj, int run
138139
return;
139140
}
140141

141-
// Skip on FT: stale ob_ref_local read from the finalizer thread can crash.
142+
// Skip on FT: the split refcount can race here and trip the assert spuriously.
142143
if (!Native.ABI.IsFreeThreaded)
143144
{
144145
Debug.Assert(Runtime.Refcount(new BorrowedReference(obj)) > 0);

src/runtime/Interop.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,9 @@ internal static Type GetPrototype(MethodInfo method)
141141
}
142142

143143

144-
internal static Dictionary<IntPtr, Delegate> allocatedThunks = new();
144+
// Concurrent: documents the multi-writer contract previously enforced
145+
// by callers happening to hold TypeManager._cacheCreateLock.
146+
internal static ConcurrentDictionary<IntPtr, Delegate> allocatedThunks = new();
145147

146148
internal static ThunkInfo GetThunk(MethodInfo method)
147149
{

src/runtime/Runtime.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -617,7 +617,7 @@ internal static unsafe void XIncref(BorrowedReference op)
617617
internal static unsafe void XDecref(StolenReference op)
618618
{
619619
#if DEBUG
620-
// Racy on FT: stale ob_ref_local read may crash.
620+
// Skip on FT: the split refcount can race here and trip the assert spuriously.
621621
Debug.Assert(op == null || Native.ABI.IsFreeThreaded || Refcount(new BorrowedReference(op.Pointer)) > 0);
622622
Debug.Assert(_isInitialized || Py_IsInitialized() != 0 || _Py_IsFinalizing() != false);
623623
#endif

src/runtime/TypeManager.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,9 @@ internal class TypeManager
3333
internal static readonly ConcurrentDictionary<MaybeType, PyType> cache = new();
3434
internal static readonly object _cacheCreateLock = new();
3535

36-
static readonly Dictionary<PyType, SlotsHolder> _slotsHolders = new(PythonReferenceComparer.Instance);
36+
// Concurrent: documents the multi-writer contract previously enforced
37+
// by callers happening to hold _cacheCreateLock.
38+
static readonly ConcurrentDictionary<PyType, SlotsHolder> _slotsHolders = new(PythonReferenceComparer.Instance);
3739

3840
// Slots which must be set
3941
private static readonly string[] _requiredSlots = new string[]
@@ -949,7 +951,7 @@ internal static SlotsHolder CreateSlotsHolder(PyType type)
949951
{
950952
type = new PyType(type);
951953
var holder = new SlotsHolder(type);
952-
_slotsHolders.Add(type, holder);
954+
_slotsHolders[type] = holder;
953955
return holder;
954956
}
955957
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad © 2024 Your Company Name. All rights reserved.





Check this box to remove all script contents from the fetched content.



Check this box to remove all images from the fetched content.


Check this box to remove all CSS styles from the fetched content.


Check this box to keep images inefficiently compressed and original size.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy