Skip to content

Commit 32af1f4

Browse files
author
dse
committed
Simple woking finalizer implementation.
1 parent cfc6409 commit 32af1f4

File tree

2 files changed

+18
-113
lines changed

2 files changed

+18
-113
lines changed
Lines changed: 17 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -1,154 +1,61 @@
11
using System;
22
using System.Collections.Concurrent;
3-
using System.Threading;
4-
using System.Threading.Tasks;
53

64
namespace Python.Runtime
75
{
86
internal class PyReferenceDecrementer: IDisposable
97
{
10-
private readonly BlockingCollection<IntPtr> _asyncDecRefQueue = new BlockingCollection<IntPtr>();
118
private readonly ConcurrentQueue<IntPtr> _decRefQueue = new ConcurrentQueue<IntPtr>();
12-
private CancellationTokenSource _cts;
13-
private CancellationToken _ct;
14-
private Task _backgroundWorkerTask;
15-
private bool _multipleThreadsAllowed;
169

17-
public void ScheduleDecRef(IntPtr pyRef)
18-
{
19-
if (_multipleThreadsAllowed)
20-
{
21-
// ReSharper disable once MethodSupportsCancellation
22-
_asyncDecRefQueue.Add(pyRef);
23-
}
24-
else
25-
{
26-
_decRefQueue.Enqueue(pyRef);
27-
}
28-
}
29-
30-
public void AllowMultipleThreads()
10+
public void TryPerformScheduledDecrements()
3111
{
32-
DecReferences();
33-
_multipleThreadsAllowed = true;
34-
InitDecRefThread();
12+
//Trying to not affecting performance.
13+
DecReferences(1000);
3514
}
3615

37-
public void DisableMultipleThreads()
16+
public void ScheduleDecRef(IntPtr pyRef)
3817
{
39-
ShutdownDecRefThread();
40-
_multipleThreadsAllowed = false;
41-
}
42-
43-
public void TryPerformScheduledDecrements()
44-
{
45-
if (!_multipleThreadsAllowed)
46-
{
47-
DecReferences();
48-
}
18+
_decRefQueue.Enqueue(pyRef);
4919
}
5020

5121
public void FlushDecrementQueue()
5222
{
53-
if (_multipleThreadsAllowed)
23+
IntPtr gs = PythonEngine.AcquireLock();
24+
try
5425
{
5526
DecReferences();
5627
}
57-
else
28+
finally
5829
{
59-
ShutdownDecRefThread();
60-
InitDecRefThread();
30+
PythonEngine.ReleaseLock(gs);
6131
}
6232
}
6333

64-
private void ShutdownDecRefThread()
65-
{
66-
_cts?.Cancel();
67-
try
68-
{
69-
_backgroundWorkerTask.Wait();
70-
}
71-
catch
72-
{
73-
// Just stopping background thread.
74-
}
75-
_cts = null;
76-
_ct = default(CancellationToken);
77-
78-
_backgroundWorkerTask = null;
79-
}
80-
81-
private void InitDecRefThread()
82-
{
83-
_cts = new CancellationTokenSource();
84-
_ct = _cts.Token;
85-
_backgroundWorkerTask = Task.Factory.StartNew(WorkerThread, TaskCreationOptions.LongRunning);
86-
}
87-
88-
private void DecReferences()
34+
private void DecReferences(int? maxDecreases = null)
8935
{
9036
try
9137
{
38+
int decreasedCount = 0;
9239
IntPtr refToDecrease;
9340
while (_decRefQueue.TryDequeue(out refToDecrease))
9441
{
9542
Runtime.XDecref(refToDecrease);
96-
}
97-
}
98-
catch
99-
{
100-
// Do nothing.
101-
}
102-
}
103-
104-
private void WorkerThread()
105-
{
106-
try
107-
{
108-
while (true)
109-
{
110-
IntPtr refToDecrease;
111-
112-
refToDecrease = _asyncDecRefQueue.Take(_ct);
113-
114-
try
43+
decreasedCount++;
44+
if (maxDecreases != null && decreasedCount > maxDecreases)
11545
{
116-
IntPtr gs = PythonEngine.AcquireLock();
117-
try
118-
{
119-
do
120-
{
121-
Runtime.XDecref(refToDecrease);
122-
} while (_asyncDecRefQueue.TryTake(out refToDecrease));
123-
}
124-
finally
125-
{
126-
PythonEngine.ReleaseLock(gs);
127-
}
128-
}
129-
catch
130-
{
131-
// Nothing to do in this case.
46+
break;
13247
}
13348
}
13449
}
135-
catch (OperationCanceledException)
50+
catch
13651
{
137-
// This is normal exit pass.
52+
// Do nothing.
13853
}
13954
}
14055

14156
public void Dispose()
14257
{
143-
if (_multipleThreadsAllowed)
144-
{
145-
ShutdownDecRefThread();
146-
}
147-
else
148-
{
149-
DecReferences();
150-
}
58+
DecReferences();
15159
}
15260
}
153-
15461
}

src/runtime/pythonengine.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using System;
1+
using System;
22
using System.Collections.Generic;
33
using System.IO;
44
using System.Linq;
@@ -362,7 +362,6 @@ public static void ReleaseLock(IntPtr gs)
362362
/// </remarks>
363363
public static IntPtr BeginAllowThreads()
364364
{
365-
CurrentRefDecrementer?.AllowMultipleThreads();
366365
return Runtime.PyEval_SaveThread();
367366
}
368367

@@ -379,7 +378,6 @@ public static IntPtr BeginAllowThreads()
379378
/// </remarks>
380379
public static void EndAllowThreads(IntPtr ts)
381380
{
382-
CurrentRefDecrementer?.DisableMultipleThreads();
383381
Runtime.PyEval_RestoreThread(ts);
384382
}
385383

0 commit comments

Comments
 (0)