Skip to content

Commit ab0cb02

Browse files
committed
Add explicit release action
1 parent 4df7760 commit ab0cb02

File tree

1 file changed

+64
-57
lines changed

1 file changed

+64
-57
lines changed

src/runtime/runtime.cs

Lines changed: 64 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -198,71 +198,91 @@ internal static void Initialize(bool initSigs = false)
198198
IntPtr op;
199199
{
200200
var builtins = GetBuiltins();
201-
SetPyMember(ref PyNotImplemented, PyObject_GetAttrString(builtins, "NotImplemented"));
202-
203-
SetPyMember(ref PyBaseObjectType, PyObject_GetAttrString(builtins, "object"));
204-
205-
SetPyMember(ref PyNone, PyObject_GetAttrString(builtins, "None"));
206-
SetPyMember(ref PyTrue, PyObject_GetAttrString(builtins, "True"));
207-
SetPyMember(ref PyFalse, PyObject_GetAttrString(builtins, "False"));
208-
209-
SetPyMember(ref PyBoolType, PyObject_Type(PyTrue));
210-
SetPyMember(ref PyNoneType, PyObject_Type(PyNone));
211-
SetPyMember(ref PyTypeType, PyObject_Type(PyNoneType));
201+
SetPyMember(ref PyNotImplemented, PyObject_GetAttrString(builtins, "NotImplemented"),
202+
() => PyNotImplemented = IntPtr.Zero);
203+
204+
SetPyMember(ref PyBaseObjectType, PyObject_GetAttrString(builtins, "object"),
205+
() => PyBaseObjectType = IntPtr.Zero);
206+
207+
SetPyMember(ref PyNone, PyObject_GetAttrString(builtins, "None"),
208+
() => PyNone = IntPtr.Zero);
209+
SetPyMember(ref PyTrue, PyObject_GetAttrString(builtins, "True"),
210+
() => PyTrue = IntPtr.Zero);
211+
SetPyMember(ref PyFalse, PyObject_GetAttrString(builtins, "False"),
212+
() => PyFalse = IntPtr.Zero);
213+
214+
SetPyMember(ref PyBoolType, PyObject_Type(PyTrue),
215+
() => PyBoolType = IntPtr.Zero);
216+
SetPyMember(ref PyNoneType, PyObject_Type(PyNone),
217+
() => PyNoneType = IntPtr.Zero);
218+
SetPyMember(ref PyTypeType, PyObject_Type(PyNoneType),
219+
() => PyTypeType = IntPtr.Zero);
212220

213221
op = PyObject_GetAttrString(builtins, "len");
214-
SetPyMember(ref PyMethodType, PyObject_Type(op));
222+
SetPyMember(ref PyMethodType, PyObject_Type(op),
223+
() => PyMethodType = IntPtr.Zero);
215224
XDecref(op);
216225

217226
// For some arcane reason, builtins.__dict__.__setitem__ is *not*
218227
// a wrapper_descriptor, even though dict.__setitem__ is.
219228
//
220229
// object.__init__ seems safe, though.
221230
op = PyObject_GetAttrString(PyBaseObjectType, "__init__");
222-
SetPyMember(ref PyWrapperDescriptorType, PyObject_Type(op));
231+
SetPyMember(ref PyWrapperDescriptorType, PyObject_Type(op),
232+
() => PyWrapperDescriptorType = IntPtr.Zero);
223233
XDecref(op);
224234

225-
SetPyMember(ref PySuper_Type, PyObject_GetAttrString(builtins, "super"));
235+
SetPyMember(ref PySuper_Type, PyObject_GetAttrString(builtins, "super"),
236+
() => PySuper_Type = IntPtr.Zero);
226237

227238
XDecref(builtins);
228239
}
229240

230241
op = PyString_FromString("string");
231-
SetPyMember(ref PyStringType, PyObject_Type(op));
242+
SetPyMember(ref PyStringType, PyObject_Type(op),
243+
() => PyStringType = IntPtr.Zero);
232244
XDecref(op);
233245

234246
op = PyUnicode_FromString("unicode");
235-
SetPyMember(ref PyUnicodeType, PyObject_Type(op));
247+
SetPyMember(ref PyUnicodeType, PyObject_Type(op),
248+
() => PyUnicodeType = IntPtr.Zero);
236249
XDecref(op);
237250

