|
@@ -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
|
|
|
{
|
|
@@ -24,7 +25,6 @@ namespace System.Reactive.Linq.ObservableImpl
|
|
|
internal sealed class _ : IdentitySink<TSource>
|
|
|
{
|
|
|
private readonly Action _finallyAction;
|
|
|
-
|
|
|
private IDisposable _sourceDisposable;
|
|
|
|
|
|
public _(Action finallyAction, IObserver<TSource> observer)
|
|
@@ -35,19 +35,43 @@ namespace System.Reactive.Linq.ObservableImpl
|
|
|
|
|
|
public override void Run(IObservable<TSource> source)
|
|
|
{
|
|
|
- Disposable.SetSingle(ref _sourceDisposable, source.SubscribeSafe(this));
|
|
|
+ var d = source.SubscribeSafe(this);
|
|
|
+
|
|
|
+ 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
|
|
|
+ {
|
|
|
+ d.Dispose();
|
|
|
+ }
|
|
|
+ finally
|
|
|
+ {
|
|
|
+ _finallyAction();
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
protected override void Dispose(bool disposing)
|
|
|
{
|
|
|
+ base.Dispose(disposing);
|
|
|
+
|
|
|
if (disposing)
|
|
|
{
|
|
|
- if (Disposable.TryDispose(ref _sourceDisposable))
|
|
|
+ var d = Interlocked.Exchange(ref _sourceDisposable, BooleanDisposable.True);
|
|
|
+ if (d != BooleanDisposable.True && d != null)
|
|
|
{
|
|
|
- _finallyAction();
|
|
|
+ try
|
|
|
+ {
|
|
|
+ d.Dispose();
|
|
|
+ }
|
|
|
+ finally
|
|
|
+ {
|
|
|
+ _finallyAction();
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
- base.Dispose(disposing);
|
|
|
}
|
|
|
}
|
|
|
}
|