Skip to content

Commit 389881c

Browse files
authored
Use the helper methods for IDisposable-fields, avoid repeating code patterns. (#556)
1 parent 673dd5a commit 389881c

File tree

11 files changed

+38
-77
lines changed

11 files changed

+38
-77
lines changed

Rx.NET/Source/src/System.Reactive/Disposables/ContextDisposable.cs

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ namespace System.Reactive.Disposables
1212
/// </summary>
1313
public sealed class ContextDisposable : ICancelable
1414
{
15-
private volatile IDisposable _disposable;
15+
private IDisposable _disposable;
1616

1717
/// <summary>
1818
/// Initializes a new instance of the <see cref="ContextDisposable"/> class that uses the specified <see cref="SynchronizationContext"/> on which to dispose the specified disposable resource.
@@ -28,7 +28,7 @@ public ContextDisposable(SynchronizationContext context, IDisposable disposable)
2828
throw new ArgumentNullException(nameof(disposable));
2929

3030
Context = context;
31-
_disposable = disposable;
31+
Disposable.SetSingle(ref _disposable, disposable);
3232
}
3333

3434
/// <summary>
@@ -39,19 +39,14 @@ public ContextDisposable(SynchronizationContext context, IDisposable disposable)
3939
/// <summary>
4040
/// Gets a value that indicates whether the object is disposed.
4141
/// </summary>
42-
public bool IsDisposed => _disposable == BooleanDisposable.True;
42+
public bool IsDisposed => Disposable.GetIsDisposed(ref _disposable);
4343

4444
/// <summary>
4545
/// Disposes the underlying disposable on the provided <see cref="SynchronizationContext"/>.
4646
/// </summary>
4747
public void Dispose()
4848
{
49-
var disposable = Interlocked.Exchange(ref _disposable, BooleanDisposable.True);
50-
51-
if (disposable != BooleanDisposable.True)
52-
{
53-
Context.PostWithStartComplete(d => d.Dispose(), disposable);
54-
}
49+
Disposable.TryRelease(ref _disposable, this.Context, (disposable, context) => context.PostWithStartComplete(d => d.Dispose(), disposable));
5550
}
5651
}
5752
}

Rx.NET/Source/src/System.Reactive/Disposables/Disposable.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,5 +210,16 @@ internal static bool TryDispose(ref IDisposable fieldRef)
210210
old?.Dispose();
211211
return true;
212212
}
213+
214+
internal static bool TryRelease<TState>(ref IDisposable fieldRef, TState state, Action<IDisposable, TState> disposeAction)
215+
{
216+
var old = Interlocked.Exchange(ref fieldRef, BooleanDisposable.True);
217+
218+
if (old == BooleanDisposable.True)
219+
return false;
220+
221+
disposeAction(old, state);
222+
return true;
223+
}
213224
}
214225
}

Rx.NET/Source/src/System.Reactive/Disposables/ScheduledDisposable.cs

Lines changed: 5 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ namespace System.Reactive.Disposables
1212
/// </summary>
1313
public sealed class ScheduledDisposable : ICancelable
1414
{
15-
private volatile IDisposable _disposable;
15+
private IDisposable _disposable;
1616

1717
/// <summary>
1818
/// Initializes a new instance of the <see cref="ScheduledDisposable"/> class that uses an <see cref="IScheduler"/> on which to dispose the disposable.
@@ -28,7 +28,7 @@ public ScheduledDisposable(IScheduler scheduler, IDisposable disposable)
2828
throw new ArgumentNullException(nameof(disposable));
2929

3030
Scheduler = scheduler;
31-
_disposable = disposable;
31+
Disposables.Disposable.SetSingle(ref _disposable, disposable);
3232
}
3333

3434
/// <summary>
@@ -39,39 +39,16 @@ public ScheduledDisposable(IScheduler scheduler, IDisposable disposable)
3939
/// <summary>
4040
/// Gets the underlying disposable. After disposal, the result is undefined.
4141
/// </summary>
42-
public IDisposable Disposable
43-
{
44-
get
45-
{
46-
var current = _disposable;
47-
48-
if (current == BooleanDisposable.True)
49-
{
50-
return Disposables.Disposable.Empty; // Don't leak the sentinel value.
51-
}
52-
53-
return current;
54-
}
55-
}
42+
public IDisposable Disposable => Disposables.Disposable.GetValueOrDefault(ref _disposable);
5643

5744
/// <summary>
5845
/// Gets a value that indicates whether the object is disposed.
5946
/// </summary>
60-
public bool IsDisposed => _disposable == BooleanDisposable.True;
47+
public bool IsDisposed => Disposables.Disposable.GetIsDisposed(ref _disposable);
6148

6249
/// <summary>
6350
/// Disposes the wrapped disposable on the provided scheduler.
6451
/// </summary>
65-
public void Dispose() => Scheduler.Schedule(DisposeInner);
66-
67-
private void DisposeInner()
68-
{
69-
var disposable = Interlocked.Exchange(ref _disposable, BooleanDisposable.True);
70-
71-
if (disposable != BooleanDisposable.True)
72-
{
73-
disposable.Dispose();
74-
}
75-
}
52+
public void Dispose() => Scheduler.Schedule(scheduler => Disposables.Disposable.TryDispose(ref scheduler._disposable), this);
7653
}
7754
}