238251
#if PYTHON3
239252
op = PyBytes_FromString("bytes");
240-
SetPyMember(ref PyBytesType, PyObject_Type(op));
253+
SetPyMember(ref PyBytesType, PyObject_Type(op),
254+
() => PyBytesType = IntPtr.Zero);
241255
XDecref(op);
242256
#endif
243257

244258
op = PyTuple_New(0);
245-
SetPyMember(ref PyTupleType, PyObject_Type(op));
259+
SetPyMember(ref PyTupleType, PyObject_Type(op),
260+
() => PyTupleType = IntPtr.Zero);
246261
XDecref(op);
247262

248263
op = PyList_New(0);
249-
SetPyMember(ref PyListType, PyObject_Type(op));
264+
SetPyMember(ref PyListType, PyObject_Type(op),
265+
() => PyListType = IntPtr.Zero);
250266
XDecref(op);
251267

252268
op = PyDict_New();
253-
SetPyMember(ref PyDictType, PyObject_Type(op));
269+
SetPyMember(ref PyDictType, PyObject_Type(op),
270+
() => PyDictType = IntPtr.Zero);
254271
XDecref(op);
255272

256273
op = PyInt_FromInt32(0);
257-
SetPyMember(ref PyIntType, PyObject_Type(op));
274+
SetPyMember(ref PyIntType, PyObject_Type(op),
275+
() => PyIntType = IntPtr.Zero);
258276
XDecref(op);
259277

260278
op = PyLong_FromLong(0);
261-
SetPyMember(ref PyLongType, PyObject_Type(op));
279+
SetPyMember(ref PyLongType, PyObject_Type(op),
280+
() => PyLongType = IntPtr.Zero);
262281
XDecref(op);
263282

264283
op = PyFloat_FromDouble(0);
265-
SetPyMember(ref PyFloatType, PyObject_Type(op));
284+
SetPyMember(ref PyFloatType, PyObject_Type(op),
285+
() => PyFloatType = IntPtr.Zero);
266286
XDecref(op);
267287

268288
#if !PYTHON2
@@ -274,10 +294,12 @@ internal static void Initialize(bool initSigs = false)
274294
IntPtr d = PyDict_New();
275295

276296
IntPtr c = PyClass_New(IntPtr.Zero, d, s);
277-
SetPyMember(ref PyClassType, PyObject_Type(c));
297+
SetPyMember(ref PyClassType, PyObject_Type(c),
298+
() => PyClassType = IntPtr.Zero);
278299

279300
IntPtr i = PyInstance_New(c, IntPtr.Zero, IntPtr.Zero);
280-
SetPyMember(ref PyInstanceType, PyObject_Type(i));
301+
SetPyMember(ref PyInstanceType, PyObject_Type(i),
302+
() => PyInstanceType = IntPtr.Zero);
281303

282304
XDecref(s);
283305
XDecref(i);
@@ -393,12 +415,12 @@ internal static int AtExit()
393415
return 0;
394416
}
395417

396-
private static void SetPyMember(ref IntPtr obj, IntPtr value)
418+
private static void SetPyMember(ref IntPtr obj, IntPtr value, Action onRelease)
397419
{
398420
// XXX: For current usages, value should not be null.
399421
PythonException.ThrowIfIsNull(value);
400422
obj = value;
401-
_pyRefs.Add(ref obj);
423+
_pyRefs.Add(value, onRelease);
402424
}
403425

404426
private static void ResetPyMembers()
@@ -977,7 +999,7 @@ internal static int PyObject_Compare(IntPtr value1, IntPtr value2)
977999

9781000
internal static long PyObject_Size(IntPtr pointer)
9791001
{
980-
return (long) _PyObject_Size(pointer);
1002+
return (long)_PyObject_Size(pointer);
9811003
}
9821004

9831005
[DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "PyObject_Size")]
@@ -1093,7 +1115,7 @@ internal static bool PyLong_Check(IntPtr ob)
10931115

