Skip to content

Commit

Permalink
Save two allocations in the finally operator
Browse files Browse the repository at this point in the history
  • Loading branch information
quinmars authored and Oren Novotny committed Aug 1, 2019
1 parent cfab9f9 commit 31e6aa8
Showing 1 changed file with 30 additions and 4 deletions.
34 changes: 30 additions & 4 deletions Rx.NET/Source/src/System.Reactive/Linq/Observable/Finally.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.

using System.Reactive.Disposables;
using System.Threading;

namespace System.Reactive.Linq.ObservableImpl
{
Expand All @@ -24,6 +25,7 @@ public Finally(IObservable<TSource> source, Action finallyAction)
internal sealed class _ : IdentitySink<TSource>
{
private readonly Action _finallyAction;
private IDisposable _sourceDisposable;

public _(Action finallyAction, IObserver<TSource> observer)
: base(observer)
Expand All @@ -33,19 +35,43 @@ public _(Action finallyAction, IObserver<TSource> observer)

public override void Run(IObservable<TSource> source)
{
var subscription = source.SubscribeSafe(this);
var d = source.SubscribeSafe(this);

SetUpstream(Disposable.Create(() =>
if (Interlocked.CompareExchange(ref _sourceDisposable, d, null) == BooleanDisposable.True)
{
// The Dispose(bool) methode was already called before the
// subscription could be assign, hence the subscription
// needs to be diposed here and the action needs to be invoked.
try
{
subscription.Dispose();
d.Dispose();
}
finally
{
_finallyAction();
}
}));
}
}

protected override void Dispose(bool disposing)
{
base.Dispose(disposing);

if (disposing)
{
var d = Interlocked.Exchange(ref _sourceDisposable, BooleanDisposable.True);
if (d != BooleanDisposable.True && d != null)
{
try
{
d.Dispose();
}
finally
{
_finallyAction();
}
}
}
}
}
}
Expand Down

0 comments on commit 31e6aa8

Please sign in to comment.