Rx.NET/Source/src/System.Reactive/Internal/AutoDetachObserver.cs

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ internal sealed class AutoDetachObserver<T> : ObserverBase<T>
1111
{
1212
private readonly IObserver<T> _observer;
1313

14-
private IDisposable disposable;
14+
private IDisposable _disposable;
1515

1616
public AutoDetachObserver(IObserver<T> observer)
1717
{
@@ -20,17 +20,7 @@ public AutoDetachObserver(IObserver<T> observer)
2020

2121
public IDisposable Disposable
2222
{
23-
set
24-
{
25-
if (Interlocked.CompareExchange(ref disposable, value, null) != null)
26-
{
27-
value?.Dispose();
28-
if (Volatile.Read(ref disposable) != BooleanDisposable.True)
29-
{
30-
throw new InvalidOperationException(Strings_Core.DISPOSABLE_ALREADY_ASSIGNED);
31-
}
32-
}
33-
}
23+
set => Disposables.Disposable.SetSingle(ref _disposable, value);
3424
}
3525

3626
protected override void OnNextCore(T value)
@@ -111,7 +101,7 @@ protected override void Dispose(bool disposing)
111101

112102
if (disposing)
113103
{
114-
Interlocked.Exchange(ref disposable, BooleanDisposable.True)?.Dispose();
104+
Disposables.Disposable.TryDispose(ref _disposable);
115105
}
116106
}
117107
}

Rx.NET/Source/src/System.Reactive/Internal/ScheduledObserver.cs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -401,8 +401,8 @@ public ObserveOnObserverNew(IScheduler scheduler, IObserver<T> downstream, IDisp
401401
public void Dispose()
402402
{
403403
Volatile.Write(ref disposed, true);
404-
Interlocked.Exchange(ref upstream, BooleanDisposable.True)?.Dispose();
405-
Interlocked.Exchange(ref task, BooleanDisposable.True)?.Dispose();
404+
Disposable.TryDispose(ref upstream);
405+
Disposable.TryDispose(ref task);
406406
Clear();
407407
}
408408

@@ -443,14 +443,10 @@ void Schedule()
443443
{
444444
if (Interlocked.Increment(ref wip) == 1)
445445
{
446-
var oldTask = Volatile.Read(ref task);
447-
448446
var newTask = new SingleAssignmentDisposable();
449447

450-
if (oldTask != BooleanDisposable.True
451-
&& Interlocked.CompareExchange(ref task, newTask, oldTask) == oldTask)
448+
if (Disposable.TrySetMultiple(ref task, newTask))
452449
{
453-
454450
var longRunning = this.longRunning;
455451
if (longRunning != null)
456452
{

Rx.NET/Source/src/System.Reactive/Internal/TailRecursiveSink.cs

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -68,10 +68,8 @@ void Drain()
6868
var enumerator = stack.Pop();
6969
enumerator.Dispose();
7070
}
71-
if (Volatile.Read(ref currentSubscription) != BooleanDisposable.True)
72-
{
73-
Interlocked.Exchange(ref currentSubscription, BooleanDisposable.True)?.Dispose();
74-
}
71+
72+
Disposable.TryDispose(ref currentSubscription);
7573
}
7674
else
7775
{
@@ -131,7 +129,8 @@ void Drain()
131129
else
132130
{
133131
var sad = new SingleAssignmentDisposable();
134-
if (Interlocked.CompareExchange(ref currentSubscription, sad, null) == null)
132+
133+
if (Disposable.TrySetSingle(ref currentSubscription, sad) == TrySetSingleResult.Success)
135134
{
136135
sad.Disposable = next.SubscribeSafe(this);
137136
}
@@ -172,15 +171,8 @@ void DisposeAll()
172171

173172
protected void Recurse()
174173
{
175-
var d = Volatile.Read(ref currentSubscription);
176-
if (d != BooleanDisposable.True)
177-
{
178-
d?.Dispose();
179-
if (Interlocked.CompareExchange(ref currentSubscription, null, d) == d)
180-
{
181-
Drain();
182-
}
183-
}
174+
if (Disposable.TrySetSerial(ref currentSubscription, null))
175+
Drain();
184176
}
185177

186178
protected abstract IEnumerable<IObservable<TSource>> Extract(IObservable<TSource> source);

Rx.NET/Source/src/System.Reactive/Linq/Observable/Amb.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ internal void OnSubscribe(IDisposable d)
103103

104104
public void Dispose()
105105
{
106-
Interlocked.Exchange(ref upstream, BooleanDisposable.True)?.Dispose();
106+
Disposable.TryDispose(ref upstream);
107107
}
108108

109109
public void OnCompleted()

Rx.NET/Source/src/System.Reactive/Linq/Observable/AmbMany.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ public InnerObserver(AmbCoordinator<T> parent, int index)
153153

154154
public void Dispose()
155155
{
156-
Interlocked.Exchange(ref upstream, BooleanDisposable.True)?.Dispose();
156+
Disposable.TryDispose(ref upstream);
157157
}
158158

159159
public void OnCompleted()

Rx.NET/Source/src/System.Reactive/Linq/Observable/ConcatMany.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,12 +66,12 @@ public void Dispose()
6666

6767
void DisposeMain()
6868
{
69-
Interlocked.Exchange(ref upstream, BooleanDisposable.True)?.Dispose();
69+
Disposable.TryDispose(ref upstream);
7070
}
7171

7272
bool IsDisposed()
7373
{
74-
return Volatile.Read(ref upstream) == BooleanDisposable.True;
74+
return Disposable.GetIsDisposed(ref upstream);
7575
}
7676

7777
public void OnCompleted()

Rx.NET/Source/src/System.Reactive/Linq/Observable/RetryWhen.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ internal void OnSubscribe(IDisposable d)
200200

201201
public void Dispose()
202202
{
203-
Interlocked.Exchange(ref upstream, BooleanDisposable.True)?.Dispose();
203+
Disposable.TryDispose(ref upstream);
204204
}
205205

206206
public void OnCompleted()

0 commit comments

Comments
 (0)