Skip to content

Commit 42a7dca

Browse files
committed
Dispose the owned 'current' object owned by PyIter instances when no longer needed.
1 parent 8f8aff9 commit 42a7dca

File tree

2 files changed

+41
-22
lines changed

2 files changed

+41
-22
lines changed

src/runtime/pyiter.cs

Lines changed: 34 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -21,42 +21,57 @@ public class PyIter : PyObject, IEnumerator<object>
2121
private PyObject _current = null;
2222

2323
/// <summary>
24-
/// PyIter Constructor
25-
/// </summary>
26-
///
27-
/// <remarks>
28-
/// Creates a new PyIter from an existing iterator reference. Note
29-
/// that the instance assumes ownership of the object reference.
30-
/// The object reference is not checked for type-correctness.
31-
/// </remarks>
24+
/// PyIter Constructor
25+
/// </summary>
26+
///
27+
/// <remarks>
28+
/// Creates a new PyIter from an existing iterator reference. Note
29+
/// that the instance assumes ownership of the object reference.
30+
/// The object reference is not checked for type-correctness.
31+
/// </remarks>
3232

33-
public PyIter(IntPtr ptr) : base(ptr) {}
33+
public PyIter(IntPtr ptr) : base(ptr) {}
3434

3535
/// <summary>
36-
/// PyIter Constructor
37-
/// </summary>
38-
///
39-
/// <remarks>
40-
/// Creates a Python iterator from an iterable. Like doing "iter(iterable)" in python.
41-
/// </remarks>
36+
/// PyIter Constructor
37+
/// </summary>
38+
///
39+
/// <remarks>
40+
/// Creates a Python iterator from an iterable. Like doing "iter(iterable)" in python.
41+
/// </remarks>
4242

43-
public PyIter(PyObject iterable) : base()
43+
public PyIter(PyObject iterable) : base()
4444
{
4545
obj = Runtime.PyObject_GetIter(iterable.obj);
4646
if (obj == IntPtr.Zero)
4747
throw new PythonException();
4848
}
4949

50+
protected override void Dispose(bool disposing)
51+
{
52+
if (null != _current)
53+
{
54+
_current.Dispose();
55+
_current = null;
56+
}
57+
base.Dispose(disposing);
58+
}
59+
5060
#region IEnumerator Members
5161

5262
public bool MoveNext()
5363
{
64+
// dispose of the previous object, if there was one
65+
if (null != _current)
66+
{
67+
_current.Dispose();
68+
_current = null;
69+
}
70+
5471
IntPtr next = Runtime.PyIter_Next(obj);
5572
if (next == IntPtr.Zero)
56-
{
57-
_current = null; //release reference
5873
return false;
59-
}
74+
6075
_current = new PyObject(next);
6176
return true;
6277
}

src/runtime/pyobject.cs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -118,19 +118,23 @@ public object AsManagedObject(Type t) {
118118
/// collection occurs.
119119
/// </remarks>
120120

121-
public void Dispose() {
121+
protected virtual void Dispose(bool disposing) {
122122
if (!disposed) {
123123
if (Runtime.Py_IsInitialized() > 0) {
124124
IntPtr gs = PythonEngine.AcquireLock();
125125
Runtime.Decref(obj);
126-
obj = IntPtr.Zero;
126+
obj = IntPtr.Zero;
127127
PythonEngine.ReleaseLock(gs);
128128
}
129-
GC.SuppressFinalize(this);
130129
disposed = true;
131130
}
132131
}
133132

133+
public void Dispose() {
134+
Dispose(true);
135+
GC.SuppressFinalize(this);
136+
}
137+
134138

135139
/// <summary>
136140
/// GetPythonType Method

0 commit comments

Comments
 (0)