Skip to content

Commit 091f231

Browse files
author
Oren (electricessence)
committed
Checkpoint.
1 parent fabf9f0 commit 091f231

File tree

3 files changed

+47
-5
lines changed

3 files changed

+47
-5
lines changed

DisposableBase.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ private void Dispose(bool calledExplicitly)
3434
if (!StartDispose())
3535
return;
3636

37-
GC.SuppressFinalize(this);
37+
if(calledExplicitly)
38+
GC.SuppressFinalize(this);
3839

3940
try
4041
{

DisposableStateBase.cs

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
* @author electricessence / https://github.com/electricessence/
33
* Licensing: MIThttps://github.com/electricessence/Open.Disposable/blob/master/LISCENSE.md
44
*/
5-
5+
66
using System;
77
using System.Threading;
88

@@ -16,11 +16,48 @@ public abstract class DisposableStateBase : IDisposalState
1616
protected const int DISPOSED = 2;
1717

1818
// Since all write operations are done through Interlocked, no need for volatile.
19-
private int _disposeState;
19+
private int _disposeCalled = ALIVE;
20+
private int _disposeState = ALIVE;
2021
public DisposeState DisposeState => (DisposeState)_disposeState;
22+
23+
/* This is important because some classes might react to disposal
24+
* and still need access to the live class before it's disposed. */
25+
#region Before Disposal
26+
protected virtual void OnBeforeDispose() { }
27+
28+
/// <summary>
29+
/// This event is triggered by the DisposeHelper immediately before
30+
/// </summary>
31+
public event EventHandler BeforeDispose;
32+
internal void FireBeforeDispose()
33+
{
34+
// Events should only fire if there are listeners...
35+
if (BeforeDispose != null)
36+
{
37+
BeforeDispose(this, EventArgs.Empty);
38+
BeforeDispose = null;
39+
}
40+
}
41+
#endregion
42+
43+
2144
protected bool StartDispose()
22-
=> _disposeState == ALIVE
23-
&& Interlocked.CompareExchange(ref _disposeState, DISPOSING, ALIVE) == ALIVE;
45+
{
46+
if(_disposeCalled == ALIVE
47+
&& Interlocked.CompareExchange(ref _disposeCalled, DISPOSING, ALIVE) == ALIVE)
48+
{
49+
try {
50+
51+
}
52+
finally {
53+
if(_disposeState == ALIVE)
54+
Interlocked.CompareExchange(ref _disposeState, DISPOSING, ALIVE);
55+
}
56+
return true;
57+
}
58+
59+
return false;
60+
}
2461

2562
protected void Disposed()
2663
=> Interlocked.Exchange(ref _disposeState, DISPOSED); // State.Disposed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,7 @@ It can be all too easy to allocate more memory by constructing more classes or s
1717
#### Plan for the worst, but code for the best
1818

1919
Thread safety is important and in many cases should be assured. But when the 99% case is the local use of a class, over-engineering can simply create unnecessary overhead and contention.
20+
21+
#### Let the GC do its job
22+
23+
Aggressively attempting to help out the garbage collector can be serious anti-pattern as you are simply slowing down your own application in order to avoid GC operations which might actually be helping your performance in total by deferring cleanup.

0 commit comments

Comments
 (0)