Skip to content

Commit f697757

Browse files
committed
further improvements - System.Reactive.Extendibility prototyping
1 parent d78e725 commit f697757

29 files changed

+388
-17
lines changed

Assets/Src/Scripts/Data/Linq/DataObservable.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ public static IObservable<Unit> AsUnitObservable<T>(this IObservable<T> source)
1616
}
1717

1818
/// <summary>
19-
/// Same as LastOrDefault().AsUnitObservable().
19+
/// Like .AsUnitObservable() but only emits once when the source observable was completed and only if it published at least one value before doing so.
2020
/// </summary>
2121
public static IObservable<Unit> AsSingleUnitObservable<T>(this IObservable<T> source) {
2222
if (source == null)

Assets/Src/Scripts/Data/Linq/Observables/AsSingleUnit.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1-
namespace System.Reactive.Data.Linq.Observables {
2-
internal sealed class AsSingleUnit<T> : Producer<Unit, AsSingleUnit<T>._> {
1+
using System.Reactive.Extendibility.Observables;
2+
3+
namespace System.Reactive.Data.Linq.Observables {
4+
internal sealed class AsSingleUnit<T> : ObservableProducer<Unit, AsSingleUnit<T>._> {
35
private readonly IObservable<T> _source;
46

57
public AsSingleUnit(IObservable<T> source) => _source = source;

Assets/Src/Scripts/Data/Linq/Observables/AsUnit.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
using System;
22
using System.Reactive;
3+
using System.Reactive.Extendibility.Observables;
34

45
namespace System.Reactive.Data.Linq.Observables {
5-
internal sealed class AsUnit<T> : Producer<Unit, AsUnit<T>._> {
6+
internal sealed class AsUnit<T> : ObservableProducer<Unit, AsUnit<T>._> {
67
private readonly IObservable<T> _source;
78

89
public AsUnit(IObservable<T> source) => _source = source;

Assets/Src/Scripts/Data/Linq/Observables/Pairwise.cs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
1-
using System;
2-
using System.Collections;
3-
using System.Collections.Generic;
4-
using System.Reactive;
1+
using System.Reactive.Extendibility.Observables;
52

63
namespace System.Reactive.Data.Linq.Observables {
7-
internal sealed class Pairwise<T> : Producer<Pair<T>, Pairwise<T>._> {
4+
internal sealed class Pairwise<T> : ObservableProducer<Pair<T>, Pairwise<T>._> {
85
private readonly IObservable<T> _source;
96

107
public Pairwise(IObservable<T> source) => _source = source;

Assets/Src/Scripts/Data/System.Reactive.Data.asmdef

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
{
22
"name": "System.Reactive.Data",
33
"rootNamespace": "",
4-
"references": [],
4+
"references": [
5+
"GUID:1f337dc262e02754a96f0617d03119e8"
6+
],
57
"includePlatforms": [],
68
"excludePlatforms": [],
79
"allowUnsafeCode": false,

Assets/Src/Scripts/Extendibility.meta

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Assets/Src/Scripts/Extendibility/Disposables.meta

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
using System.Reactive.Disposables;
2+
3+
namespace System.Reactive.Extendibility.Disposables {
4+
/// <summary>
5+
/// Represents a disposable resource that can be checked for disposal status.
6+
/// </summary>
7+
internal sealed class BooleanDisposable : ICancelable {
8+
// Keep internal! This is used as sentinel in other IDisposable implementations to detect disposal and
9+
// should never be exposed to user code in order to prevent users from swapping in the sentinel. Have
10+
// a look at the code in e.g. SingleAssignmentDisposable for usage patterns.
11+
internal static readonly BooleanDisposable True = new BooleanDisposable(true);
12+
13+
private volatile bool _isDisposed;
14+
15+
/// <summary>
16+
/// Initializes a new instance of the <see cref="BooleanDisposable"/> class.
17+
/// </summary>
18+
public BooleanDisposable() {
19+
}
20+
21+
private BooleanDisposable(bool isDisposed) {
22+
_isDisposed = isDisposed;
23+
}
24+
25+
/// <summary>
26+
/// Gets a value that indicates whether the object is disposed.
27+
/// </summary>
28+
public bool IsDisposed => _isDisposed;
29+
30+
/// <summary>
31+
/// Sets the status to disposed, which can be observer through the <see cref="IsDisposed"/> property.
32+
/// </summary>
33+
public void Dispose() {
34+
_isDisposed = true;
35+
}
36+
}
37+
}

Assets/Src/Scripts/Extendibility/Disposables/BooleanDisposable.cs.meta

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
using System.Diagnostics.CodeAnalysis;
2+
using System.Threading;
3+
4+
namespace System.Reactive.Extendibility.Disposables {
5+
internal static partial class Disposable {
6+
/// <summary>
7+
/// Gets the value stored in <paramref name="fieldRef" /> or a no-op-Disposable if
8+
/// <paramref name="fieldRef" /> was already disposed.
9+
/// </summary>
10+
[return: NotNullIfNotNull("fieldRef")]
11+
internal static IDisposable? GetValueOrDefault([NotNullIfNotNull("fieldRef")] /*in*/ ref IDisposable? fieldRef) {
12+
var current = Volatile.Read(ref fieldRef);
13+
14+
return current == BooleanDisposable.True
15+
? System.Reactive.Disposables.Disposable.Empty
16+
: current;
17+
}
18+
19+
/// <summary>
20+
/// Tries to assign <paramref name="value" /> to <paramref name="fieldRef" />.
21+
/// </summary>
22+
/// <returns>A <see cref="TrySetSingleResult"/> value indicating the outcome of the operation.</returns>
23+
internal static TrySetSingleResult TrySetSingle([NotNullIfNotNull("value")] ref IDisposable? fieldRef, IDisposable? value) {
24+
var old = Interlocked.CompareExchange(ref fieldRef, value, null);
25+
if (old == null) {
26+
return TrySetSingleResult.Success;
27+
}
28+
29+
if (old != BooleanDisposable.True) {
30+
return TrySetSingleResult.AlreadyAssigned;
31+
}
32+
33+
value?.Dispose();
34+
return TrySetSingleResult.Disposed;
35+
}
36+
37+
/// <summary>
38+
/// Disposes <paramref name="fieldRef" />.
39+
/// </summary>
40+
internal static void Dispose([NotNullIfNotNull("fieldRef")] ref IDisposable? fieldRef) {
41+
var old = Interlocked.Exchange(ref fieldRef, BooleanDisposable.True);
42+
43+
if (old != BooleanDisposable.True) {
44+
old?.Dispose();
45+
}
46+
}
47+
}
48+
}

0 commit comments

Comments
 (0)