10941116
internal static IntPtr PyLong_FromUnsignedLong(object value)
10951117
{
1096-
if(Is32Bit || IsWindows)
1118+
if (Is32Bit || IsWindows)
10971119
return PyLong_FromUnsignedLong32(Convert.ToUInt32(value));
10981120
else
10991121
return PyLong_FromUnsignedLong64(Convert.ToUInt64(value));
@@ -1283,7 +1305,7 @@ internal static int PySequence_DelSlice(IntPtr pointer, long i1, long i2)
12831305

12841306
internal static long PySequence_Size(IntPtr pointer)
12851307
{
1286-
return (long) _PySequence_Size(pointer);
1308+
return (long)_PySequence_Size(pointer);
12871309
}
12881310

12891311
[DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "PySequence_Size")]
@@ -1308,7 +1330,7 @@ internal static IntPtr PySequence_Repeat(IntPtr pointer, long count)
13081330

13091331
internal static long PySequence_Count(IntPtr pointer, IntPtr value)
13101332
{
1311-
return (long) _PySequence_Count(pointer, value);
1333+
return (long)_PySequence_Count(pointer, value);
13121334
}
13131335

13141336
[DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "PySequence_Count")]
@@ -1351,7 +1373,7 @@ internal static IntPtr PyString_FromString(string value)
13511373

13521374
internal static long PyBytes_Size(IntPtr op)
13531375
{
1354-
return (long) _PyBytes_Size(op);
1376+
return (long)_PyBytes_Size(op);
13551377
}
13561378

13571379
[DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "PyBytes_Size")]
@@ -1582,7 +1604,7 @@ internal static bool PyDict_Check(IntPtr ob)
15821604

15831605
internal static long PyDict_Size(IntPtr pointer)
15841606
{
1585-
return (long) _PyDict_Size(pointer);
1607+
return (long)_PyDict_Size(pointer);
15861608
}
15871609

15881610
[DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "PyDict_Size")]
@@ -1660,7 +1682,7 @@ internal static int PyList_SetSlice(IntPtr pointer, long start, long end, IntPtr
16601682

16611683
internal static long PyList_Size(IntPtr pointer)
16621684
{
1663-
return (long) _PyList_Size(pointer);
1685+
return (long)_PyList_Size(pointer);
16641686
}
16651687

16661688
[DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "PyList_Size")]
@@ -1709,7 +1731,7 @@ internal static IntPtr PyTuple_GetSlice(IntPtr pointer, long start, long end)
17091731

17101732
internal static long PyTuple_Size(IntPtr pointer)
17111733
{
1712-
return (long) _PyTuple_Size(pointer);
1734+
return (long)_PyTuple_Size(pointer);
17131735
}
17141736

17151737
[DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "PyTuple_Size")]
@@ -1976,40 +1998,25 @@ internal static IntPtr GetBuiltins()
19761998

19771999
class PyReferenceCollection
19782000
{
1979-
public List<IntPtr> _objects { get; private set; }
1980-
1981-
public PyReferenceCollection()
1982-
{
1983-
_objects = new List<IntPtr>();
1984-
}
2001+
private List<KeyValuePair<IntPtr, Action>> _actions = new List<KeyValuePair<IntPtr, Action>>();
19852002

19862003
/// <summary>
19872004
/// Record obj's address to release the obj in the future,
19882005
/// obj must alive before calling Release.
19892006
/// </summary>
1990-
public void Add(ref IntPtr obj)
2007+
public void Add(IntPtr ob, Action onRelease)
19912008
{
1992-
unsafe
1993-
{
1994-
fixed (void* p = &obj)
1995-
{
1996-
_objects.Add((IntPtr)p);
1997-
}
1998-
}
2009+
_actions.Add(new KeyValuePair<IntPtr, Action>(ob, onRelease));
19992010
}
20002011

20012012
public void Release()
20022013
{
2003-
foreach (var objRef in _objects)
2014+
foreach (var item in _actions)
20042015
{
2005-
unsafe
2006-
{
2007-
var p = (void**)objRef;
2008-
Runtime.XDecref((IntPtr)(*p));
2009-
*p = null;
2010-
}
2016+
Runtime.XDecref(item.Key);
2017+
item.Value?.Invoke();
20112018
}
2012-
_objects.Clear();
2019+
_actions.Clear();
20132020
}
20142021
}
20152022
}

0 commit comments

Comments
 (0)