diff --git a/Rx.NET/Source/src/System.Reactive/Concurrency/Synchronization.ObserveOn.cs b/Rx.NET/Source/src/System.Reactive/Concurrency/Synchronization.ObserveOn.cs index f7676ba939..3d91fb4fa3 100644 --- a/Rx.NET/Source/src/System.Reactive/Concurrency/Synchronization.ObserveOn.cs +++ b/Rx.NET/Source/src/System.Reactive/Concurrency/Synchronization.ObserveOn.cs @@ -7,34 +7,21 @@ namespace System.Reactive.Concurrency { - internal sealed class ObserveOn : Producer + internal static class ObserveOn { - private readonly IObservable _source; - private readonly IScheduler _scheduler; - private readonly SynchronizationContext _context; - - public ObserveOn(IObservable source, IScheduler scheduler) - { - _source = source; - _scheduler = scheduler; - } - - public ObserveOn(IObservable source, SynchronizationContext context) + internal sealed class Scheduler : Producer { - _source = source; - _context = context; - } + private readonly IObservable _source; + private readonly IScheduler _scheduler; - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "2", Justification = "Visibility restricted to friend assemblies. Those should be correct by inspection.")] - protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) - { - if (_context != null) + public Scheduler(IObservable source, IScheduler scheduler) { - var sink = new ObserveOnSink(this, observer, cancel); - setSink(sink); - return sink.Run(); + _source = source; + _scheduler = scheduler; } - else + + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "2", Justification = "Visibility restricted to friend assemblies. Those should be correct by inspection.")] + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { var sink = new ObserveOnObserver(_scheduler, observer, cancel); setSink(sink); @@ -42,66 +29,83 @@ protected override IDisposable Run(IObserver observer, IDisposable canc } } - private sealed class ObserveOnSink : Sink, IObserver + internal sealed class Context : Producer { - private readonly ObserveOn _parent; + private readonly IObservable _source; + private readonly SynchronizationContext _context; - public ObserveOnSink(ObserveOn parent, IObserver observer, IDisposable cancel) - : base(observer, cancel) + public Context(IObservable source, SynchronizationContext context) { - _parent = parent; + _source = source; + _context = context; } - public IDisposable Run() + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "2", Justification = "Visibility restricted to friend assemblies. Those should be correct by inspection.")] + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - // - // The interactions with OperationStarted/OperationCompleted below allow - // for test frameworks to wait until a whole sequence is observed, running - // asserts on a per-message level. Also, for ASP.NET pages, the use of the - // built-in synchronization context would allow processing to finished in - // its entirety before moving on with the page lifecycle. - // - _parent._context.OperationStarted(); - - var d = _parent._source.SubscribeSafe(this); - var c = Disposable.Create(() => - { - _parent._context.OperationCompleted(); - }); - - return StableCompositeDisposable.Create(d, c); + var sink = new _(_context, observer, cancel); + setSink(sink); + return sink.Run(_source); } - public void OnNext(TSource value) + private sealed class _ : Sink, IObserver { - _parent._context.Post(OnNextPosted, value); - } + private readonly SynchronizationContext _context; - public void OnError(Exception error) - { - _parent._context.Post(OnErrorPosted, error); - } + public _(SynchronizationContext context, IObserver observer, IDisposable cancel) + : base(observer, cancel) + { + _context = context; + } - public void OnCompleted() - { - _parent._context.Post(OnCompletedPosted, state: null); - } + public IDisposable Run(IObservable source) + { + // + // The interactions with OperationStarted/OperationCompleted below allow + // for test frameworks to wait until a whole sequence is observed, running + // asserts on a per-message level. Also, for ASP.NET pages, the use of the + // built-in synchronization context would allow processing to finished in + // its entirety before moving on with the page lifecycle. + // + _context.OperationStarted(); + + var d = source.SubscribeSafe(this); + var c = Disposable.Create(_context.OperationCompleted); + + return StableCompositeDisposable.Create(d, c); + } + + public void OnNext(TSource value) + { + _context.Post(OnNextPosted, value); + } - private void OnNextPosted(object value) - { - _observer.OnNext((TSource)value); - } + public void OnError(Exception error) + { + _context.Post(OnErrorPosted, error); + } - private void OnErrorPosted(object error) - { - _observer.OnError((Exception)error); - Dispose(); - } + public void OnCompleted() + { + _context.Post(OnCompletedPosted, state: null); + } - private void OnCompletedPosted(object ignored) - { - _observer.OnCompleted(); - Dispose(); + private void OnNextPosted(object value) + { + _observer.OnNext((TSource)value); + } + + private void OnErrorPosted(object error) + { + _observer.OnError((Exception)error); + Dispose(); + } + + private void OnCompletedPosted(object ignored) + { + _observer.OnCompleted(); + Dispose(); + } } } } diff --git a/Rx.NET/Source/src/System.Reactive/Concurrency/Synchronization.cs b/Rx.NET/Source/src/System.Reactive/Concurrency/Synchronization.cs index c4e1cff8ae..b868238d2f 100644 --- a/Rx.NET/Source/src/System.Reactive/Concurrency/Synchronization.cs +++ b/Rx.NET/Source/src/System.Reactive/Concurrency/Synchronization.cs @@ -102,7 +102,7 @@ public static IObservable ObserveOn(IObservable sourc if (scheduler == null) throw new ArgumentNullException(nameof(scheduler)); - return new ObserveOn(source, scheduler); + return new ObserveOn.Scheduler(source, scheduler); } /// @@ -120,7 +120,7 @@ public static IObservable ObserveOn(IObservable sourc if (context == null) throw new ArgumentNullException(nameof(context)); - return new ObserveOn(source, context); + return new ObserveOn.Context(source, context); } #endregion diff --git a/Rx.NET/Source/src/System.Reactive/Internal/Helpers.cs b/Rx.NET/Source/src/System.Reactive/Internal/Helpers.cs index 99ba1ed5b6..06bd0d41e7 100644 --- a/Rx.NET/Source/src/System.Reactive/Internal/Helpers.cs +++ b/Rx.NET/Source/src/System.Reactive/Internal/Helpers.cs @@ -39,5 +39,34 @@ public static IObservable Unpack(IObservable source) return source; } + + public static bool All(this bool[] values) + { + foreach (var value in values) + { + if (!value) + { + return false; + } + } + + return true; + } + + public static bool AllExcept(this bool[] values, int index) + { + for (var i = 0; i < values.Length; i++) + { + if (i != index) + { + if (!values[i]) + { + return false; + } + } + } + + return true; + } } } diff --git a/Rx.NET/Source/src/System.Reactive/Linq/GroupedObservable.cs b/Rx.NET/Source/src/System.Reactive/Linq/GroupedObservable.cs index 8bcdf46625..146ae370c2 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/GroupedObservable.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/GroupedObservable.cs @@ -7,29 +7,25 @@ namespace System.Reactive.Linq { - class GroupedObservable : ObservableBase, IGroupedObservable + internal sealed class GroupedObservable : ObservableBase, IGroupedObservable { - private readonly TKey _key; private readonly IObservable _subject; private readonly RefCountDisposable _refCount; public GroupedObservable(TKey key, ISubject subject, RefCountDisposable refCount) { - _key = key; + Key = key; _subject = subject; _refCount = refCount; } public GroupedObservable(TKey key, ISubject subject) { - _key = key; + Key = key; _subject = subject; } - public TKey Key - { - get { return _key; } - } + public TKey Key { get; } protected override IDisposable SubscribeCore(IObserver observer) { diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/AddRef.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/AddRef.cs index edaf838dbe..8b1e3ff2d1 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/AddRef.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/AddRef.cs @@ -26,7 +26,7 @@ protected override IDisposable Run(IObserver observer, IDisposable canc return _source.SubscribeSafe(sink); } - class _ : Sink, IObserver + private sealed class _ : Sink, IObserver { public _(IObserver observer, IDisposable cancel) : base(observer, cancel) diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Aggregate.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Aggregate.cs index c0ade29e64..14f98dd671 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Aggregate.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Aggregate.cs @@ -4,50 +4,56 @@ namespace System.Reactive.Linq.ObservableImpl { - internal sealed class Aggregate : Producer + internal sealed class Aggregate : Producer { private readonly IObservable _source; - private readonly TAccumulate _seed; - private readonly Func _accumulator; - private readonly Func _resultSelector; + private readonly Func _accumulator; - public Aggregate(IObservable source, TAccumulate seed, Func accumulator, Func resultSelector) + public Aggregate(IObservable source, Func accumulator) { _source = source; - _seed = seed; _accumulator = accumulator; - _resultSelector = resultSelector; } - protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - var sink = new _(this, observer, cancel); + var sink = new _(_accumulator, observer, cancel); setSink(sink); return _source.SubscribeSafe(sink); } - class _ : Sink, IObserver + private sealed class _ : Sink, IObserver { - private readonly Aggregate _parent; - private TAccumulate _accumulation; + private readonly Func _accumulator; + private TSource _accumulation; + private bool _hasAccumulation; - public _(Aggregate parent, IObserver observer, IDisposable cancel) + public _(Func accumulator, IObserver observer, IDisposable cancel) : base(observer, cancel) { - _parent = parent; - _accumulation = _parent._seed; + _accumulator = accumulator; + _accumulation = default(TSource); + _hasAccumulation = false; } public void OnNext(TSource value) { - try + if (!_hasAccumulation) { - _accumulation = _parent._accumulator(_accumulation, value); + _accumulation = value; + _hasAccumulation = true; } - catch (Exception exception) + else { - base._observer.OnError(exception); - base.Dispose(); + try + { + _accumulation = _accumulator(_accumulation, value); + } + catch (Exception exception) + { + base._observer.OnError(exception); + base.Dispose(); + } } } @@ -59,75 +65,129 @@ public void OnError(Exception error) public void OnCompleted() { - var result = default(TResult); + if (!_hasAccumulation) + { + base._observer.OnError(new InvalidOperationException(Strings_Linq.NO_ELEMENTS)); + base.Dispose(); + } + else + { + base._observer.OnNext(_accumulation); + base._observer.OnCompleted(); + base.Dispose(); + } + } + } + } + + internal sealed class Aggregate : Producer + { + private readonly IObservable _source; + private readonly TAccumulate _seed; + private readonly Func _accumulator; + + public Aggregate(IObservable source, TAccumulate seed, Func accumulator) + { + _source = source; + _seed = seed; + _accumulator = accumulator; + } + + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) + { + var sink = new _(_seed, _accumulator, observer, cancel); + setSink(sink); + return _source.SubscribeSafe(sink); + } + + private sealed class _ : Sink, IObserver + { + private readonly Func _accumulator; + private TAccumulate _accumulation; + + public _(TAccumulate seed, Func accumulator, IObserver observer, IDisposable cancel) + : base(observer, cancel) + { + _accumulator = accumulator; + _accumulation = seed; + } + + public void OnNext(TSource value) + { try { - result = _parent._resultSelector(_accumulation); + _accumulation = _accumulator(_accumulation, value); } catch (Exception exception) { base._observer.OnError(exception); base.Dispose(); - return; } + } - base._observer.OnNext(result); + public void OnError(Exception error) + { + base._observer.OnError(error); + base.Dispose(); + } + + public void OnCompleted() + { + base._observer.OnNext(_accumulation); base._observer.OnCompleted(); base.Dispose(); } } } - internal sealed class Aggregate : Producer + internal sealed class Aggregate : Producer { private readonly IObservable _source; - private readonly Func _accumulator; + private readonly TAccumulate _seed; + private readonly Func _accumulator; + private readonly Func _resultSelector; - public Aggregate(IObservable source, Func accumulator) + public Aggregate(IObservable source, TAccumulate seed, Func accumulator, Func resultSelector) { _source = source; + _seed = seed; _accumulator = accumulator; + _resultSelector = resultSelector; } - protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { var sink = new _(this, observer, cancel); setSink(sink); return _source.SubscribeSafe(sink); } - class _ : Sink, IObserver + private sealed class _ : Sink, IObserver { - private readonly Aggregate _parent; - private TSource _accumulation; - private bool _hasAccumulation; + private readonly Func _accumulator; + private readonly Func _resultSelector; + + private TAccumulate _accumulation; - public _(Aggregate parent, IObserver observer, IDisposable cancel) + public _(Aggregate parent, IObserver observer, IDisposable cancel) : base(observer, cancel) { - _parent = parent; - _accumulation = default(TSource); - _hasAccumulation = false; + _accumulator = parent._accumulator; + _resultSelector = parent._resultSelector; + + _accumulation = parent._seed; } public void OnNext(TSource value) { - if (!_hasAccumulation) + try { - _accumulation = value; - _hasAccumulation = true; + _accumulation = _accumulator(_accumulation, value); } - else + catch (Exception exception) { - try - { - _accumulation = _parent._accumulator(_accumulation, value); - } - catch (Exception exception) - { - base._observer.OnError(exception); - base.Dispose(); - } + base._observer.OnError(exception); + base.Dispose(); } } @@ -139,17 +199,21 @@ public void OnError(Exception error) public void OnCompleted() { - if (!_hasAccumulation) + var result = default(TResult); + try { - base._observer.OnError(new InvalidOperationException(Strings_Linq.NO_ELEMENTS)); - base.Dispose(); + result = _resultSelector(_accumulation); } - else + catch (Exception exception) { - base._observer.OnNext(_accumulation); - base._observer.OnCompleted(); + base._observer.OnError(exception); base.Dispose(); + return; } + + base._observer.OnNext(result); + base._observer.OnCompleted(); + base.Dispose(); } } } diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/All.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/All.cs index 2b18d05533..b48028cfbb 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/All.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/All.cs @@ -17,19 +17,19 @@ public All(IObservable source, Func predicate) protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - var sink = new _(this, observer, cancel); + var sink = new _(_predicate, observer, cancel); setSink(sink); return _source.SubscribeSafe(sink); } - class _ : Sink, IObserver + private sealed class _ : Sink, IObserver { - private readonly All _parent; + private readonly Func _predicate; - public _(All parent, IObserver observer, IDisposable cancel) + public _(Func predicate, IObserver observer, IDisposable cancel) : base(observer, cancel) { - _parent = parent; + _predicate = predicate; } public void OnNext(TSource value) @@ -37,7 +37,7 @@ public void OnNext(TSource value) var res = false; try { - res = _parent._predicate(value); + res = _predicate(value); } catch (Exception ex) { diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Amb.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Amb.cs index 6eddfc88cb..6c5d450999 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Amb.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Amb.cs @@ -19,24 +19,21 @@ public Amb(IObservable left, IObservable right) protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - var sink = new _(this, observer, cancel); + var sink = new _( observer, cancel); setSink(sink); - return sink.Run(); + return sink.Run(this); } - class _ : Sink + private sealed class _ : Sink { - private readonly Amb _parent; - - public _(Amb parent, IObserver observer, IDisposable cancel) + public _(IObserver observer, IDisposable cancel) : base(observer, cancel) { - _parent = parent; } private AmbState _choice; - public IDisposable Run() + public IDisposable Run(Amb parent) { var ls = new SingleAssignmentDisposable(); var rs = new SingleAssignmentDisposable(); @@ -54,13 +51,13 @@ public IDisposable Run() _choice = AmbState.Neither; - ls.Disposable = _parent._left.SubscribeSafe(lo); - rs.Disposable = _parent._right.SubscribeSafe(ro); + ls.Disposable = parent._left.SubscribeSafe(lo); + rs.Disposable = parent._right.SubscribeSafe(ro); return d; } - class DecisionObserver : IObserver + private sealed class DecisionObserver : IObserver { private readonly _ _parent; private readonly AmbState _me; @@ -92,7 +89,9 @@ public void OnNext(TSource value) } if (_parent._choice == _me) + { _parent._observer.OnNext(value); + } } } @@ -137,7 +136,7 @@ public void OnCompleted() } } - class AmbObserver : IObserver + private sealed class AmbObserver : IObserver { public IObserver _target; @@ -161,11 +160,11 @@ public void OnCompleted() } } - enum AmbState + private enum AmbState { Left, Right, - Neither + Neither, } } } diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Any.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Any.cs index adf3c9fc6e..af02bd4d8c 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Any.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Any.cs @@ -4,110 +4,116 @@ namespace System.Reactive.Linq.ObservableImpl { - internal sealed class Any : Producer + internal static class Any { - private readonly IObservable _source; - private readonly Func _predicate; - - public Any(IObservable source) + internal sealed class Count : Producer { - _source = source; - } + private readonly IObservable _source; - public Any(IObservable source, Func predicate) - { - _source = source; - _predicate = predicate; - } - - protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) - { - if (_predicate != null) + public Count(IObservable source) { - var sink = new AnyImpl(this, observer, cancel); - setSink(sink); - return _source.SubscribeSafe(sink); + _source = source; } - else + + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { var sink = new _(observer, cancel); setSink(sink); return _source.SubscribeSafe(sink); } - } - class _ : Sink, IObserver - { - public _(IObserver observer, IDisposable cancel) - : base(observer, cancel) + private sealed class _ : Sink, IObserver { - } + public _(IObserver observer, IDisposable cancel) + : base(observer, cancel) + { + } - public void OnNext(TSource value) - { - base._observer.OnNext(true); - base._observer.OnCompleted(); - base.Dispose(); - } + public void OnNext(TSource value) + { + base._observer.OnNext(true); + base._observer.OnCompleted(); + base.Dispose(); + } - public void OnError(Exception error) - { - base._observer.OnError(error); - base.Dispose(); - } + public void OnError(Exception error) + { + base._observer.OnError(error); + base.Dispose(); + } - public void OnCompleted() - { - base._observer.OnNext(false); - base._observer.OnCompleted(); - base.Dispose(); + public void OnCompleted() + { + base._observer.OnNext(false); + base._observer.OnCompleted(); + base.Dispose(); + } } } - class AnyImpl : Sink, IObserver + internal sealed class Predicate : Producer { - private readonly Any _parent; + private readonly IObservable _source; + private readonly Func _predicate; - public AnyImpl(Any parent, IObserver observer, IDisposable cancel) - : base(observer, cancel) + public Predicate(IObservable source, Func predicate) { - _parent = parent; + _source = source; + _predicate = predicate; } - public void OnNext(TSource value) + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - var res = false; - try + var sink = new _(_predicate, observer, cancel); + setSink(sink); + return _source.SubscribeSafe(sink); + } + + private sealed class _ : Sink, IObserver + { + private readonly Func _predicate; + + public _(Func predicate, IObserver observer, IDisposable cancel) + : base(observer, cancel) { - res = _parent._predicate(value); + _predicate = predicate; } - catch (Exception ex) + + public void OnNext(TSource value) + { + var res = false; + try + { + res = _predicate(value); + } + catch (Exception ex) + { + base._observer.OnError(ex); + base.Dispose(); + return; + } + + if (res) + { + base._observer.OnNext(true); + base._observer.OnCompleted(); + base.Dispose(); + } + } + + public void OnError(Exception error) { - base._observer.OnError(ex); + base._observer.OnError(error); base.Dispose(); - return; } - if (res) + public void OnCompleted() { - base._observer.OnNext(true); + base._observer.OnNext(false); base._observer.OnCompleted(); base.Dispose(); } } - - public void OnError(Exception error) - { - base._observer.OnError(error); - base.Dispose(); - } - - public void OnCompleted() - { - base._observer.OnNext(false); - base._observer.OnCompleted(); - base.Dispose(); - } } } } diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/AsObservable.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/AsObservable.cs index 537d76d964..891100cdbf 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/AsObservable.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/AsObservable.cs @@ -13,10 +13,7 @@ public AsObservable(IObservable source) _source = source; } - public IObservable Eval() - { - return _source; - } + public IObservable Eval() => _source; protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { @@ -25,7 +22,7 @@ protected override IDisposable Run(IObserver observer, IDisposable canc return _source.SubscribeSafe(sink); } - class _ : Sink, IObserver + private sealed class _ : Sink, IObserver { public _(IObserver observer, IDisposable cancel) : base(observer, cancel) diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Average.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Average.cs index fbab56c26d..c608eb3086 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Average.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Average.cs @@ -20,7 +20,7 @@ protected override IDisposable Run(IObserver observer, IDisposable cance return _source.SubscribeSafe(sink); } - class _ : Sink, IObserver + private sealed class _ : Sink, IObserver { private double _sum; private long _count; @@ -88,7 +88,7 @@ protected override IDisposable Run(IObserver observer, IDisposable cancel return _source.SubscribeSafe(sink); } - class _ : Sink, IObserver + private sealed class _ : Sink, IObserver { private double _sum; // NOTE: Uses a different accumulator type (double), conform LINQ to Objects. private long _count; @@ -156,7 +156,7 @@ protected override IDisposable Run(IObserver observer, IDisposable canc return _source.SubscribeSafe(sink); } - class _ : Sink, IObserver + private sealed class _ : Sink, IObserver { private decimal _sum; private long _count; @@ -224,7 +224,7 @@ protected override IDisposable Run(IObserver observer, IDisposable cance return _source.SubscribeSafe(sink); } - class _ : Sink, IObserver + private sealed class _ : Sink, IObserver { private long _sum; private long _count; @@ -292,7 +292,7 @@ protected override IDisposable Run(IObserver observer, IDisposable cance return _source.SubscribeSafe(sink); } - class _ : Sink, IObserver + private sealed class _ : Sink, IObserver { private long _sum; private long _count; @@ -360,7 +360,7 @@ protected override IDisposable Run(IObserver observer, IDisposable canc return _source.SubscribeSafe(sink); } - class _ : Sink, IObserver + private sealed class _ : Sink, IObserver { private double _sum; private long _count; @@ -431,7 +431,7 @@ protected override IDisposable Run(IObserver observer, IDisposable cance return _source.SubscribeSafe(sink); } - class _ : Sink, IObserver + private sealed class _ : Sink, IObserver { private double _sum; // NOTE: Uses a different accumulator type (double), conform LINQ to Objects. private long _count; @@ -502,7 +502,7 @@ protected override IDisposable Run(IObserver observer, IDisposable can return _source.SubscribeSafe(sink); } - class _ : Sink, IObserver + private sealed class _ : Sink, IObserver { private decimal _sum; private long _count; @@ -573,7 +573,7 @@ protected override IDisposable Run(IObserver observer, IDisposable canc return _source.SubscribeSafe(sink); } - class _ : Sink, IObserver + private sealed class _ : Sink, IObserver { private long _sum; private long _count; @@ -644,7 +644,7 @@ protected override IDisposable Run(IObserver observer, IDisposable canc return _source.SubscribeSafe(sink); } - class _ : Sink, IObserver + private sealed class _ : Sink, IObserver { private long _sum; private long _count; diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Buffer.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Buffer.cs index 1dbf9a77c0..b6b0e9a632 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Buffer.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Buffer.cs @@ -8,697 +8,709 @@ namespace System.Reactive.Linq.ObservableImpl { - internal sealed class Buffer : Producer> + internal static class Buffer { - private readonly IObservable _source; - private readonly int _count; - private readonly int _skip; - - private readonly TimeSpan _timeSpan; - private readonly TimeSpan _timeShift; - private readonly IScheduler _scheduler; - - public Buffer(IObservable source, int count, int skip) - { - _source = source; - _count = count; - _skip = skip; - } - - public Buffer(IObservable source, TimeSpan timeSpan, TimeSpan timeShift, IScheduler scheduler) + internal sealed class Count : Producer> { - _source = source; - _timeSpan = timeSpan; - _timeShift = timeShift; - _scheduler = scheduler; - } + private readonly IObservable _source; + private readonly int _count; + private readonly int _skip; - public Buffer(IObservable source, TimeSpan timeSpan, int count, IScheduler scheduler) - { - _source = source; - _timeSpan = timeSpan; - _count = count; - _scheduler = scheduler; - } - - protected override IDisposable Run(IObserver> observer, IDisposable cancel, Action setSink) - { - if (_scheduler == null) + public Count(IObservable source, int count, int skip) { - var sink = new _(this, observer, cancel); - setSink(sink); - return sink.Run(); + _source = source; + _count = count; + _skip = skip; } - else if (_count > 0) + + protected override IDisposable Run(IObserver> observer, IDisposable cancel, Action setSink) { - var sink = new Impl(this, observer, cancel); + var sink = new _(this, observer, cancel); setSink(sink); - return sink.Run(); - } - else - { - if (_timeSpan == _timeShift) - { - var sink = new BufferTimeShift(this, observer, cancel); - setSink(sink); - return sink.Run(); - } - else - { - var sink = new BufferImpl(this, observer, cancel); - setSink(sink); - return sink.Run(); - } + return sink.Run(_source); } - } - - class _ : Sink>, IObserver - { - private readonly Buffer _parent; - public _(Buffer parent, IObserver> observer, IDisposable cancel) - : base(observer, cancel) + private sealed class _ : Sink>, IObserver { - _parent = parent; - } + private readonly Queue> _queue = new Queue>(); - private Queue> _queue; - private int _n; + private readonly int _count; + private readonly int _skip; - public IDisposable Run() - { - _queue = new Queue>(); - _n = 0; + public _(Count parent, IObserver> observer, IDisposable cancel) + : base(observer, cancel) + { + _count = parent._count; + _skip = parent._skip; + } - CreateWindow(); - return _parent._source.SubscribeSafe(this); - } + private int _n; - private void CreateWindow() - { - var s = new List(); - _queue.Enqueue(s); - } + public IDisposable Run(IObservable source) + { + _n = 0; - public void OnNext(TSource value) - { - foreach (var s in _queue) - s.Add(value); + CreateWindow(); + return source.SubscribeSafe(this); + } - var c = _n - _parent._count + 1; - if (c >= 0 && c % _parent._skip == 0) + private void CreateWindow() { - var s = _queue.Dequeue(); - if (s.Count > 0) - base._observer.OnNext(s); + var s = new List(); + _queue.Enqueue(s); } - _n++; - if (_n % _parent._skip == 0) - CreateWindow(); - } + public void OnNext(TSource value) + { + foreach (var s in _queue) + s.Add(value); - public void OnError(Exception error) - { - while (_queue.Count > 0) - _queue.Dequeue().Clear(); + var c = _n - _count + 1; + if (c >= 0 && c % _skip == 0) + { + var s = _queue.Dequeue(); + if (s.Count > 0) + base._observer.OnNext(s); + } - base._observer.OnError(error); - base.Dispose(); - } + _n++; + if (_n % _skip == 0) + CreateWindow(); + } - public void OnCompleted() - { - while (_queue.Count > 0) + public void OnError(Exception error) { - var s = _queue.Dequeue(); - if (s.Count > 0) - base._observer.OnNext(s); + while (_queue.Count > 0) + _queue.Dequeue().Clear(); + + base._observer.OnError(error); + base.Dispose(); } - base._observer.OnCompleted(); - base.Dispose(); + public void OnCompleted() + { + while (_queue.Count > 0) + { + var s = _queue.Dequeue(); + if (s.Count > 0) + base._observer.OnNext(s); + } + + base._observer.OnCompleted(); + base.Dispose(); + } } } - class BufferImpl : Sink>, IObserver + internal sealed class TimeSliding : Producer> { - private readonly Buffer _parent; + private readonly IObservable _source; + + private readonly TimeSpan _timeSpan; + private readonly TimeSpan _timeShift; + private readonly IScheduler _scheduler; - public BufferImpl(Buffer parent, IObserver> observer, IDisposable cancel) - : base(observer, cancel) + public TimeSliding(IObservable source, TimeSpan timeSpan, TimeSpan timeShift, IScheduler scheduler) { - _parent = parent; + _source = source; + _timeSpan = timeSpan; + _timeShift = timeShift; + _scheduler = scheduler; } - private TimeSpan _totalTime; - private TimeSpan _nextShift; - private TimeSpan _nextSpan; - - private object _gate; - private Queue> _q; - - private SerialDisposable _timerD; + protected override IDisposable Run(IObserver> observer, IDisposable cancel, Action setSink) + { + var sink = new _(this, observer, cancel); + setSink(sink); + return sink.Run(this); + } - public IDisposable Run() + private sealed class _ : Sink>, IObserver { - _totalTime = TimeSpan.Zero; - _nextShift = _parent._timeShift; - _nextSpan = _parent._timeSpan; + private readonly TimeSpan _timeShift; + private readonly IScheduler _scheduler; - _gate = new object(); - _q = new Queue>(); + private readonly object _gate = new object(); + private readonly Queue> _q = new Queue>(); + private readonly SerialDisposable _timerD = new SerialDisposable(); - _timerD = new SerialDisposable(); + public _(TimeSliding parent, IObserver> observer, IDisposable cancel) + : base(observer, cancel) + { + _timeShift = parent._timeShift; + _scheduler = parent._scheduler; + } - CreateWindow(); - CreateTimer(); + private TimeSpan _totalTime; + private TimeSpan _nextShift; + private TimeSpan _nextSpan; - var subscription = _parent._source.SubscribeSafe(this); + public IDisposable Run(TimeSliding parent) + { + _totalTime = TimeSpan.Zero; + _nextShift = parent._timeShift; + _nextSpan = parent._timeSpan; - return StableCompositeDisposable.Create(_timerD, subscription); - } + CreateWindow(); + CreateTimer(); - private void CreateWindow() - { - var s = new List(); - _q.Enqueue(s); - } + var subscription = parent._source.SubscribeSafe(this); - private void CreateTimer() - { - var m = new SingleAssignmentDisposable(); - _timerD.Disposable = m; + return StableCompositeDisposable.Create(_timerD, subscription); + } - var isSpan = false; - var isShift = false; - if (_nextSpan == _nextShift) + private void CreateWindow() { - isSpan = true; - isShift = true; + var s = new List(); + _q.Enqueue(s); } - else if (_nextSpan < _nextShift) - isSpan = true; - else - isShift = true; - var newTotalTime = isSpan ? _nextSpan : _nextShift; - var ts = newTotalTime - _totalTime; - _totalTime = newTotalTime; + private void CreateTimer() + { + var m = new SingleAssignmentDisposable(); + _timerD.Disposable = m; - if (isSpan) - _nextSpan += _parent._timeShift; - if (isShift) - _nextShift += _parent._timeShift; + var isSpan = false; + var isShift = false; + if (_nextSpan == _nextShift) + { + isSpan = true; + isShift = true; + } + else if (_nextSpan < _nextShift) + isSpan = true; + else + isShift = true; - m.Disposable = _parent._scheduler.Schedule(new State { isSpan = isSpan, isShift = isShift }, ts, Tick); - } + var newTotalTime = isSpan ? _nextSpan : _nextShift; + var ts = newTotalTime - _totalTime; + _totalTime = newTotalTime; - struct State - { - public bool isSpan; - public bool isShift; - } + if (isSpan) + _nextSpan += _timeShift; + if (isShift) + _nextShift += _timeShift; - private IDisposable Tick(IScheduler self, State state) - { - lock (_gate) + m.Disposable = _scheduler.Schedule(new State { isSpan = isSpan, isShift = isShift }, ts, Tick); + } + + private struct State { - // - // Before v2, the two operations below were reversed. This doesn't have an observable - // difference for Buffer, but is done to keep code consistent with Window, where we - // took a breaking change in v2 to ensure consistency across overloads. For more info, - // see the comment in Tick for Window. - // - if (state.isSpan) - { - var s = _q.Dequeue(); - base._observer.OnNext(s); - } + public bool isSpan; + public bool isShift; + } - if (state.isShift) + private IDisposable Tick(IScheduler self, State state) + { + lock (_gate) { - CreateWindow(); + // + // Before v2, the two operations below were reversed. This doesn't have an observable + // difference for Buffer, but is done to keep code consistent with Window, where we + // took a breaking change in v2 to ensure consistency across overloads. For more info, + // see the comment in Tick for Window. + // + if (state.isSpan) + { + var s = _q.Dequeue(); + base._observer.OnNext(s); + } + + if (state.isShift) + { + CreateWindow(); + } } - } - CreateTimer(); + CreateTimer(); - return Disposable.Empty; - } + return Disposable.Empty; + } - public void OnNext(TSource value) - { - lock (_gate) + public void OnNext(TSource value) { - foreach (var s in _q) - s.Add(value); + lock (_gate) + { + foreach (var s in _q) + s.Add(value); + } } - } - public void OnError(Exception error) - { - lock (_gate) + public void OnError(Exception error) { - while (_q.Count > 0) - _q.Dequeue().Clear(); + lock (_gate) + { + while (_q.Count > 0) + _q.Dequeue().Clear(); - base._observer.OnError(error); - base.Dispose(); + base._observer.OnError(error); + base.Dispose(); + } } - } - public void OnCompleted() - { - lock (_gate) + public void OnCompleted() { - while (_q.Count > 0) - base._observer.OnNext(_q.Dequeue()); + lock (_gate) + { + while (_q.Count > 0) + base._observer.OnNext(_q.Dequeue()); - base._observer.OnCompleted(); - base.Dispose(); + base._observer.OnCompleted(); + base.Dispose(); + } } } } - class BufferTimeShift : Sink>, IObserver + internal sealed class TimeHopping : Producer> { - private readonly Buffer _parent; + private readonly IObservable _source; - public BufferTimeShift(Buffer parent, IObserver> observer, IDisposable cancel) - : base(observer, cancel) + private readonly TimeSpan _timeSpan; + private readonly IScheduler _scheduler; + + public TimeHopping(IObservable source, TimeSpan timeSpan, IScheduler scheduler) { - _parent = parent; + _source = source; + _timeSpan = timeSpan; + _scheduler = scheduler; } - private object _gate; - private List _list; + protected override IDisposable Run(IObserver> observer, IDisposable cancel, Action setSink) + { + var sink = new _( observer, cancel); + setSink(sink); + return sink.Run(this); + } - public IDisposable Run() + private sealed class _ : Sink>, IObserver { - _gate = new object(); - _list = new List(); + private readonly object _gate = new object(); - var d = _parent._scheduler.SchedulePeriodic(_parent._timeSpan, Tick); - var s = _parent._source.SubscribeSafe(this); + public _(IObserver> observer, IDisposable cancel) + : base(observer, cancel) + { + } - return StableCompositeDisposable.Create(d, s); - } + private List _list; - private void Tick() - { - lock (_gate) + public IDisposable Run(TimeHopping parent) { - base._observer.OnNext(_list); _list = new List(); + + var d = parent._scheduler.SchedulePeriodic(parent._timeSpan, Tick); + var s = parent._source.SubscribeSafe(this); + + return StableCompositeDisposable.Create(d, s); } - } - public void OnNext(TSource value) - { - lock (_gate) + private void Tick() { - _list.Add(value); + lock (_gate) + { + base._observer.OnNext(_list); + _list = new List(); + } } - } - public void OnError(Exception error) - { - lock (_gate) + public void OnNext(TSource value) { - _list.Clear(); + lock (_gate) + { + _list.Add(value); + } + } - base._observer.OnError(error); - base.Dispose(); + public void OnError(Exception error) + { + lock (_gate) + { + _list.Clear(); + + base._observer.OnError(error); + base.Dispose(); + } } - } - public void OnCompleted() - { - lock (_gate) + public void OnCompleted() { - base._observer.OnNext(_list); - base._observer.OnCompleted(); - base.Dispose(); + lock (_gate) + { + base._observer.OnNext(_list); + base._observer.OnCompleted(); + base.Dispose(); + } } } } - class Impl : Sink>, IObserver + internal sealed class Ferry : Producer> { - private readonly Buffer _parent; + private readonly IObservable _source; + private readonly int _count; + private readonly TimeSpan _timeSpan; + private readonly IScheduler _scheduler; - public Impl(Buffer parent, IObserver> observer, IDisposable cancel) - : base(observer, cancel) + public Ferry(IObservable source, TimeSpan timeSpan, int count, IScheduler scheduler) { - _parent = parent; + _source = source; + _timeSpan = timeSpan; + _count = count; + _scheduler = scheduler; } - private object _gate; - private IList _s; - private int _n; - private int _windowId; - - private SerialDisposable _timerD; - - public IDisposable Run() + protected override IDisposable Run(IObserver> observer, IDisposable cancel, Action setSink) { - _gate = new object(); - _s = default(IList); - _n = 0; - _windowId = 0; - - _timerD = new SerialDisposable(); - - _s = new List(); - CreateTimer(0); - - var subscription = _parent._source.SubscribeSafe(this); - - return StableCompositeDisposable.Create(_timerD, subscription); + var sink = new _(this, observer, cancel); + setSink(sink); + return sink.Run(); } - private void CreateTimer(int id) + private sealed class _ : Sink>, IObserver { - var m = new SingleAssignmentDisposable(); - _timerD.Disposable = m; + private readonly Ferry _parent; - m.Disposable = _parent._scheduler.Schedule(id, _parent._timeSpan, Tick); - } + private readonly object _gate = new object(); + private readonly SerialDisposable _timerD = new SerialDisposable(); - private IDisposable Tick(IScheduler self, int id) - { - var d = Disposable.Empty; - - var newId = 0; - lock (_gate) + public _(Ferry parent, IObserver> observer, IDisposable cancel) + : base(observer, cancel) { - if (id != _windowId) - return d; + _parent = parent; + } - _n = 0; - newId = ++_windowId; + private IList _s; + private int _n; + private int _windowId; - var res = _s; + public IDisposable Run() + { _s = new List(); - base._observer.OnNext(res); + _n = 0; + _windowId = 0; + + CreateTimer(0); + + var subscription = _parent._source.SubscribeSafe(this); - CreateTimer(newId); + return StableCompositeDisposable.Create(_timerD, subscription); } - return d; - } + private void CreateTimer(int id) + { + var m = new SingleAssignmentDisposable(); + _timerD.Disposable = m; - public void OnNext(TSource value) - { - var newWindow = false; - var newId = 0; + m.Disposable = _parent._scheduler.Schedule(id, _parent._timeSpan, Tick); + } - lock (_gate) + private IDisposable Tick(IScheduler self, int id) { - _s.Add(value); + var d = Disposable.Empty; - _n++; - if (_n == _parent._count) + var newId = 0; + lock (_gate) { - newWindow = true; + if (id != _windowId) + return d; + _n = 0; newId = ++_windowId; var res = _s; _s = new List(); base._observer.OnNext(res); - } - if (newWindow) CreateTimer(newId); + } + + return d; } - } - public void OnError(Exception error) - { - lock (_gate) + public void OnNext(TSource value) { - _s.Clear(); - base._observer.OnError(error); - base.Dispose(); + var newWindow = false; + var newId = 0; + + lock (_gate) + { + _s.Add(value); + + _n++; + if (_n == _parent._count) + { + newWindow = true; + _n = 0; + newId = ++_windowId; + + var res = _s; + _s = new List(); + base._observer.OnNext(res); + } + + if (newWindow) + CreateTimer(newId); + } } - } - public void OnCompleted() - { - lock (_gate) + public void OnError(Exception error) { - base._observer.OnNext(_s); - base._observer.OnCompleted(); - base.Dispose(); + lock (_gate) + { + _s.Clear(); + base._observer.OnError(error); + base.Dispose(); + } + } + + public void OnCompleted() + { + lock (_gate) + { + base._observer.OnNext(_s); + base._observer.OnCompleted(); + base.Dispose(); + } } } } } - internal sealed class Buffer : Producer> + internal static class Buffer { - private readonly IObservable _source; - private readonly Func> _bufferClosingSelector; - private readonly IObservable _bufferBoundaries; - - public Buffer(IObservable source, Func> bufferClosingSelector) + internal sealed class Selector : Producer> { - _source = source; - _bufferClosingSelector = bufferClosingSelector; - } + private readonly IObservable _source; + private readonly Func> _bufferClosingSelector; - public Buffer(IObservable source, IObservable bufferBoundaries) - { - _source = source; - _bufferBoundaries = bufferBoundaries; - } - - protected override IDisposable Run(IObserver> observer, IDisposable cancel, Action setSink) - { - if (_bufferClosingSelector != null) + public Selector(IObservable source, Func> bufferClosingSelector) { - var sink = new _(this, observer, cancel); - setSink(sink); - return sink.Run(); + _source = source; + _bufferClosingSelector = bufferClosingSelector; } - else + + protected override IDisposable Run(IObserver> observer, IDisposable cancel, Action setSink) { - var sink = new Beta(this, observer, cancel); + var sink = new _(this, observer, cancel); setSink(sink); - return sink.Run(); + return sink.Run(_source); } - } - class _ : Sink>, IObserver - { - private readonly Buffer _parent; - - public _(Buffer parent, IObserver> observer, IDisposable cancel) - : base(observer, cancel) + private sealed class _ : Sink>, IObserver { - _parent = parent; - } + private readonly object _gate = new object(); + private readonly AsyncLock _bufferGate = new AsyncLock(); + private readonly SerialDisposable _bufferClosingSubscription = new SerialDisposable(); - private IList _buffer; - private object _gate; - private AsyncLock _bufferGate; + private readonly Func> _bufferClosingSelector; - private SerialDisposable _m; + public _(Selector parent, IObserver> observer, IDisposable cancel) + : base(observer, cancel) + { + _bufferClosingSelector = parent._bufferClosingSelector; + } - public IDisposable Run() - { - _buffer = new List(); - _gate = new object(); - _bufferGate = new AsyncLock(); + private IList _buffer; - _m = new SerialDisposable(); - var groupDisposable = new CompositeDisposable(2) { _m }; + public IDisposable Run(IObservable source) + { + _buffer = new List(); - groupDisposable.Add(_parent._source.SubscribeSafe(this)); + var groupDisposable = StableCompositeDisposable.Create(_bufferClosingSubscription, source.SubscribeSafe(this)); - _bufferGate.Wait(CreateBufferClose); + _bufferGate.Wait(CreateBufferClose); - return groupDisposable; - } + return groupDisposable; + } - private void CreateBufferClose() - { - var bufferClose = default(IObservable); - try + private void CreateBufferClose() { - bufferClose = _parent._bufferClosingSelector(); + var bufferClose = default(IObservable); + try + { + bufferClose = _bufferClosingSelector(); + } + catch (Exception exception) + { + lock (_gate) + { + base._observer.OnError(exception); + base.Dispose(); + } + return; + } + + var closingSubscription = new SingleAssignmentDisposable(); + _bufferClosingSubscription.Disposable = closingSubscription; + closingSubscription.Disposable = bufferClose.SubscribeSafe(new BufferClosingObserver(this, closingSubscription)); } - catch (Exception exception) + + private void CloseBuffer(IDisposable closingSubscription) { + closingSubscription.Dispose(); + lock (_gate) { - base._observer.OnError(exception); - base.Dispose(); + var res = _buffer; + _buffer = new List(); + base._observer.OnNext(res); } - return; - } - var closingSubscription = new SingleAssignmentDisposable(); - _m.Disposable = closingSubscription; - closingSubscription.Disposable = bufferClose.SubscribeSafe(new Omega(this, closingSubscription)); - } - - private void CloseBuffer(IDisposable closingSubscription) - { - closingSubscription.Dispose(); + _bufferGate.Wait(CreateBufferClose); + } - lock (_gate) + private sealed class BufferClosingObserver : IObserver { - var res = _buffer; - _buffer = new List(); - base._observer.OnNext(res); - } + private readonly _ _parent; + private readonly IDisposable _self; - _bufferGate.Wait(CreateBufferClose); - } + public BufferClosingObserver(_ parent, IDisposable self) + { + _parent = parent; + _self = self; + } - class Omega : IObserver - { - private readonly _ _parent; - private readonly IDisposable _self; + public void OnNext(TBufferClosing value) + { + _parent.CloseBuffer(_self); + } - public Omega(_ parent, IDisposable self) - { - _parent = parent; - _self = self; + public void OnError(Exception error) + { + _parent.OnError(error); + } + + public void OnCompleted() + { + _parent.CloseBuffer(_self); + } } - public void OnNext(TBufferClosing value) + public void OnNext(TSource value) { - _parent.CloseBuffer(_self); + lock (_gate) + { + _buffer.Add(value); + } } public void OnError(Exception error) { - _parent.OnError(error); + lock (_gate) + { + _buffer.Clear(); + base._observer.OnError(error); + base.Dispose(); + } } public void OnCompleted() { - _parent.CloseBuffer(_self); + lock (_gate) + { + base._observer.OnNext(_buffer); + base._observer.OnCompleted(); + base.Dispose(); + } } } + } - public void OnNext(TSource value) + internal sealed class Boundaries : Producer> + { + private readonly IObservable _source; + private readonly IObservable _bufferBoundaries; + + public Boundaries(IObservable source, IObservable bufferBoundaries) { - lock (_gate) - { - _buffer.Add(value); - } + _source = source; + _bufferBoundaries = bufferBoundaries; } - public void OnError(Exception error) + protected override IDisposable Run(IObserver> observer, IDisposable cancel, Action setSink) { - lock (_gate) - { - _buffer.Clear(); - base._observer.OnError(error); - base.Dispose(); - } + var sink = new _(observer, cancel); + setSink(sink); + return sink.Run(this); } - public void OnCompleted() + private sealed class _ : Sink>, IObserver { - lock (_gate) + private readonly object _gate = new object(); + + public _(IObserver> observer, IDisposable cancel) + : base(observer, cancel) { - base._observer.OnNext(_buffer); - base._observer.OnCompleted(); - base.Dispose(); } - } - } - - class Beta : Sink>, IObserver - { - private readonly Buffer _parent; - public Beta(Buffer parent, IObserver> observer, IDisposable cancel) - : base(observer, cancel) - { - _parent = parent; - } + private IList _buffer; - private IList _buffer; - private object _gate; + public IDisposable Run(Boundaries parent) + { + _buffer = new List(); - private RefCountDisposable _refCountDisposable; + var sourceSubscription = parent._source.SubscribeSafe(this); + var boundariesSubscription = parent._bufferBoundaries.SubscribeSafe(new BufferClosingObserver(this)); - public IDisposable Run() - { - _buffer = new List(); - _gate = new object(); + return StableCompositeDisposable.Create(sourceSubscription, boundariesSubscription); + } - var d = new CompositeDisposable(2); - _refCountDisposable = new RefCountDisposable(d); + private sealed class BufferClosingObserver : IObserver + { + private readonly _ _parent; - d.Add(_parent._source.SubscribeSafe(this)); - d.Add(_parent._bufferBoundaries.SubscribeSafe(new Omega(this))); + public BufferClosingObserver(_ parent) + { + _parent = parent; + } - return _refCountDisposable; - } + public void OnNext(TBufferClosing value) + { + lock (_parent._gate) + { + var res = _parent._buffer; + _parent._buffer = new List(); + _parent._observer.OnNext(res); + } + } - class Omega : IObserver - { - private readonly Beta _parent; + public void OnError(Exception error) + { + _parent.OnError(error); + } - public Omega(Beta parent) - { - _parent = parent; + public void OnCompleted() + { + _parent.OnCompleted(); + } } - public void OnNext(TBufferClosing value) + public void OnNext(TSource value) { - lock (_parent._gate) + lock (_gate) { - var res = _parent._buffer; - _parent._buffer = new List(); - _parent._observer.OnNext(res); + _buffer.Add(value); } } public void OnError(Exception error) { - _parent.OnError(error); + lock (_gate) + { + _buffer.Clear(); + base._observer.OnError(error); + base.Dispose(); + } } public void OnCompleted() { - _parent.OnCompleted(); - } - } - - public void OnNext(TSource value) - { - lock (_gate) - { - _buffer.Add(value); - } - } - - public void OnError(Exception error) - { - lock (_gate) - { - _buffer.Clear(); - base._observer.OnError(error); - base.Dispose(); - } - } - - public void OnCompleted() - { - lock (_gate) - { - base._observer.OnNext(_buffer); - base._observer.OnCompleted(); - base.Dispose(); + lock (_gate) + { + base._observer.OnNext(_buffer); + base._observer.OnCompleted(); + base.Dispose(); + } } } } diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Case.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Case.cs index 9c67036b45..aa92377ad8 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Case.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Case.cs @@ -31,27 +31,24 @@ public IObservable Eval() protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - var sink = new _(this, observer, cancel); + var sink = new _(observer, cancel); setSink(sink); - return sink.Run(); + return sink.Run(this); } - class _ : Sink, IObserver + private sealed class _ : Sink, IObserver { - private readonly Case _parent; - - public _(Case parent, IObserver observer, IDisposable cancel) + public _(IObserver observer, IDisposable cancel) : base(observer, cancel) { - _parent = parent; } - public IDisposable Run() + public IDisposable Run(Case parent) { var result = default(IObservable); try { - result = _parent.Eval(); + result = parent.Eval(); } catch (Exception exception) { diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Cast.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Cast.cs index 8f3b126679..5b4247383e 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Cast.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Cast.cs @@ -20,7 +20,7 @@ protected override IDisposable Run(IObserver observer, IDisposable canc return _source.SubscribeSafe(sink); } - class _ : Sink, IObserver + private sealed class _ : Sink, IObserver { public _(IObserver observer, IDisposable cancel) : base(observer, cancel) diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Catch.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Catch.cs index 34a87afb7a..2b7e9b58c0 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Catch.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Catch.cs @@ -23,7 +23,7 @@ protected override IDisposable Run(IObserver observer, IDisposable canc return sink.Run(_sources); } - class _ : TailRecursiveSink + private sealed class _ : TailRecursiveSink { public _(IObserver observer, IDisposable cancel) : base(observer, cancel) @@ -94,30 +94,30 @@ public Catch(IObservable source, Func> protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - var sink = new _(this, observer, cancel); + var sink = new _(_handler, observer, cancel); setSink(sink); - return sink.Run(); + return sink.Run(_source); } - class _ : Sink, IObserver + private sealed class _ : Sink, IObserver { - private readonly Catch _parent; + private readonly Func> _handler; - public _(Catch parent, IObserver observer, IDisposable cancel) + public _(Func> handler, IObserver observer, IDisposable cancel) : base(observer, cancel) { - _parent = parent; + _handler = handler; } private SerialDisposable _subscription; - public IDisposable Run() + public IDisposable Run(IObservable source) { _subscription = new SerialDisposable(); var d1 = new SingleAssignmentDisposable(); _subscription.Disposable = d1; - d1.Disposable = _parent._source.SubscribeSafe(this); + d1.Disposable = source.SubscribeSafe(this); return _subscription; } @@ -135,7 +135,7 @@ public void OnError(Exception error) var result = default(IObservable); try { - result = _parent._handler(e); + result = _handler(e); } catch (Exception ex) { @@ -146,7 +146,7 @@ public void OnError(Exception error) var d = new SingleAssignmentDisposable(); _subscription.Disposable = d; - d.Disposable = result.SubscribeSafe(new Impl(this)); + d.Disposable = result.SubscribeSafe(new HandlerObserver(this)); } else { @@ -161,11 +161,11 @@ public void OnCompleted() base.Dispose(); } - class Impl : IObserver + private sealed class HandlerObserver : IObserver { private readonly _ _parent; - public Impl(_ parent) + public HandlerObserver(_ parent) { _parent = parent; } diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Collect.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Collect.cs index 7e18bd1593..5244c00d45 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Collect.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Collect.cs @@ -25,8 +25,10 @@ protected override PushToPullSink Run(IDisposable subscription return sink; } - class _ : PushToPullSink + private sealed class _ : PushToPullSink { + // CONSIDER: This sink has a parent reference that can be considered for removal. + private readonly Collect _parent; public _(Collect parent, IDisposable subscription) diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/CombineLatest.Generated.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/CombineLatest.Generated.cs index d3ded501e7..6d2a4af41f 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/CombineLatest.Generated.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/CombineLatest.Generated.cs @@ -10,7 +10,7 @@ namespace System.Reactive.Linq.ObservableImpl /* The following code is generated by a T4 template. */ - #region CombineLatest auto-generated code (4/14/2017 12:18:58 PM) + #region CombineLatest auto-generated code (4/17/2017 3:25:27 PM) internal sealed class CombineLatest : Producer { @@ -29,26 +29,26 @@ public CombineLatest(IObservable source1, IObservable source2, IObservab protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - var sink = new _(this, observer, cancel); + var sink = new _(_resultSelector, observer, cancel); setSink(sink); - return sink.Run(); + return sink.Run(_source1, _source2, _source3); } - class _ : CombineLatestSink + private sealed class _ : CombineLatestSink { - private readonly CombineLatest _parent; + private readonly Func _resultSelector; - public _(CombineLatest parent, IObserver observer, IDisposable cancel) + public _(Func resultSelector, IObserver observer, IDisposable cancel) : base(3, observer, cancel) { - _parent = parent; + _resultSelector = resultSelector; } private CombineLatestObserver _observer1; private CombineLatestObserver _observer2; private CombineLatestObserver _observer3; - public IDisposable Run() + public IDisposable Run(IObservable source1, IObservable source2, IObservable source3) { var subscriptions = new SingleAssignmentDisposable[3]; for (int i = 0; i < 3; i++) @@ -57,18 +57,15 @@ public IDisposable Run() _observer1 = new CombineLatestObserver(_gate, this, 0, subscriptions[0]); _observer2 = new CombineLatestObserver(_gate, this, 1, subscriptions[1]); _observer3 = new CombineLatestObserver(_gate, this, 2, subscriptions[2]); - - subscriptions[0].Disposable = _parent._source1.SubscribeSafe(_observer1); - subscriptions[1].Disposable = _parent._source2.SubscribeSafe(_observer2); - subscriptions[2].Disposable = _parent._source3.SubscribeSafe(_observer3); + + subscriptions[0].Disposable = source1.SubscribeSafe(_observer1); + subscriptions[1].Disposable = source2.SubscribeSafe(_observer2); + subscriptions[2].Disposable = source3.SubscribeSafe(_observer3); return StableCompositeDisposable.Create(subscriptions); } - protected override TResult GetResult() - { - return _parent._resultSelector(_observer1.Value, _observer2.Value, _observer3.Value); - } + protected override TResult GetResult() => _resultSelector(_observer1.Value, _observer2.Value, _observer3.Value); } } @@ -91,19 +88,19 @@ public CombineLatest(IObservable source1, IObservable source2, IObservab protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - var sink = new _(this, observer, cancel); + var sink = new _(_resultSelector, observer, cancel); setSink(sink); - return sink.Run(); + return sink.Run(_source1, _source2, _source3, _source4); } - class _ : CombineLatestSink + private sealed class _ : CombineLatestSink { - private readonly CombineLatest _parent; + private readonly Func _resultSelector; - public _(CombineLatest parent, IObserver observer, IDisposable cancel) + public _(Func resultSelector, IObserver observer, IDisposable cancel) : base(4, observer, cancel) { - _parent = parent; + _resultSelector = resultSelector; } private CombineLatestObserver _observer1; @@ -111,7 +108,7 @@ public _(CombineLatest parent, IObserver obser private CombineLatestObserver _observer3; private CombineLatestObserver _observer4; - public IDisposable Run() + public IDisposable Run(IObservable source1, IObservable source2, IObservable source3, IObservable source4) { var subscriptions = new SingleAssignmentDisposable[4]; for (int i = 0; i < 4; i++) @@ -121,19 +118,16 @@ public IDisposable Run() _observer2 = new CombineLatestObserver(_gate, this, 1, subscriptions[1]); _observer3 = new CombineLatestObserver(_gate, this, 2, subscriptions[2]); _observer4 = new CombineLatestObserver(_gate, this, 3, subscriptions[3]); - - subscriptions[0].Disposable = _parent._source1.SubscribeSafe(_observer1); - subscriptions[1].Disposable = _parent._source2.SubscribeSafe(_observer2); - subscriptions[2].Disposable = _parent._source3.SubscribeSafe(_observer3); - subscriptions[3].Disposable = _parent._source4.SubscribeSafe(_observer4); + + subscriptions[0].Disposable = source1.SubscribeSafe(_observer1); + subscriptions[1].Disposable = source2.SubscribeSafe(_observer2); + subscriptions[2].Disposable = source3.SubscribeSafe(_observer3); + subscriptions[3].Disposable = source4.SubscribeSafe(_observer4); return StableCompositeDisposable.Create(subscriptions); } - protected override TResult GetResult() - { - return _parent._resultSelector(_observer1.Value, _observer2.Value, _observer3.Value, _observer4.Value); - } + protected override TResult GetResult() => _resultSelector(_observer1.Value, _observer2.Value, _observer3.Value, _observer4.Value); } } @@ -158,19 +152,19 @@ public CombineLatest(IObservable source1, IObservable source2, IObservab protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - var sink = new _(this, observer, cancel); + var sink = new _(_resultSelector, observer, cancel); setSink(sink); - return sink.Run(); + return sink.Run(_source1, _source2, _source3, _source4, _source5); } - class _ : CombineLatestSink + private sealed class _ : CombineLatestSink { - private readonly CombineLatest _parent; + private readonly Func _resultSelector; - public _(CombineLatest parent, IObserver observer, IDisposable cancel) + public _(Func resultSelector, IObserver observer, IDisposable cancel) : base(5, observer, cancel) { - _parent = parent; + _resultSelector = resultSelector; } private CombineLatestObserver _observer1; @@ -179,7 +173,7 @@ public _(CombineLatest parent, IObserver o private CombineLatestObserver _observer4; private CombineLatestObserver _observer5; - public IDisposable Run() + public IDisposable Run(IObservable source1, IObservable source2, IObservable source3, IObservable source4, IObservable source5) { var subscriptions = new SingleAssignmentDisposable[5]; for (int i = 0; i < 5; i++) @@ -190,20 +184,17 @@ public IDisposable Run() _observer3 = new CombineLatestObserver(_gate, this, 2, subscriptions[2]); _observer4 = new CombineLatestObserver(_gate, this, 3, subscriptions[3]); _observer5 = new CombineLatestObserver(_gate, this, 4, subscriptions[4]); - - subscriptions[0].Disposable = _parent._source1.SubscribeSafe(_observer1); - subscriptions[1].Disposable = _parent._source2.SubscribeSafe(_observer2); - subscriptions[2].Disposable = _parent._source3.SubscribeSafe(_observer3); - subscriptions[3].Disposable = _parent._source4.SubscribeSafe(_observer4); - subscriptions[4].Disposable = _parent._source5.SubscribeSafe(_observer5); + + subscriptions[0].Disposable = source1.SubscribeSafe(_observer1); + subscriptions[1].Disposable = source2.SubscribeSafe(_observer2); + subscriptions[2].Disposable = source3.SubscribeSafe(_observer3); + subscriptions[3].Disposable = source4.SubscribeSafe(_observer4); + subscriptions[4].Disposable = source5.SubscribeSafe(_observer5); return StableCompositeDisposable.Create(subscriptions); } - protected override TResult GetResult() - { - return _parent._resultSelector(_observer1.Value, _observer2.Value, _observer3.Value, _observer4.Value, _observer5.Value); - } + protected override TResult GetResult() => _resultSelector(_observer1.Value, _observer2.Value, _observer3.Value, _observer4.Value, _observer5.Value); } } @@ -230,19 +221,19 @@ public CombineLatest(IObservable source1, IObservable source2, IObservab protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - var sink = new _(this, observer, cancel); + var sink = new _(_resultSelector, observer, cancel); setSink(sink); - return sink.Run(); + return sink.Run(_source1, _source2, _source3, _source4, _source5, _source6); } - class _ : CombineLatestSink + private sealed class _ : CombineLatestSink { - private readonly CombineLatest _parent; + private readonly Func _resultSelector; - public _(CombineLatest parent, IObserver observer, IDisposable cancel) + public _(Func resultSelector, IObserver observer, IDisposable cancel) : base(6, observer, cancel) { - _parent = parent; + _resultSelector = resultSelector; } private CombineLatestObserver _observer1; @@ -252,7 +243,7 @@ public _(CombineLatest parent, IObserver _observer5; private CombineLatestObserver _observer6; - public IDisposable Run() + public IDisposable Run(IObservable source1, IObservable source2, IObservable source3, IObservable source4, IObservable source5, IObservable source6) { var subscriptions = new SingleAssignmentDisposable[6]; for (int i = 0; i < 6; i++) @@ -264,21 +255,18 @@ public IDisposable Run() _observer4 = new CombineLatestObserver(_gate, this, 3, subscriptions[3]); _observer5 = new CombineLatestObserver(_gate, this, 4, subscriptions[4]); _observer6 = new CombineLatestObserver(_gate, this, 5, subscriptions[5]); - - subscriptions[0].Disposable = _parent._source1.SubscribeSafe(_observer1); - subscriptions[1].Disposable = _parent._source2.SubscribeSafe(_observer2); - subscriptions[2].Disposable = _parent._source3.SubscribeSafe(_observer3); - subscriptions[3].Disposable = _parent._source4.SubscribeSafe(_observer4); - subscriptions[4].Disposable = _parent._source5.SubscribeSafe(_observer5); - subscriptions[5].Disposable = _parent._source6.SubscribeSafe(_observer6); + + subscriptions[0].Disposable = source1.SubscribeSafe(_observer1); + subscriptions[1].Disposable = source2.SubscribeSafe(_observer2); + subscriptions[2].Disposable = source3.SubscribeSafe(_observer3); + subscriptions[3].Disposable = source4.SubscribeSafe(_observer4); + subscriptions[4].Disposable = source5.SubscribeSafe(_observer5); + subscriptions[5].Disposable = source6.SubscribeSafe(_observer6); return StableCompositeDisposable.Create(subscriptions); } - protected override TResult GetResult() - { - return _parent._resultSelector(_observer1.Value, _observer2.Value, _observer3.Value, _observer4.Value, _observer5.Value, _observer6.Value); - } + protected override TResult GetResult() => _resultSelector(_observer1.Value, _observer2.Value, _observer3.Value, _observer4.Value, _observer5.Value, _observer6.Value); } } @@ -307,19 +295,19 @@ public CombineLatest(IObservable source1, IObservable source2, IObservab protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - var sink = new _(this, observer, cancel); + var sink = new _(_resultSelector, observer, cancel); setSink(sink); - return sink.Run(); + return sink.Run(_source1, _source2, _source3, _source4, _source5, _source6, _source7); } - class _ : CombineLatestSink + private sealed class _ : CombineLatestSink { - private readonly CombineLatest _parent; + private readonly Func _resultSelector; - public _(CombineLatest parent, IObserver observer, IDisposable cancel) + public _(Func resultSelector, IObserver observer, IDisposable cancel) : base(7, observer, cancel) { - _parent = parent; + _resultSelector = resultSelector; } private CombineLatestObserver _observer1; @@ -330,7 +318,7 @@ public _(CombineLatest parent, IObserver _observer6; private CombineLatestObserver _observer7; - public IDisposable Run() + public IDisposable Run(IObservable source1, IObservable source2, IObservable source3, IObservable source4, IObservable source5, IObservable source6, IObservable source7) { var subscriptions = new SingleAssignmentDisposable[7]; for (int i = 0; i < 7; i++) @@ -343,22 +331,19 @@ public IDisposable Run() _observer5 = new CombineLatestObserver(_gate, this, 4, subscriptions[4]); _observer6 = new CombineLatestObserver(_gate, this, 5, subscriptions[5]); _observer7 = new CombineLatestObserver(_gate, this, 6, subscriptions[6]); - - subscriptions[0].Disposable = _parent._source1.SubscribeSafe(_observer1); - subscriptions[1].Disposable = _parent._source2.SubscribeSafe(_observer2); - subscriptions[2].Disposable = _parent._source3.SubscribeSafe(_observer3); - subscriptions[3].Disposable = _parent._source4.SubscribeSafe(_observer4); - subscriptions[4].Disposable = _parent._source5.SubscribeSafe(_observer5); - subscriptions[5].Disposable = _parent._source6.SubscribeSafe(_observer6); - subscriptions[6].Disposable = _parent._source7.SubscribeSafe(_observer7); + + subscriptions[0].Disposable = source1.SubscribeSafe(_observer1); + subscriptions[1].Disposable = source2.SubscribeSafe(_observer2); + subscriptions[2].Disposable = source3.SubscribeSafe(_observer3); + subscriptions[3].Disposable = source4.SubscribeSafe(_observer4); + subscriptions[4].Disposable = source5.SubscribeSafe(_observer5); + subscriptions[5].Disposable = source6.SubscribeSafe(_observer6); + subscriptions[6].Disposable = source7.SubscribeSafe(_observer7); return StableCompositeDisposable.Create(subscriptions); } - protected override TResult GetResult() - { - return _parent._resultSelector(_observer1.Value, _observer2.Value, _observer3.Value, _observer4.Value, _observer5.Value, _observer6.Value, _observer7.Value); - } + protected override TResult GetResult() => _resultSelector(_observer1.Value, _observer2.Value, _observer3.Value, _observer4.Value, _observer5.Value, _observer6.Value, _observer7.Value); } } @@ -389,19 +374,19 @@ public CombineLatest(IObservable source1, IObservable source2, IObservab protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - var sink = new _(this, observer, cancel); + var sink = new _(_resultSelector, observer, cancel); setSink(sink); - return sink.Run(); + return sink.Run(_source1, _source2, _source3, _source4, _source5, _source6, _source7, _source8); } - class _ : CombineLatestSink + private sealed class _ : CombineLatestSink { - private readonly CombineLatest _parent; + private readonly Func _resultSelector; - public _(CombineLatest parent, IObserver observer, IDisposable cancel) + public _(Func resultSelector, IObserver observer, IDisposable cancel) : base(8, observer, cancel) { - _parent = parent; + _resultSelector = resultSelector; } private CombineLatestObserver _observer1; @@ -413,7 +398,7 @@ public _(CombineLatest parent, IObserve private CombineLatestObserver _observer7; private CombineLatestObserver _observer8; - public IDisposable Run() + public IDisposable Run(IObservable source1, IObservable source2, IObservable source3, IObservable source4, IObservable source5, IObservable source6, IObservable source7, IObservable source8) { var subscriptions = new SingleAssignmentDisposable[8]; for (int i = 0; i < 8; i++) @@ -427,23 +412,20 @@ public IDisposable Run() _observer6 = new CombineLatestObserver(_gate, this, 5, subscriptions[5]); _observer7 = new CombineLatestObserver(_gate, this, 6, subscriptions[6]); _observer8 = new CombineLatestObserver(_gate, this, 7, subscriptions[7]); - - subscriptions[0].Disposable = _parent._source1.SubscribeSafe(_observer1); - subscriptions[1].Disposable = _parent._source2.SubscribeSafe(_observer2); - subscriptions[2].Disposable = _parent._source3.SubscribeSafe(_observer3); - subscriptions[3].Disposable = _parent._source4.SubscribeSafe(_observer4); - subscriptions[4].Disposable = _parent._source5.SubscribeSafe(_observer5); - subscriptions[5].Disposable = _parent._source6.SubscribeSafe(_observer6); - subscriptions[6].Disposable = _parent._source7.SubscribeSafe(_observer7); - subscriptions[7].Disposable = _parent._source8.SubscribeSafe(_observer8); + + subscriptions[0].Disposable = source1.SubscribeSafe(_observer1); + subscriptions[1].Disposable = source2.SubscribeSafe(_observer2); + subscriptions[2].Disposable = source3.SubscribeSafe(_observer3); + subscriptions[3].Disposable = source4.SubscribeSafe(_observer4); + subscriptions[4].Disposable = source5.SubscribeSafe(_observer5); + subscriptions[5].Disposable = source6.SubscribeSafe(_observer6); + subscriptions[6].Disposable = source7.SubscribeSafe(_observer7); + subscriptions[7].Disposable = source8.SubscribeSafe(_observer8); return StableCompositeDisposable.Create(subscriptions); } - protected override TResult GetResult() - { - return _parent._resultSelector(_observer1.Value, _observer2.Value, _observer3.Value, _observer4.Value, _observer5.Value, _observer6.Value, _observer7.Value, _observer8.Value); - } + protected override TResult GetResult() => _resultSelector(_observer1.Value, _observer2.Value, _observer3.Value, _observer4.Value, _observer5.Value, _observer6.Value, _observer7.Value, _observer8.Value); } } @@ -476,19 +458,19 @@ public CombineLatest(IObservable source1, IObservable source2, IObservab protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - var sink = new _(this, observer, cancel); + var sink = new _(_resultSelector, observer, cancel); setSink(sink); - return sink.Run(); + return sink.Run(_source1, _source2, _source3, _source4, _source5, _source6, _source7, _source8, _source9); } - class _ : CombineLatestSink + private sealed class _ : CombineLatestSink { - private readonly CombineLatest _parent; + private readonly Func _resultSelector; - public _(CombineLatest parent, IObserver observer, IDisposable cancel) + public _(Func resultSelector, IObserver observer, IDisposable cancel) : base(9, observer, cancel) { - _parent = parent; + _resultSelector = resultSelector; } private CombineLatestObserver _observer1; @@ -501,7 +483,7 @@ public _(CombineLatest parent, IObs private CombineLatestObserver _observer8; private CombineLatestObserver _observer9; - public IDisposable Run() + public IDisposable Run(IObservable source1, IObservable source2, IObservable source3, IObservable source4, IObservable source5, IObservable source6, IObservable source7, IObservable source8, IObservable source9) { var subscriptions = new SingleAssignmentDisposable[9]; for (int i = 0; i < 9; i++) @@ -516,24 +498,21 @@ public IDisposable Run() _observer7 = new CombineLatestObserver(_gate, this, 6, subscriptions[6]); _observer8 = new CombineLatestObserver(_gate, this, 7, subscriptions[7]); _observer9 = new CombineLatestObserver(_gate, this, 8, subscriptions[8]); - - subscriptions[0].Disposable = _parent._source1.SubscribeSafe(_observer1); - subscriptions[1].Disposable = _parent._source2.SubscribeSafe(_observer2); - subscriptions[2].Disposable = _parent._source3.SubscribeSafe(_observer3); - subscriptions[3].Disposable = _parent._source4.SubscribeSafe(_observer4); - subscriptions[4].Disposable = _parent._source5.SubscribeSafe(_observer5); - subscriptions[5].Disposable = _parent._source6.SubscribeSafe(_observer6); - subscriptions[6].Disposable = _parent._source7.SubscribeSafe(_observer7); - subscriptions[7].Disposable = _parent._source8.SubscribeSafe(_observer8); - subscriptions[8].Disposable = _parent._source9.SubscribeSafe(_observer9); + + subscriptions[0].Disposable = source1.SubscribeSafe(_observer1); + subscriptions[1].Disposable = source2.SubscribeSafe(_observer2); + subscriptions[2].Disposable = source3.SubscribeSafe(_observer3); + subscriptions[3].Disposable = source4.SubscribeSafe(_observer4); + subscriptions[4].Disposable = source5.SubscribeSafe(_observer5); + subscriptions[5].Disposable = source6.SubscribeSafe(_observer6); + subscriptions[6].Disposable = source7.SubscribeSafe(_observer7); + subscriptions[7].Disposable = source8.SubscribeSafe(_observer8); + subscriptions[8].Disposable = source9.SubscribeSafe(_observer9); return StableCompositeDisposable.Create(subscriptions); } - protected override TResult GetResult() - { - return _parent._resultSelector(_observer1.Value, _observer2.Value, _observer3.Value, _observer4.Value, _observer5.Value, _observer6.Value, _observer7.Value, _observer8.Value, _observer9.Value); - } + protected override TResult GetResult() => _resultSelector(_observer1.Value, _observer2.Value, _observer3.Value, _observer4.Value, _observer5.Value, _observer6.Value, _observer7.Value, _observer8.Value, _observer9.Value); } } @@ -568,19 +547,19 @@ public CombineLatest(IObservable source1, IObservable source2, IObservab protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - var sink = new _(this, observer, cancel); + var sink = new _(_resultSelector, observer, cancel); setSink(sink); - return sink.Run(); + return sink.Run(_source1, _source2, _source3, _source4, _source5, _source6, _source7, _source8, _source9, _source10); } - class _ : CombineLatestSink + private sealed class _ : CombineLatestSink { - private readonly CombineLatest _parent; + private readonly Func _resultSelector; - public _(CombineLatest parent, IObserver observer, IDisposable cancel) + public _(Func resultSelector, IObserver observer, IDisposable cancel) : base(10, observer, cancel) { - _parent = parent; + _resultSelector = resultSelector; } private CombineLatestObserver _observer1; @@ -594,7 +573,7 @@ public _(CombineLatest parent, private CombineLatestObserver _observer9; private CombineLatestObserver _observer10; - public IDisposable Run() + public IDisposable Run(IObservable source1, IObservable source2, IObservable source3, IObservable source4, IObservable source5, IObservable source6, IObservable source7, IObservable source8, IObservable source9, IObservable source10) { var subscriptions = new SingleAssignmentDisposable[10]; for (int i = 0; i < 10; i++) @@ -610,25 +589,22 @@ public IDisposable Run() _observer8 = new CombineLatestObserver(_gate, this, 7, subscriptions[7]); _observer9 = new CombineLatestObserver(_gate, this, 8, subscriptions[8]); _observer10 = new CombineLatestObserver(_gate, this, 9, subscriptions[9]); - - subscriptions[0].Disposable = _parent._source1.SubscribeSafe(_observer1); - subscriptions[1].Disposable = _parent._source2.SubscribeSafe(_observer2); - subscriptions[2].Disposable = _parent._source3.SubscribeSafe(_observer3); - subscriptions[3].Disposable = _parent._source4.SubscribeSafe(_observer4); - subscriptions[4].Disposable = _parent._source5.SubscribeSafe(_observer5); - subscriptions[5].Disposable = _parent._source6.SubscribeSafe(_observer6); - subscriptions[6].Disposable = _parent._source7.SubscribeSafe(_observer7); - subscriptions[7].Disposable = _parent._source8.SubscribeSafe(_observer8); - subscriptions[8].Disposable = _parent._source9.SubscribeSafe(_observer9); - subscriptions[9].Disposable = _parent._source10.SubscribeSafe(_observer10); + + subscriptions[0].Disposable = source1.SubscribeSafe(_observer1); + subscriptions[1].Disposable = source2.SubscribeSafe(_observer2); + subscriptions[2].Disposable = source3.SubscribeSafe(_observer3); + subscriptions[3].Disposable = source4.SubscribeSafe(_observer4); + subscriptions[4].Disposable = source5.SubscribeSafe(_observer5); + subscriptions[5].Disposable = source6.SubscribeSafe(_observer6); + subscriptions[6].Disposable = source7.SubscribeSafe(_observer7); + subscriptions[7].Disposable = source8.SubscribeSafe(_observer8); + subscriptions[8].Disposable = source9.SubscribeSafe(_observer9); + subscriptions[9].Disposable = source10.SubscribeSafe(_observer10); return StableCompositeDisposable.Create(subscriptions); } - protected override TResult GetResult() - { - return _parent._resultSelector(_observer1.Value, _observer2.Value, _observer3.Value, _observer4.Value, _observer5.Value, _observer6.Value, _observer7.Value, _observer8.Value, _observer9.Value, _observer10.Value); - } + protected override TResult GetResult() => _resultSelector(_observer1.Value, _observer2.Value, _observer3.Value, _observer4.Value, _observer5.Value, _observer6.Value, _observer7.Value, _observer8.Value, _observer9.Value, _observer10.Value); } } @@ -665,19 +641,19 @@ public CombineLatest(IObservable source1, IObservable source2, IObservab protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - var sink = new _(this, observer, cancel); + var sink = new _(_resultSelector, observer, cancel); setSink(sink); - return sink.Run(); + return sink.Run(_source1, _source2, _source3, _source4, _source5, _source6, _source7, _source8, _source9, _source10, _source11); } - class _ : CombineLatestSink + private sealed class _ : CombineLatestSink { - private readonly CombineLatest _parent; + private readonly Func _resultSelector; - public _(CombineLatest parent, IObserver observer, IDisposable cancel) + public _(Func resultSelector, IObserver observer, IDisposable cancel) : base(11, observer, cancel) { - _parent = parent; + _resultSelector = resultSelector; } private CombineLatestObserver _observer1; @@ -692,7 +668,7 @@ public _(CombineLatest pa private CombineLatestObserver _observer10; private CombineLatestObserver _observer11; - public IDisposable Run() + public IDisposable Run(IObservable source1, IObservable source2, IObservable source3, IObservable source4, IObservable source5, IObservable source6, IObservable source7, IObservable source8, IObservable source9, IObservable source10, IObservable source11) { var subscriptions = new SingleAssignmentDisposable[11]; for (int i = 0; i < 11; i++) @@ -709,26 +685,23 @@ public IDisposable Run() _observer9 = new CombineLatestObserver(_gate, this, 8, subscriptions[8]); _observer10 = new CombineLatestObserver(_gate, this, 9, subscriptions[9]); _observer11 = new CombineLatestObserver(_gate, this, 10, subscriptions[10]); - - subscriptions[0].Disposable = _parent._source1.SubscribeSafe(_observer1); - subscriptions[1].Disposable = _parent._source2.SubscribeSafe(_observer2); - subscriptions[2].Disposable = _parent._source3.SubscribeSafe(_observer3); - subscriptions[3].Disposable = _parent._source4.SubscribeSafe(_observer4); - subscriptions[4].Disposable = _parent._source5.SubscribeSafe(_observer5); - subscriptions[5].Disposable = _parent._source6.SubscribeSafe(_observer6); - subscriptions[6].Disposable = _parent._source7.SubscribeSafe(_observer7); - subscriptions[7].Disposable = _parent._source8.SubscribeSafe(_observer8); - subscriptions[8].Disposable = _parent._source9.SubscribeSafe(_observer9); - subscriptions[9].Disposable = _parent._source10.SubscribeSafe(_observer10); - subscriptions[10].Disposable = _parent._source11.SubscribeSafe(_observer11); + + subscriptions[0].Disposable = source1.SubscribeSafe(_observer1); + subscriptions[1].Disposable = source2.SubscribeSafe(_observer2); + subscriptions[2].Disposable = source3.SubscribeSafe(_observer3); + subscriptions[3].Disposable = source4.SubscribeSafe(_observer4); + subscriptions[4].Disposable = source5.SubscribeSafe(_observer5); + subscriptions[5].Disposable = source6.SubscribeSafe(_observer6); + subscriptions[6].Disposable = source7.SubscribeSafe(_observer7); + subscriptions[7].Disposable = source8.SubscribeSafe(_observer8); + subscriptions[8].Disposable = source9.SubscribeSafe(_observer9); + subscriptions[9].Disposable = source10.SubscribeSafe(_observer10); + subscriptions[10].Disposable = source11.SubscribeSafe(_observer11); return StableCompositeDisposable.Create(subscriptions); } - protected override TResult GetResult() - { - return _parent._resultSelector(_observer1.Value, _observer2.Value, _observer3.Value, _observer4.Value, _observer5.Value, _observer6.Value, _observer7.Value, _observer8.Value, _observer9.Value, _observer10.Value, _observer11.Value); - } + protected override TResult GetResult() => _resultSelector(_observer1.Value, _observer2.Value, _observer3.Value, _observer4.Value, _observer5.Value, _observer6.Value, _observer7.Value, _observer8.Value, _observer9.Value, _observer10.Value, _observer11.Value); } } @@ -767,19 +740,19 @@ public CombineLatest(IObservable source1, IObservable source2, IObservab protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - var sink = new _(this, observer, cancel); + var sink = new _(_resultSelector, observer, cancel); setSink(sink); - return sink.Run(); + return sink.Run(_source1, _source2, _source3, _source4, _source5, _source6, _source7, _source8, _source9, _source10, _source11, _source12); } - class _ : CombineLatestSink + private sealed class _ : CombineLatestSink { - private readonly CombineLatest _parent; + private readonly Func _resultSelector; - public _(CombineLatest parent, IObserver observer, IDisposable cancel) + public _(Func resultSelector, IObserver observer, IDisposable cancel) : base(12, observer, cancel) { - _parent = parent; + _resultSelector = resultSelector; } private CombineLatestObserver _observer1; @@ -795,7 +768,7 @@ public _(CombineLatest _observer11; private CombineLatestObserver _observer12; - public IDisposable Run() + public IDisposable Run(IObservable source1, IObservable source2, IObservable source3, IObservable source4, IObservable source5, IObservable source6, IObservable source7, IObservable source8, IObservable source9, IObservable source10, IObservable source11, IObservable source12) { var subscriptions = new SingleAssignmentDisposable[12]; for (int i = 0; i < 12; i++) @@ -813,27 +786,24 @@ public IDisposable Run() _observer10 = new CombineLatestObserver(_gate, this, 9, subscriptions[9]); _observer11 = new CombineLatestObserver(_gate, this, 10, subscriptions[10]); _observer12 = new CombineLatestObserver(_gate, this, 11, subscriptions[11]); - - subscriptions[0].Disposable = _parent._source1.SubscribeSafe(_observer1); - subscriptions[1].Disposable = _parent._source2.SubscribeSafe(_observer2); - subscriptions[2].Disposable = _parent._source3.SubscribeSafe(_observer3); - subscriptions[3].Disposable = _parent._source4.SubscribeSafe(_observer4); - subscriptions[4].Disposable = _parent._source5.SubscribeSafe(_observer5); - subscriptions[5].Disposable = _parent._source6.SubscribeSafe(_observer6); - subscriptions[6].Disposable = _parent._source7.SubscribeSafe(_observer7); - subscriptions[7].Disposable = _parent._source8.SubscribeSafe(_observer8); - subscriptions[8].Disposable = _parent._source9.SubscribeSafe(_observer9); - subscriptions[9].Disposable = _parent._source10.SubscribeSafe(_observer10); - subscriptions[10].Disposable = _parent._source11.SubscribeSafe(_observer11); - subscriptions[11].Disposable = _parent._source12.SubscribeSafe(_observer12); + + subscriptions[0].Disposable = source1.SubscribeSafe(_observer1); + subscriptions[1].Disposable = source2.SubscribeSafe(_observer2); + subscriptions[2].Disposable = source3.SubscribeSafe(_observer3); + subscriptions[3].Disposable = source4.SubscribeSafe(_observer4); + subscriptions[4].Disposable = source5.SubscribeSafe(_observer5); + subscriptions[5].Disposable = source6.SubscribeSafe(_observer6); + subscriptions[6].Disposable = source7.SubscribeSafe(_observer7); + subscriptions[7].Disposable = source8.SubscribeSafe(_observer8); + subscriptions[8].Disposable = source9.SubscribeSafe(_observer9); + subscriptions[9].Disposable = source10.SubscribeSafe(_observer10); + subscriptions[10].Disposable = source11.SubscribeSafe(_observer11); + subscriptions[11].Disposable = source12.SubscribeSafe(_observer12); return StableCompositeDisposable.Create(subscriptions); } - protected override TResult GetResult() - { - return _parent._resultSelector(_observer1.Value, _observer2.Value, _observer3.Value, _observer4.Value, _observer5.Value, _observer6.Value, _observer7.Value, _observer8.Value, _observer9.Value, _observer10.Value, _observer11.Value, _observer12.Value); - } + protected override TResult GetResult() => _resultSelector(_observer1.Value, _observer2.Value, _observer3.Value, _observer4.Value, _observer5.Value, _observer6.Value, _observer7.Value, _observer8.Value, _observer9.Value, _observer10.Value, _observer11.Value, _observer12.Value); } } @@ -874,19 +844,19 @@ public CombineLatest(IObservable source1, IObservable source2, IObservab protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - var sink = new _(this, observer, cancel); + var sink = new _(_resultSelector, observer, cancel); setSink(sink); - return sink.Run(); + return sink.Run(_source1, _source2, _source3, _source4, _source5, _source6, _source7, _source8, _source9, _source10, _source11, _source12, _source13); } - class _ : CombineLatestSink + private sealed class _ : CombineLatestSink { - private readonly CombineLatest _parent; + private readonly Func _resultSelector; - public _(CombineLatest parent, IObserver observer, IDisposable cancel) + public _(Func resultSelector, IObserver observer, IDisposable cancel) : base(13, observer, cancel) { - _parent = parent; + _resultSelector = resultSelector; } private CombineLatestObserver _observer1; @@ -903,7 +873,7 @@ public _(CombineLatest _observer12; private CombineLatestObserver _observer13; - public IDisposable Run() + public IDisposable Run(IObservable source1, IObservable source2, IObservable source3, IObservable source4, IObservable source5, IObservable source6, IObservable source7, IObservable source8, IObservable source9, IObservable source10, IObservable source11, IObservable source12, IObservable source13) { var subscriptions = new SingleAssignmentDisposable[13]; for (int i = 0; i < 13; i++) @@ -922,28 +892,25 @@ public IDisposable Run() _observer11 = new CombineLatestObserver(_gate, this, 10, subscriptions[10]); _observer12 = new CombineLatestObserver(_gate, this, 11, subscriptions[11]); _observer13 = new CombineLatestObserver(_gate, this, 12, subscriptions[12]); - - subscriptions[0].Disposable = _parent._source1.SubscribeSafe(_observer1); - subscriptions[1].Disposable = _parent._source2.SubscribeSafe(_observer2); - subscriptions[2].Disposable = _parent._source3.SubscribeSafe(_observer3); - subscriptions[3].Disposable = _parent._source4.SubscribeSafe(_observer4); - subscriptions[4].Disposable = _parent._source5.SubscribeSafe(_observer5); - subscriptions[5].Disposable = _parent._source6.SubscribeSafe(_observer6); - subscriptions[6].Disposable = _parent._source7.SubscribeSafe(_observer7); - subscriptions[7].Disposable = _parent._source8.SubscribeSafe(_observer8); - subscriptions[8].Disposable = _parent._source9.SubscribeSafe(_observer9); - subscriptions[9].Disposable = _parent._source10.SubscribeSafe(_observer10); - subscriptions[10].Disposable = _parent._source11.SubscribeSafe(_observer11); - subscriptions[11].Disposable = _parent._source12.SubscribeSafe(_observer12); - subscriptions[12].Disposable = _parent._source13.SubscribeSafe(_observer13); + + subscriptions[0].Disposable = source1.SubscribeSafe(_observer1); + subscriptions[1].Disposable = source2.SubscribeSafe(_observer2); + subscriptions[2].Disposable = source3.SubscribeSafe(_observer3); + subscriptions[3].Disposable = source4.SubscribeSafe(_observer4); + subscriptions[4].Disposable = source5.SubscribeSafe(_observer5); + subscriptions[5].Disposable = source6.SubscribeSafe(_observer6); + subscriptions[6].Disposable = source7.SubscribeSafe(_observer7); + subscriptions[7].Disposable = source8.SubscribeSafe(_observer8); + subscriptions[8].Disposable = source9.SubscribeSafe(_observer9); + subscriptions[9].Disposable = source10.SubscribeSafe(_observer10); + subscriptions[10].Disposable = source11.SubscribeSafe(_observer11); + subscriptions[11].Disposable = source12.SubscribeSafe(_observer12); + subscriptions[12].Disposable = source13.SubscribeSafe(_observer13); return StableCompositeDisposable.Create(subscriptions); } - protected override TResult GetResult() - { - return _parent._resultSelector(_observer1.Value, _observer2.Value, _observer3.Value, _observer4.Value, _observer5.Value, _observer6.Value, _observer7.Value, _observer8.Value, _observer9.Value, _observer10.Value, _observer11.Value, _observer12.Value, _observer13.Value); - } + protected override TResult GetResult() => _resultSelector(_observer1.Value, _observer2.Value, _observer3.Value, _observer4.Value, _observer5.Value, _observer6.Value, _observer7.Value, _observer8.Value, _observer9.Value, _observer10.Value, _observer11.Value, _observer12.Value, _observer13.Value); } } @@ -986,19 +953,19 @@ public CombineLatest(IObservable source1, IObservable source2, IObservab protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - var sink = new _(this, observer, cancel); + var sink = new _(_resultSelector, observer, cancel); setSink(sink); - return sink.Run(); + return sink.Run(_source1, _source2, _source3, _source4, _source5, _source6, _source7, _source8, _source9, _source10, _source11, _source12, _source13, _source14); } - class _ : CombineLatestSink + private sealed class _ : CombineLatestSink { - private readonly CombineLatest _parent; + private readonly Func _resultSelector; - public _(CombineLatest parent, IObserver observer, IDisposable cancel) + public _(Func resultSelector, IObserver observer, IDisposable cancel) : base(14, observer, cancel) { - _parent = parent; + _resultSelector = resultSelector; } private CombineLatestObserver _observer1; @@ -1016,7 +983,7 @@ public _(CombineLatest _observer13; private CombineLatestObserver _observer14; - public IDisposable Run() + public IDisposable Run(IObservable source1, IObservable source2, IObservable source3, IObservable source4, IObservable source5, IObservable source6, IObservable source7, IObservable source8, IObservable source9, IObservable source10, IObservable source11, IObservable source12, IObservable source13, IObservable source14) { var subscriptions = new SingleAssignmentDisposable[14]; for (int i = 0; i < 14; i++) @@ -1036,29 +1003,26 @@ public IDisposable Run() _observer12 = new CombineLatestObserver(_gate, this, 11, subscriptions[11]); _observer13 = new CombineLatestObserver(_gate, this, 12, subscriptions[12]); _observer14 = new CombineLatestObserver(_gate, this, 13, subscriptions[13]); - - subscriptions[0].Disposable = _parent._source1.SubscribeSafe(_observer1); - subscriptions[1].Disposable = _parent._source2.SubscribeSafe(_observer2); - subscriptions[2].Disposable = _parent._source3.SubscribeSafe(_observer3); - subscriptions[3].Disposable = _parent._source4.SubscribeSafe(_observer4); - subscriptions[4].Disposable = _parent._source5.SubscribeSafe(_observer5); - subscriptions[5].Disposable = _parent._source6.SubscribeSafe(_observer6); - subscriptions[6].Disposable = _parent._source7.SubscribeSafe(_observer7); - subscriptions[7].Disposable = _parent._source8.SubscribeSafe(_observer8); - subscriptions[8].Disposable = _parent._source9.SubscribeSafe(_observer9); - subscriptions[9].Disposable = _parent._source10.SubscribeSafe(_observer10); - subscriptions[10].Disposable = _parent._source11.SubscribeSafe(_observer11); - subscriptions[11].Disposable = _parent._source12.SubscribeSafe(_observer12); - subscriptions[12].Disposable = _parent._source13.SubscribeSafe(_observer13); - subscriptions[13].Disposable = _parent._source14.SubscribeSafe(_observer14); + + subscriptions[0].Disposable = source1.SubscribeSafe(_observer1); + subscriptions[1].Disposable = source2.SubscribeSafe(_observer2); + subscriptions[2].Disposable = source3.SubscribeSafe(_observer3); + subscriptions[3].Disposable = source4.SubscribeSafe(_observer4); + subscriptions[4].Disposable = source5.SubscribeSafe(_observer5); + subscriptions[5].Disposable = source6.SubscribeSafe(_observer6); + subscriptions[6].Disposable = source7.SubscribeSafe(_observer7); + subscriptions[7].Disposable = source8.SubscribeSafe(_observer8); + subscriptions[8].Disposable = source9.SubscribeSafe(_observer9); + subscriptions[9].Disposable = source10.SubscribeSafe(_observer10); + subscriptions[10].Disposable = source11.SubscribeSafe(_observer11); + subscriptions[11].Disposable = source12.SubscribeSafe(_observer12); + subscriptions[12].Disposable = source13.SubscribeSafe(_observer13); + subscriptions[13].Disposable = source14.SubscribeSafe(_observer14); return StableCompositeDisposable.Create(subscriptions); } - protected override TResult GetResult() - { - return _parent._resultSelector(_observer1.Value, _observer2.Value, _observer3.Value, _observer4.Value, _observer5.Value, _observer6.Value, _observer7.Value, _observer8.Value, _observer9.Value, _observer10.Value, _observer11.Value, _observer12.Value, _observer13.Value, _observer14.Value); - } + protected override TResult GetResult() => _resultSelector(_observer1.Value, _observer2.Value, _observer3.Value, _observer4.Value, _observer5.Value, _observer6.Value, _observer7.Value, _observer8.Value, _observer9.Value, _observer10.Value, _observer11.Value, _observer12.Value, _observer13.Value, _observer14.Value); } } @@ -1103,19 +1067,19 @@ public CombineLatest(IObservable source1, IObservable source2, IObservab protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - var sink = new _(this, observer, cancel); + var sink = new _(_resultSelector, observer, cancel); setSink(sink); - return sink.Run(); + return sink.Run(_source1, _source2, _source3, _source4, _source5, _source6, _source7, _source8, _source9, _source10, _source11, _source12, _source13, _source14, _source15); } - class _ : CombineLatestSink + private sealed class _ : CombineLatestSink { - private readonly CombineLatest _parent; + private readonly Func _resultSelector; - public _(CombineLatest parent, IObserver observer, IDisposable cancel) + public _(Func resultSelector, IObserver observer, IDisposable cancel) : base(15, observer, cancel) { - _parent = parent; + _resultSelector = resultSelector; } private CombineLatestObserver _observer1; @@ -1134,7 +1098,7 @@ public _(CombineLatest _observer14; private CombineLatestObserver _observer15; - public IDisposable Run() + public IDisposable Run(IObservable source1, IObservable source2, IObservable source3, IObservable source4, IObservable source5, IObservable source6, IObservable source7, IObservable source8, IObservable source9, IObservable source10, IObservable source11, IObservable source12, IObservable source13, IObservable source14, IObservable source15) { var subscriptions = new SingleAssignmentDisposable[15]; for (int i = 0; i < 15; i++) @@ -1155,30 +1119,27 @@ public IDisposable Run() _observer13 = new CombineLatestObserver(_gate, this, 12, subscriptions[12]); _observer14 = new CombineLatestObserver(_gate, this, 13, subscriptions[13]); _observer15 = new CombineLatestObserver(_gate, this, 14, subscriptions[14]); - - subscriptions[0].Disposable = _parent._source1.SubscribeSafe(_observer1); - subscriptions[1].Disposable = _parent._source2.SubscribeSafe(_observer2); - subscriptions[2].Disposable = _parent._source3.SubscribeSafe(_observer3); - subscriptions[3].Disposable = _parent._source4.SubscribeSafe(_observer4); - subscriptions[4].Disposable = _parent._source5.SubscribeSafe(_observer5); - subscriptions[5].Disposable = _parent._source6.SubscribeSafe(_observer6); - subscriptions[6].Disposable = _parent._source7.SubscribeSafe(_observer7); - subscriptions[7].Disposable = _parent._source8.SubscribeSafe(_observer8); - subscriptions[8].Disposable = _parent._source9.SubscribeSafe(_observer9); - subscriptions[9].Disposable = _parent._source10.SubscribeSafe(_observer10); - subscriptions[10].Disposable = _parent._source11.SubscribeSafe(_observer11); - subscriptions[11].Disposable = _parent._source12.SubscribeSafe(_observer12); - subscriptions[12].Disposable = _parent._source13.SubscribeSafe(_observer13); - subscriptions[13].Disposable = _parent._source14.SubscribeSafe(_observer14); - subscriptions[14].Disposable = _parent._source15.SubscribeSafe(_observer15); + + subscriptions[0].Disposable = source1.SubscribeSafe(_observer1); + subscriptions[1].Disposable = source2.SubscribeSafe(_observer2); + subscriptions[2].Disposable = source3.SubscribeSafe(_observer3); + subscriptions[3].Disposable = source4.SubscribeSafe(_observer4); + subscriptions[4].Disposable = source5.SubscribeSafe(_observer5); + subscriptions[5].Disposable = source6.SubscribeSafe(_observer6); + subscriptions[6].Disposable = source7.SubscribeSafe(_observer7); + subscriptions[7].Disposable = source8.SubscribeSafe(_observer8); + subscriptions[8].Disposable = source9.SubscribeSafe(_observer9); + subscriptions[9].Disposable = source10.SubscribeSafe(_observer10); + subscriptions[10].Disposable = source11.SubscribeSafe(_observer11); + subscriptions[11].Disposable = source12.SubscribeSafe(_observer12); + subscriptions[12].Disposable = source13.SubscribeSafe(_observer13); + subscriptions[13].Disposable = source14.SubscribeSafe(_observer14); + subscriptions[14].Disposable = source15.SubscribeSafe(_observer15); return StableCompositeDisposable.Create(subscriptions); } - protected override TResult GetResult() - { - return _parent._resultSelector(_observer1.Value, _observer2.Value, _observer3.Value, _observer4.Value, _observer5.Value, _observer6.Value, _observer7.Value, _observer8.Value, _observer9.Value, _observer10.Value, _observer11.Value, _observer12.Value, _observer13.Value, _observer14.Value, _observer15.Value); - } + protected override TResult GetResult() => _resultSelector(_observer1.Value, _observer2.Value, _observer3.Value, _observer4.Value, _observer5.Value, _observer6.Value, _observer7.Value, _observer8.Value, _observer9.Value, _observer10.Value, _observer11.Value, _observer12.Value, _observer13.Value, _observer14.Value, _observer15.Value); } } @@ -1225,19 +1186,19 @@ public CombineLatest(IObservable source1, IObservable source2, IObservab protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - var sink = new _(this, observer, cancel); + var sink = new _(_resultSelector, observer, cancel); setSink(sink); - return sink.Run(); + return sink.Run(_source1, _source2, _source3, _source4, _source5, _source6, _source7, _source8, _source9, _source10, _source11, _source12, _source13, _source14, _source15, _source16); } - class _ : CombineLatestSink + private sealed class _ : CombineLatestSink { - private readonly CombineLatest _parent; + private readonly Func _resultSelector; - public _(CombineLatest parent, IObserver observer, IDisposable cancel) + public _(Func resultSelector, IObserver observer, IDisposable cancel) : base(16, observer, cancel) { - _parent = parent; + _resultSelector = resultSelector; } private CombineLatestObserver _observer1; @@ -1257,7 +1218,7 @@ public _(CombineLatest _observer15; private CombineLatestObserver _observer16; - public IDisposable Run() + public IDisposable Run(IObservable source1, IObservable source2, IObservable source3, IObservable source4, IObservable source5, IObservable source6, IObservable source7, IObservable source8, IObservable source9, IObservable source10, IObservable source11, IObservable source12, IObservable source13, IObservable source14, IObservable source15, IObservable source16) { var subscriptions = new SingleAssignmentDisposable[16]; for (int i = 0; i < 16; i++) @@ -1279,31 +1240,28 @@ public IDisposable Run() _observer14 = new CombineLatestObserver(_gate, this, 13, subscriptions[13]); _observer15 = new CombineLatestObserver(_gate, this, 14, subscriptions[14]); _observer16 = new CombineLatestObserver(_gate, this, 15, subscriptions[15]); - - subscriptions[0].Disposable = _parent._source1.SubscribeSafe(_observer1); - subscriptions[1].Disposable = _parent._source2.SubscribeSafe(_observer2); - subscriptions[2].Disposable = _parent._source3.SubscribeSafe(_observer3); - subscriptions[3].Disposable = _parent._source4.SubscribeSafe(_observer4); - subscriptions[4].Disposable = _parent._source5.SubscribeSafe(_observer5); - subscriptions[5].Disposable = _parent._source6.SubscribeSafe(_observer6); - subscriptions[6].Disposable = _parent._source7.SubscribeSafe(_observer7); - subscriptions[7].Disposable = _parent._source8.SubscribeSafe(_observer8); - subscriptions[8].Disposable = _parent._source9.SubscribeSafe(_observer9); - subscriptions[9].Disposable = _parent._source10.SubscribeSafe(_observer10); - subscriptions[10].Disposable = _parent._source11.SubscribeSafe(_observer11); - subscriptions[11].Disposable = _parent._source12.SubscribeSafe(_observer12); - subscriptions[12].Disposable = _parent._source13.SubscribeSafe(_observer13); - subscriptions[13].Disposable = _parent._source14.SubscribeSafe(_observer14); - subscriptions[14].Disposable = _parent._source15.SubscribeSafe(_observer15); - subscriptions[15].Disposable = _parent._source16.SubscribeSafe(_observer16); + + subscriptions[0].Disposable = source1.SubscribeSafe(_observer1); + subscriptions[1].Disposable = source2.SubscribeSafe(_observer2); + subscriptions[2].Disposable = source3.SubscribeSafe(_observer3); + subscriptions[3].Disposable = source4.SubscribeSafe(_observer4); + subscriptions[4].Disposable = source5.SubscribeSafe(_observer5); + subscriptions[5].Disposable = source6.SubscribeSafe(_observer6); + subscriptions[6].Disposable = source7.SubscribeSafe(_observer7); + subscriptions[7].Disposable = source8.SubscribeSafe(_observer8); + subscriptions[8].Disposable = source9.SubscribeSafe(_observer9); + subscriptions[9].Disposable = source10.SubscribeSafe(_observer10); + subscriptions[10].Disposable = source11.SubscribeSafe(_observer11); + subscriptions[11].Disposable = source12.SubscribeSafe(_observer12); + subscriptions[12].Disposable = source13.SubscribeSafe(_observer13); + subscriptions[13].Disposable = source14.SubscribeSafe(_observer14); + subscriptions[14].Disposable = source15.SubscribeSafe(_observer15); + subscriptions[15].Disposable = source16.SubscribeSafe(_observer16); return StableCompositeDisposable.Create(subscriptions); } - protected override TResult GetResult() - { - return _parent._resultSelector(_observer1.Value, _observer2.Value, _observer3.Value, _observer4.Value, _observer5.Value, _observer6.Value, _observer7.Value, _observer8.Value, _observer9.Value, _observer10.Value, _observer11.Value, _observer12.Value, _observer13.Value, _observer14.Value, _observer15.Value, _observer16.Value); - } + protected override TResult GetResult() => _resultSelector(_observer1.Value, _observer2.Value, _observer3.Value, _observer4.Value, _observer5.Value, _observer6.Value, _observer7.Value, _observer8.Value, _observer9.Value, _observer10.Value, _observer11.Value, _observer12.Value, _observer13.Value, _observer14.Value, _observer15.Value, _observer16.Value); } } diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/CombineLatest.Generated.tt b/Rx.NET/Source/src/System.Reactive/Linq/Observable/CombineLatest.Generated.tt index 73bcaa64ec..edf0dcb68a 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/CombineLatest.Generated.tt +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/CombineLatest.Generated.tt @@ -24,6 +24,7 @@ for (var i = 3; i <= 16; i++) var ts = string.Join(", ", Enumerable.Range(1, i).Select(j => "T" + j)); var os = string.Join(", ", Enumerable.Range(1, i).Select(j => "IObservable source" + j)); var vs = string.Join(", ", Enumerable.Range(1, i).Select(j => "_observer" + j + ".Value")); + var ss = string.Join(", ", Enumerable.Range(1, i).Select(j => "_source" + j)); #> internal sealed class CombineLatest<<#=ts#>, TResult> : Producer { @@ -52,19 +53,19 @@ for (var j = 1; j <= i; j++) protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - var sink = new _(this, observer, cancel); + var sink = new _(_resultSelector, observer, cancel); setSink(sink); - return sink.Run(); + return sink.Run(<#=ss#>); } - class _ : CombineLatestSink + private sealed class _ : CombineLatestSink { - private readonly CombineLatest<<#=ts#>, TResult> _parent; + private readonly Func<<#=ts#>, TResult> _resultSelector; - public _(CombineLatest<<#=ts#>, TResult> parent, IObserver observer, IDisposable cancel) + public _(Func<<#=ts#>, TResult> resultSelector, IObserver observer, IDisposable cancel) : base(<#=i#>, observer, cancel) { - _parent = parent; + _resultSelector = resultSelector; } <# @@ -76,7 +77,7 @@ for (var j = 1; j <= i; j++) } #> - public IDisposable Run() + public IDisposable Run(<#=os#>) { var subscriptions = new SingleAssignmentDisposable[<#=i#>]; for (int i = 0; i < <#=i#>; i++) @@ -90,12 +91,12 @@ for (var j = 1; j <= i; j++) <# } #> - + <# for (var j = 1; j <= i; j++) { #> - subscriptions[<#=j - 1#>].Disposable = _parent._source<#=j#>.SubscribeSafe(_observer<#=j#>); + subscriptions[<#=j - 1#>].Disposable = source<#=j#>.SubscribeSafe(_observer<#=j#>); <# } #> @@ -103,10 +104,7 @@ for (var j = 1; j <= i; j++) return StableCompositeDisposable.Create(subscriptions); } - protected override TResult GetResult() - { - return _parent._resultSelector(<#=vs#>); - } + protected override TResult GetResult() => _resultSelector(<#=vs#>); } } diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/CombineLatest.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/CombineLatest.cs index b1668cd492..50b08761d7 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/CombineLatest.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/CombineLatest.cs @@ -26,55 +26,55 @@ public CombineLatest(IObservable first, IObservable second, Fun protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - var sink = new _(this, observer, cancel); + var sink = new _(_resultSelector, observer, cancel); setSink(sink); - return sink.Run(); + return sink.Run(_first, _second); } - class _ : Sink + private sealed class _ : Sink { - private readonly CombineLatest _parent; + private readonly Func _resultSelector; - public _(CombineLatest parent, IObserver observer, IDisposable cancel) + public _(Func resultSelector, IObserver observer, IDisposable cancel) : base(observer, cancel) { - _parent = parent; + _resultSelector = resultSelector; } private object _gate; - public IDisposable Run() + public IDisposable Run(IObservable first, IObservable second) { _gate = new object(); var fstSubscription = new SingleAssignmentDisposable(); var sndSubscription = new SingleAssignmentDisposable(); - var fstO = new F(this, fstSubscription); - var sndO = new S(this, sndSubscription); + var fstO = new FirstObserver(this, fstSubscription); + var sndO = new SecondObserver(this, sndSubscription); fstO.Other = sndO; sndO.Other = fstO; - fstSubscription.Disposable = _parent._first.SubscribeSafe(fstO); - sndSubscription.Disposable = _parent._second.SubscribeSafe(sndO); + fstSubscription.Disposable = first.SubscribeSafe(fstO); + sndSubscription.Disposable = second.SubscribeSafe(sndO); return StableCompositeDisposable.Create(fstSubscription, sndSubscription); } - class F : IObserver + private sealed class FirstObserver : IObserver { private readonly _ _parent; private readonly IDisposable _self; - private S _other; + private SecondObserver _other; - public F(_ parent, IDisposable self) + public FirstObserver(_ parent, IDisposable self) { _parent = parent; _self = self; } - public S Other { set { _other = value; } } + public SecondObserver Other { set { _other = value; } } public bool HasValue { get; private set; } public TFirst Value { get; private set; } @@ -92,7 +92,7 @@ public void OnNext(TFirst value) var res = default(TResult); try { - res = _parent._parent._resultSelector(value, _other.Value); + res = _parent._resultSelector(value, _other.Value); } catch (Exception ex) { @@ -141,19 +141,19 @@ public void OnCompleted() } } - class S : IObserver + private sealed class SecondObserver : IObserver { private readonly _ _parent; private readonly IDisposable _self; - private F _other; + private FirstObserver _other; - public S(_ parent, IDisposable self) + public SecondObserver(_ parent, IDisposable self) { _parent = parent; _self = self; } - public F Other { set { _other = value; } } + public FirstObserver Other { set { _other = value; } } public bool HasValue { get; private set; } public TSecond Value { get; private set; } @@ -171,7 +171,7 @@ public void OnNext(TSecond value) var res = default(TResult); try { - res = _parent._parent._resultSelector(_other.Value, value); + res = _parent._resultSelector(_other.Value, value); } catch (Exception ex) { @@ -228,14 +228,14 @@ public void OnCompleted() #region Helpers for n-ary overloads - interface ICombineLatest + internal interface ICombineLatest { void Next(int index); void Fail(Exception error); void Done(int index); } - abstract class CombineLatestSink : Sink, ICombineLatest + internal abstract class CombineLatestSink : Sink, ICombineLatest { protected readonly object _gate; @@ -354,10 +354,7 @@ public CombineLatestObserver(object gate, ICombineLatest parent, int index, IDis _self = self; } - public T Value - { - get { return _value; } - } + public T Value => _value; public void OnNext(T value) { @@ -408,19 +405,19 @@ public CombineLatest(IEnumerable> sources, Func observer, IDisposable cancel, Action setSink) { - var sink = new _(this, observer, cancel); + var sink = new _(_resultSelector, observer, cancel); setSink(sink); - return sink.Run(); + return sink.Run(_sources); } - class _ : Sink + private sealed class _ : Sink { - private readonly CombineLatest _parent; + private readonly Func, TResult> _resultSelector; - public _(CombineLatest parent, IObserver observer, IDisposable cancel) + public _(Func, TResult> resultSelector, IObserver observer, IDisposable cancel) : base(observer, cancel) { - _parent = parent; + _resultSelector = resultSelector; } private object _gate; @@ -430,9 +427,9 @@ public _(CombineLatest parent, IObserver observer, ID private bool[] _isDone; private IDisposable[] _subscriptions; - public IDisposable Run() + public IDisposable Run(IEnumerable> sources) { - var srcs = _parent._sources.ToArray(); + var srcs = sources.ToArray(); var N = srcs.Length; @@ -456,7 +453,7 @@ public IDisposable Run() var d = new SingleAssignmentDisposable(); _subscriptions[j] = d; - var o = new O(this, j); + var o = new SourceObserver(this, j); d.Disposable = srcs[j].SubscribeSafe(o); } @@ -471,12 +468,12 @@ private void OnNext(int index, TSource value) _hasValue[index] = true; - if (_hasValueAll || (_hasValueAll = _hasValue.All(Stubs.I))) + if (_hasValueAll || (_hasValueAll = _hasValue.All())) { var res = default(TResult); try { - res = _parent._resultSelector(new ReadOnlyCollection(_values)); + res = _resultSelector(new ReadOnlyCollection(_values)); } catch (Exception ex) { @@ -487,7 +484,7 @@ private void OnNext(int index, TSource value) _observer.OnNext(res); } - else if (_isDone.Where((x, i) => i != index).All(Stubs.I)) + else if (_isDone.AllExcept(index)) { base._observer.OnCompleted(); base.Dispose(); @@ -511,7 +508,7 @@ private void OnCompleted(int index) { _isDone[index] = true; - if (_isDone.All(Stubs.I)) + if (_isDone.All()) { base._observer.OnCompleted(); base.Dispose(); @@ -524,12 +521,41 @@ private void OnCompleted(int index) } } - class O : IObserver + private static bool All(bool[] values) + { + foreach (var value in values) + { + if (!value) + { + return false; + } + } + + return true; + } + + private static bool AllExcept(bool[] values, int index) + { + for (var i = 0; i < values.Length; i++) + { + if (i != index) + { + if (!values[i]) + { + return false; + } + } + } + + return true; + } + + private sealed class SourceObserver : IObserver { private readonly _ _parent; private readonly int _index; - public O(_ parent, int index) + public SourceObserver(_ parent, int index) { _parent = parent; _index = index; diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Concat.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Concat.cs index b80b19f12e..018fab1639 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Concat.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Concat.cs @@ -22,12 +22,9 @@ protected override IDisposable Run(IObserver observer, IDisposable canc return sink.Run(_sources); } - public IEnumerable> GetSources() - { - return _sources; - } + public IEnumerable> GetSources() => _sources; - class _ : ConcatSink + private sealed class _ : ConcatSink { public _(IObserver observer, IDisposable cancel) : base(observer, cancel) diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Contains.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Contains.cs index 70fb40d0a3..824089efdb 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Contains.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Contains.cs @@ -26,14 +26,16 @@ protected override IDisposable Run(IObserver observer, IDisposable cancel, return _source.SubscribeSafe(sink); } - class _ : Sink, IObserver + private sealed class _ : Sink, IObserver { - private readonly Contains _parent; + private readonly TSource _value; + private readonly IEqualityComparer _comparer; public _(Contains parent, IObserver observer, IDisposable cancel) : base(observer, cancel) { - _parent = parent; + _value = parent._value; + _comparer = parent._comparer; } public void OnNext(TSource value) @@ -41,7 +43,7 @@ public void OnNext(TSource value) var res = false; try { - res = _parent._comparer.Equals(value, _parent._value); + res = _comparer.Equals(value, _value); } catch (Exception ex) { diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Count.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Count.cs index c3865e0a55..d8927dfcb2 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Count.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Count.cs @@ -4,118 +4,126 @@ namespace System.Reactive.Linq.ObservableImpl { - internal sealed class Count : Producer + internal static class Count { - private readonly IObservable _source; - private readonly Func _predicate; - - public Count(IObservable source) + internal sealed class All : Producer { - _source = source; - } + private readonly IObservable _source; - public Count(IObservable source, Func predicate) - { - _source = source; - _predicate = predicate; - } - - protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) - { - if (_predicate == null) + public All(IObservable source) { - var sink = new _(observer, cancel); - setSink(sink); - return _source.SubscribeSafe(sink); + _source = source; } - else + + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - var sink = new CountImpl(this, observer, cancel); + var sink = new _(observer, cancel); setSink(sink); return _source.SubscribeSafe(sink); } - } - - class _ : Sink, IObserver - { - private int _count; - public _(IObserver observer, IDisposable cancel) - : base(observer, cancel) + private sealed class _ : Sink, IObserver { - _count = 0; - } + private int _count; - public void OnNext(TSource value) - { - try + public _(IObserver observer, IDisposable cancel) + : base(observer, cancel) { - checked + _count = 0; + } + + public void OnNext(TSource value) + { + try { - _count++; + checked + { + _count++; + } + } + catch (Exception ex) + { + base._observer.OnError(ex); + base.Dispose(); } } - catch (Exception ex) + + public void OnError(Exception error) { - base._observer.OnError(ex); + base._observer.OnError(error); base.Dispose(); } - } - - public void OnError(Exception error) - { - base._observer.OnError(error); - base.Dispose(); - } - public void OnCompleted() - { - base._observer.OnNext(_count); - base._observer.OnCompleted(); - base.Dispose(); + public void OnCompleted() + { + base._observer.OnNext(_count); + base._observer.OnCompleted(); + base.Dispose(); + } } } - class CountImpl : Sink, IObserver + internal sealed class Predicate : Producer { - private readonly Count _parent; - private int _count; + private readonly IObservable _source; + private readonly Func _predicate; - public CountImpl(Count parent, IObserver observer, IDisposable cancel) - : base(observer, cancel) + public Predicate(IObservable source, Func predicate) { - _parent = parent; - _count = 0; + _source = source; + _predicate = predicate; } - public void OnNext(TSource value) + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - try + var sink = new _(_predicate, observer, cancel); + setSink(sink); + return _source.SubscribeSafe(sink); + } + + private sealed class _ : Sink, IObserver + { + private readonly Func _predicate; + private int _count; + + public _(Func predicate, IObserver observer, IDisposable cancel) + : base(observer, cancel) + { + _predicate = predicate; + _count = 0; + } + + public void OnNext(TSource value) { - checked + try { - if (_parent._predicate(value)) - _count++; + checked + { + if (_predicate(value)) + { + _count++; + } + } + } + catch (Exception ex) + { + base._observer.OnError(ex); + base.Dispose(); } } - catch (Exception ex) + + public void OnError(Exception error) { - base._observer.OnError(ex); + base._observer.OnError(error); base.Dispose(); } - } - public void OnError(Exception error) - { - base._observer.OnError(error); - base.Dispose(); - } - - public void OnCompleted() - { - base._observer.OnNext(_count); - base._observer.OnCompleted(); - base.Dispose(); + public void OnCompleted() + { + base._observer.OnNext(_count); + base._observer.OnCompleted(); + base.Dispose(); + } } } } diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/DefaultIfEmpty.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/DefaultIfEmpty.cs index 92d8d27e03..4a1473a20a 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/DefaultIfEmpty.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/DefaultIfEmpty.cs @@ -17,20 +17,20 @@ public DefaultIfEmpty(IObservable source, TSource defaultValue) protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - var sink = new _(this, observer, cancel); + var sink = new _(_defaultValue, observer, cancel); setSink(sink); return _source.SubscribeSafe(sink); } - class _ : Sink, IObserver + private sealed class _ : Sink, IObserver { - private readonly DefaultIfEmpty _parent; + private readonly TSource _defaultValue; private bool _found; - public _(DefaultIfEmpty parent, IObserver observer, IDisposable cancel) + public _(TSource defaultValue, IObserver observer, IDisposable cancel) : base(observer, cancel) { - _parent = parent; + _defaultValue = defaultValue; _found = false; } @@ -49,7 +49,7 @@ public void OnError(Exception error) public void OnCompleted() { if (!_found) - base._observer.OnNext(_parent._defaultValue); + base._observer.OnNext(_defaultValue); base._observer.OnCompleted(); base.Dispose(); } diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Defer.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Defer.cs index c53ab6e317..87ba5932cd 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Defer.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Defer.cs @@ -17,24 +17,21 @@ public Defer(Func> observableFactory) protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - var sink = new _(this, observer, cancel); + var sink = new _(_observableFactory, observer, cancel); setSink(sink); return sink.Run(); } - public IObservable Eval() - { - return _observableFactory(); - } + public IObservable Eval() => _observableFactory(); - class _ : Sink, IObserver + private sealed class _ : Sink, IObserver { - private readonly Defer _parent; + private readonly Func> _observableFactory; - public _(Defer parent, IObserver observer, IDisposable cancel) + public _(Func> observableFactory, IObserver observer, IDisposable cancel) : base(observer, cancel) { - _parent = parent; + _observableFactory = observableFactory; } public IDisposable Run() @@ -42,7 +39,7 @@ public IDisposable Run() var result = default(IObservable); try { - result = _parent.Eval(); + result = _observableFactory(); } catch (Exception exception) { diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Delay.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Delay.cs index 41befff837..306a7a460b 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Delay.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Delay.cs @@ -9,720 +9,817 @@ namespace System.Reactive.Linq.ObservableImpl { - internal sealed class Delay : Producer + internal static class Delay { - private readonly IObservable _source; - private readonly TimeSpan? _dueTimeR; - private readonly DateTimeOffset? _dueTimeA; - private readonly IScheduler _scheduler; - - public Delay(IObservable source, TimeSpan dueTime, IScheduler scheduler) + internal abstract class Base : Producer { - _source = source; - _dueTimeR = dueTime; - _scheduler = scheduler; - } + protected readonly IObservable _source; + protected readonly IScheduler _scheduler; - public Delay(IObservable source, DateTimeOffset dueTime, IScheduler scheduler) - { - _source = source; - _dueTimeA = dueTime; - _scheduler = scheduler; - } - - protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) - { - if (_scheduler.AsLongRunning() != null) + public Base(IObservable source, IScheduler scheduler) { - var sink = new LongRunningImpl(this, observer, cancel); - setSink(sink); - return sink.Run(); + _source = source; + _scheduler = scheduler; } - else - { - var sink = new _(this, observer, cancel); - setSink(sink); - return sink.Run(); - } - } - class _ : Sink, IObserver - { - private readonly Delay _parent; - - public _(Delay parent, IObserver observer, IDisposable cancel) - : base(observer, cancel) + protected abstract class _ : Sink, IObserver + where TParent : Base { - _parent = parent; - } + protected readonly object _gate = new object(); + protected readonly SerialDisposable _cancelable = new SerialDisposable(); - private IScheduler _scheduler; - private IDisposable _sourceSubscription; - private SerialDisposable _cancelable; - private TimeSpan _delay; - private IStopwatch _watch; - - private object _gate; - private bool _ready; - private bool _active; - private bool _running; - private Queue> _queue; - private bool _hasCompleted; - private TimeSpan _completeAt; - private bool _hasFailed; - private Exception _exception; - - public IDisposable Run() - { - _scheduler = _parent._scheduler; + protected readonly IScheduler _scheduler; - _cancelable = new SerialDisposable(); + public _(TParent parent, IObserver observer, IDisposable cancel) + : base(observer, cancel) + { + _scheduler = parent._scheduler; + } - _gate = new object(); - _active = false; - _running = false; - _queue = new Queue>(); - _hasCompleted = false; - _completeAt = default(TimeSpan); - _hasFailed = false; - _exception = default(Exception); + private IDisposable _sourceSubscription; - _watch = _scheduler.StartStopwatch(); + protected IStopwatch _watch; + protected TimeSpan _delay; + protected bool _ready; + protected bool _active; + protected bool _running; + protected Queue> _queue = new Queue>(); - if (_parent._dueTimeA.HasValue) - { - _ready = false; + private bool _hasCompleted; + private TimeSpan _completeAt; + private bool _hasFailed; + private Exception _exception; - var dueTimeA = _parent._dueTimeA.Value; - _cancelable.Disposable = _scheduler.Schedule(dueTimeA, Start); - } - else + public IDisposable Run(TParent parent) { - _ready = true; + _active = false; + _running = false; + _queue = new Queue>(); + _hasCompleted = false; + _completeAt = default(TimeSpan); + _hasFailed = false; + _exception = default(Exception); + + _watch = _scheduler.StartStopwatch(); + + RunCore(parent); - var dueTimeR = _parent._dueTimeR.Value; - _delay = Scheduler.Normalize(dueTimeR); + var sourceSubscription = new SingleAssignmentDisposable(); + _sourceSubscription = sourceSubscription; + sourceSubscription.Disposable = parent._source.SubscribeSafe(this); + + return StableCompositeDisposable.Create(_sourceSubscription, _cancelable); } - var sourceSubscription = new SingleAssignmentDisposable(); - _sourceSubscription = sourceSubscription; - sourceSubscription.Disposable = _parent._source.SubscribeSafe(this); + protected abstract void RunCore(TParent parent); - return StableCompositeDisposable.Create(_sourceSubscription, _cancelable); - } + public void OnNext(TSource value) + { + var next = _watch.Elapsed.Add(_delay); + var shouldRun = false; - private void Start() - { - var next = default(TimeSpan); - var shouldRun = false; + lock (_gate) + { + _queue.Enqueue(new System.Reactive.TimeInterval(value, next)); + + shouldRun = _ready && !_active; + _active = true; + } + + if (shouldRun) + { + _cancelable.Disposable = _scheduler.Schedule(_delay, DrainQueue); + } + } - lock (_gate) + public void OnError(Exception error) { - _delay = _watch.Elapsed; + _sourceSubscription.Dispose(); - var oldQueue = _queue; - _queue = new Queue>(); + var shouldRun = false; - if (oldQueue.Count > 0) + lock (_gate) { - next = oldQueue.Peek().Interval; + _queue.Clear(); - while (oldQueue.Count > 0) - { - var item = oldQueue.Dequeue(); - _queue.Enqueue(new Reactive.TimeInterval(item.Value, item.Interval.Add(_delay))); - } + _exception = error; + _hasFailed = true; - shouldRun = true; - _active = true; + shouldRun = !_running; } - _ready = true; + if (shouldRun) + { + base._observer.OnError(error); + base.Dispose(); + } } - if (shouldRun) + public void OnCompleted() { - _cancelable.Disposable = _scheduler.Schedule(next, DrainQueue); - } - } + _sourceSubscription.Dispose(); - public void OnNext(TSource value) - { - var next = _watch.Elapsed.Add(_delay); - var shouldRun = false; + var next = _watch.Elapsed.Add(_delay); + var shouldRun = false; - lock (_gate) - { - _queue.Enqueue(new System.Reactive.TimeInterval(value, next)); + lock (_gate) + { + _completeAt = next; + _hasCompleted = true; + + shouldRun = _ready && !_active; + _active = true; + } - shouldRun = _ready && !_active; - _active = true; + if (shouldRun) + { + _cancelable.Disposable = _scheduler.Schedule(_delay, DrainQueue); + } } - if (shouldRun) + protected void DrainQueue(Action recurse) { - _cancelable.Disposable = _scheduler.Schedule(_delay, DrainQueue); + lock (_gate) + { + if (_hasFailed) + return; + _running = true; + } + + // + // The shouldYield flag was added to address TFS 487881: "Delay can be unfair". In the old + // implementation, the loop below kept running while there was work for immediate dispatch, + // potentially causing a long running work item on the target scheduler. With the addition + // of long-running scheduling in Rx v2.0, we can check whether the scheduler supports this + // interface and perform different processing (see LongRunningImpl). To reduce the code + // churn in the old loop code here, we set the shouldYield flag to true after the first + // dispatch iteration, in order to break from the loop and enter the recursive scheduling path. + // + var shouldYield = false; + + while (true) + { + var hasFailed = false; + var error = default(Exception); + + var hasValue = false; + var value = default(TSource); + var hasCompleted = false; + + var shouldRecurse = false; + var recurseDueTime = default(TimeSpan); + + lock (_gate) + { + if (_hasFailed) + { + error = _exception; + hasFailed = true; + _running = false; + } + else + { + var now = _watch.Elapsed; + + if (_queue.Count > 0) + { + var nextDue = _queue.Peek().Interval; + + if (nextDue.CompareTo(now) <= 0 && !shouldYield) + { + value = _queue.Dequeue().Value; + hasValue = true; + } + else + { + shouldRecurse = true; + recurseDueTime = Scheduler.Normalize(nextDue.Subtract(now)); + _running = false; + } + } + else if (_hasCompleted) + { + if (_completeAt.CompareTo(now) <= 0 && !shouldYield) + { + hasCompleted = true; + } + else + { + shouldRecurse = true; + recurseDueTime = Scheduler.Normalize(_completeAt.Subtract(now)); + _running = false; + } + } + else + { + _running = false; + _active = false; + } + } + } /* lock (_gate) */ + + if (hasValue) + { + base._observer.OnNext(value); + shouldYield = true; + } + else + { + if (hasCompleted) + { + base._observer.OnCompleted(); + base.Dispose(); + } + else if (hasFailed) + { + base._observer.OnError(error); + base.Dispose(); + } + else if (shouldRecurse) + { + recurse(recurseDueTime); + } + + return; + } + } /* while (true) */ } } - public void OnError(Exception error) + protected abstract class L : Sink, IObserver + where TParent : Base { - _sourceSubscription.Dispose(); + protected readonly object _gate = new object(); + protected readonly SerialDisposable _cancelable = new SerialDisposable(); + private readonly SemaphoreSlim _evt = new SemaphoreSlim(0); - var shouldRun = false; + private readonly IScheduler _scheduler; - lock (_gate) + public L(TParent parent, IObserver observer, IDisposable cancel) + : base(observer, cancel) { - _queue.Clear(); + _scheduler = parent._scheduler; + } - _exception = error; - _hasFailed = true; + private IDisposable _sourceSubscription; - shouldRun = !_running; - } + protected IStopwatch _watch; + protected TimeSpan _delay; + protected Queue> _queue; + + private CancellationTokenSource _stop; + private bool _hasCompleted; + private TimeSpan _completeAt; + private bool _hasFailed; + private Exception _exception; - if (shouldRun) + public IDisposable Run(TParent parent) { - base._observer.OnError(error); - base.Dispose(); - } - } + _queue = new Queue>(); + _hasCompleted = false; + _completeAt = default(TimeSpan); + _hasFailed = false; + _exception = default(Exception); - public void OnCompleted() - { - _sourceSubscription.Dispose(); + _watch = _scheduler.StartStopwatch(); - var next = _watch.Elapsed.Add(_delay); - var shouldRun = false; + RunCore(parent); - lock (_gate) - { - _completeAt = next; - _hasCompleted = true; + var sourceSubscription = new SingleAssignmentDisposable(); + _sourceSubscription = sourceSubscription; + sourceSubscription.Disposable = parent._source.SubscribeSafe(this); - shouldRun = _ready && !_active; - _active = true; + return StableCompositeDisposable.Create(_sourceSubscription, _cancelable); } - if (shouldRun) + protected abstract void RunCore(TParent parent); + + protected void ScheduleDrain() { - _cancelable.Disposable = _scheduler.Schedule(_delay, DrainQueue); + _stop = new CancellationTokenSource(); + _cancelable.Disposable = Disposable.Create(_stop.Cancel); + + _scheduler.AsLongRunning().ScheduleLongRunning(DrainQueue); } - } - private void DrainQueue(Action recurse) - { - lock (_gate) + public void OnNext(TSource value) { - if (_hasFailed) - return; - _running = true; - } + var next = _watch.Elapsed.Add(_delay); + + lock (_gate) + { + _queue.Enqueue(new System.Reactive.TimeInterval(value, next)); - // - // The shouldYield flag was added to address TFS 487881: "Delay can be unfair". In the old - // implementation, the loop below kept running while there was work for immediate dispatch, - // potentially causing a long running work item on the target scheduler. With the addition - // of long-running scheduling in Rx v2.0, we can check whether the scheduler supports this - // interface and perform different processing (see LongRunningImpl). To reduce the code - // churn in the old loop code here, we set the shouldYield flag to true after the first - // dispatch iteration, in order to break from the loop and enter the recursive scheduling path. - // - var shouldYield = false; + _evt.Release(); + } + } - while (true) + public void OnError(Exception error) { - var hasFailed = false; - var error = default(Exception); + _sourceSubscription.Dispose(); + + lock (_gate) + { + _queue.Clear(); + + _exception = error; + _hasFailed = true; - var hasValue = false; - var value = default(TSource); - var hasCompleted = false; + _evt.Release(); + } + } + + public void OnCompleted() + { + _sourceSubscription.Dispose(); - var shouldRecurse = false; - var recurseDueTime = default(TimeSpan); + var next = _watch.Elapsed.Add(_delay); lock (_gate) { - if (_hasFailed) + _completeAt = next; + _hasCompleted = true; + + _evt.Release(); + } + } + + private void DrainQueue(ICancelable cancel) + { + while (true) + { + try { - error = _exception; - hasFailed = true; - _running = false; + _evt.Wait(_stop.Token); } - else + catch (OperationCanceledException) { - var now = _watch.Elapsed; + return; + } - if (_queue.Count > 0) + var hasFailed = false; + var error = default(Exception); + + var hasValue = false; + var value = default(TSource); + var hasCompleted = false; + + var shouldWait = false; + var waitTime = default(TimeSpan); + + lock (_gate) + { + if (_hasFailed) { - var nextDue = _queue.Peek().Interval; + error = _exception; + hasFailed = true; + } + else + { + var now = _watch.Elapsed; - if (nextDue.CompareTo(now) <= 0 && !shouldYield) + if (_queue.Count > 0) { - value = _queue.Dequeue().Value; + var next = _queue.Dequeue(); + hasValue = true; + value = next.Value; + + var nextDue = next.Interval; + if (nextDue.CompareTo(now) > 0) + { + shouldWait = true; + waitTime = Scheduler.Normalize(nextDue.Subtract(now)); + } } - else + else if (_hasCompleted) { - shouldRecurse = true; - recurseDueTime = Scheduler.Normalize(nextDue.Subtract(now)); - _running = false; + hasCompleted = true; + + if (_completeAt.CompareTo(now) > 0) + { + shouldWait = true; + waitTime = Scheduler.Normalize(_completeAt.Subtract(now)); + } } } - else if (_hasCompleted) + } /* lock (_gate) */ + + if (shouldWait) + { + var timer = new ManualResetEventSlim(); + _scheduler.Schedule(waitTime, () => { timer.Set(); }); + + try { - if (_completeAt.CompareTo(now) <= 0 && !shouldYield) - { - hasCompleted = true; - } - else - { - shouldRecurse = true; - recurseDueTime = Scheduler.Normalize(_completeAt.Subtract(now)); - _running = false; - } + timer.Wait(_stop.Token); } - else + catch (OperationCanceledException) { - _running = false; - _active = false; + return; } } - } /* lock (_gate) */ - if (hasValue) - { - base._observer.OnNext(value); - shouldYield = true; - } - else - { - if (hasCompleted) + if (hasValue) { - base._observer.OnCompleted(); - base.Dispose(); + base._observer.OnNext(value); } - else if (hasFailed) - { - base._observer.OnError(error); - base.Dispose(); - } - else if (shouldRecurse) + else { - recurse(recurseDueTime); - } + if (hasCompleted) + { + base._observer.OnCompleted(); + base.Dispose(); + } + else if (hasFailed) + { + base._observer.OnError(error); + base.Dispose(); + } - return; + return; + } } - } /* while (true) */ + } } } - class LongRunningImpl : Sink, IObserver + internal sealed class Absolute : Base { - private readonly Delay _parent; + private readonly DateTimeOffset _dueTime; - public LongRunningImpl(Delay parent, IObserver observer, IDisposable cancel) - : base(observer, cancel) + public Absolute(IObservable source, DateTimeOffset dueTime, IScheduler scheduler) + : base(source, scheduler) { - _parent = parent; + _dueTime = dueTime; } - private IDisposable _sourceSubscription; - private SerialDisposable _cancelable; - private TimeSpan _delay; - private IStopwatch _watch; - - private object _gate; - private SemaphoreSlim _evt; - private CancellationTokenSource _stop; - private Queue> _queue; - private bool _hasCompleted; - private TimeSpan _completeAt; - private bool _hasFailed; - private Exception _exception; - - public IDisposable Run() + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - _cancelable = new SerialDisposable(); - - _gate = new object(); - _evt = new SemaphoreSlim(0); - _queue = new Queue>(); - _hasCompleted = false; - _completeAt = default(TimeSpan); - _hasFailed = false; - _exception = default(Exception); - - _watch = _parent._scheduler.StartStopwatch(); - - if (_parent._dueTimeA.HasValue) + if (_scheduler.AsLongRunning() != null) { - var dueTimeA = _parent._dueTimeA.Value; - _cancelable.Disposable = _parent._scheduler.Schedule(dueTimeA, Start); + var sink = new L(this, observer, cancel); + setSink(sink); + return sink.Run(this); } else { - var dueTimeR = _parent._dueTimeR.Value; - _delay = Scheduler.Normalize(dueTimeR); - ScheduleDrain(); + var sink = new _(this, observer, cancel); + setSink(sink); + return sink.Run(this); } - - var sourceSubscription = new SingleAssignmentDisposable(); - _sourceSubscription = sourceSubscription; - sourceSubscription.Disposable = _parent._source.SubscribeSafe(this); - - return StableCompositeDisposable.Create(_sourceSubscription, _cancelable); } - private void Start() + private sealed class _ : _ { - lock (_gate) + public _(Absolute parent, IObserver observer, IDisposable cancel) + : base(parent, observer, cancel) { - _delay = _watch.Elapsed; - - var oldQueue = _queue; - _queue = new Queue>(); - - while (oldQueue.Count > 0) - { - var item = oldQueue.Dequeue(); - _queue.Enqueue(new Reactive.TimeInterval(item.Value, item.Interval.Add(_delay))); - } } - ScheduleDrain(); - } - - private void ScheduleDrain() - { - _stop = new CancellationTokenSource(); - _cancelable.Disposable = Disposable.Create(() => _stop.Cancel()); - - _parent._scheduler.AsLongRunning().ScheduleLongRunning(DrainQueue); - } - - public void OnNext(TSource value) - { - var next = _watch.Elapsed.Add(_delay); - - lock (_gate) + protected override void RunCore(Absolute parent) { - _queue.Enqueue(new System.Reactive.TimeInterval(value, next)); + _ready = false; - _evt.Release(); + _cancelable.Disposable = parent._scheduler.Schedule(parent._dueTime, Start); } - } - public void OnError(Exception error) - { - _sourceSubscription.Dispose(); - - lock (_gate) + private void Start() { - _queue.Clear(); + var next = default(TimeSpan); + var shouldRun = false; - _exception = error; - _hasFailed = true; + lock (_gate) + { + _delay = _watch.Elapsed; - _evt.Release(); - } - } + var oldQueue = _queue; + _queue = new Queue>(); - public void OnCompleted() - { - _sourceSubscription.Dispose(); + if (oldQueue.Count > 0) + { + next = oldQueue.Peek().Interval; - var next = _watch.Elapsed.Add(_delay); + while (oldQueue.Count > 0) + { + var item = oldQueue.Dequeue(); + _queue.Enqueue(new Reactive.TimeInterval(item.Value, item.Interval.Add(_delay))); + } - lock (_gate) - { - _completeAt = next; - _hasCompleted = true; + shouldRun = true; + _active = true; + } - _evt.Release(); + _ready = true; + } + + if (shouldRun) + { + _cancelable.Disposable = _scheduler.Schedule(next, DrainQueue); + } } } - private void DrainQueue(ICancelable cancel) + private sealed class L : L { - while (true) + public L(Absolute parent, IObserver observer, IDisposable cancel) + : base(parent, observer, cancel) { - try - { - _evt.Wait(_stop.Token); - } - catch (OperationCanceledException) - { - return; - } - - var hasFailed = false; - var error = default(Exception); - - var hasValue = false; - var value = default(TSource); - var hasCompleted = false; + } - var shouldWait = false; - var waitTime = default(TimeSpan); + protected override void RunCore(Absolute parent) + { + _cancelable.Disposable = parent._scheduler.Schedule(parent._dueTime, Start); + } + private void Start() + { lock (_gate) { - if (_hasFailed) - { - error = _exception; - hasFailed = true; - } - else - { - var now = _watch.Elapsed; - - if (_queue.Count > 0) - { - var next = _queue.Dequeue(); - - hasValue = true; - value = next.Value; + _delay = _watch.Elapsed; - var nextDue = next.Interval; - if (nextDue.CompareTo(now) > 0) - { - shouldWait = true; - waitTime = Scheduler.Normalize(nextDue.Subtract(now)); - } - } - else if (_hasCompleted) - { - hasCompleted = true; + var oldQueue = _queue; + _queue = new Queue>(); - if (_completeAt.CompareTo(now) > 0) - { - shouldWait = true; - waitTime = Scheduler.Normalize(_completeAt.Subtract(now)); - } - } - } - } /* lock (_gate) */ - - if (shouldWait) - { - var timer = new ManualResetEventSlim(); - _parent._scheduler.Schedule(waitTime, () => { timer.Set(); }); - - try - { - timer.Wait(_stop.Token); - } - catch (OperationCanceledException) + while (oldQueue.Count > 0) { - return; + var item = oldQueue.Dequeue(); + _queue.Enqueue(new Reactive.TimeInterval(item.Value, item.Interval.Add(_delay))); } } - if (hasValue) - { - base._observer.OnNext(value); - } - else - { - if (hasCompleted) - { - base._observer.OnCompleted(); - base.Dispose(); - } - else if (hasFailed) - { - base._observer.OnError(error); - base.Dispose(); - } - - return; - } + ScheduleDrain(); } } } - } - - internal sealed class Delay : Producer - { - private readonly IObservable _source; - private readonly IObservable _subscriptionDelay; - private readonly Func> _delaySelector; - - public Delay(IObservable source, IObservable subscriptionDelay, Func> delaySelector) - { - _source = source; - _subscriptionDelay = subscriptionDelay; - _delaySelector = delaySelector; - } - - protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) - { - var sink = new _(this, observer, cancel); - setSink(sink); - return sink.Run(); - } - class _ : Sink, IObserver + internal sealed class Relative : Base { - private readonly Delay _parent; + private readonly TimeSpan _dueTime; - public _(Delay parent, IObserver observer, IDisposable cancel) - : base(observer, cancel) + public Relative(IObservable source, TimeSpan dueTime, IScheduler scheduler) + : base(source, scheduler) { - _parent = parent; + _dueTime = dueTime; } - private CompositeDisposable _delays; - private object _gate; - private bool _atEnd; - private SerialDisposable _subscription; - - public IDisposable Run() + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - _delays = new CompositeDisposable(); - _gate = new object(); - _atEnd = false; - _subscription = new SerialDisposable(); - - if (_parent._subscriptionDelay == null) + if (_scheduler.AsLongRunning() != null) { - Start(); + var sink = new L(this, observer, cancel); + setSink(sink); + return sink.Run(this); } else { - _subscription.Disposable = _parent._subscriptionDelay.SubscribeSafe(new SubscriptionDelay(this)); + var sink = new _(this, observer, cancel); + setSink(sink); + return sink.Run(this); } - - return StableCompositeDisposable.Create(_subscription, _delays); - } - - private void Start() - { - _subscription.Disposable = _parent._source.SubscribeSafe(this); } - public void OnNext(TSource value) + private sealed class _ : _ { - var delay = default(IObservable); - try + public _(Relative parent, IObserver observer, IDisposable cancel) + : base(parent, observer, cancel) { - delay = _parent._delaySelector(value); } - catch (Exception error) + + protected override void RunCore(Relative parent) { - lock (_gate) - { - base._observer.OnError(error); - base.Dispose(); - } + _ready = true; - return; + _delay = Scheduler.Normalize(parent._dueTime); } - - var d = new SingleAssignmentDisposable(); - _delays.Add(d); - d.Disposable = delay.SubscribeSafe(new Delta(this, value, d)); } - public void OnError(Exception error) + private sealed class L : L { - lock (_gate) + public L(Relative parent, IObserver observer, IDisposable cancel) + : base(parent, observer, cancel) { - base._observer.OnError(error); - base.Dispose(); + } + + protected override void RunCore(Relative parent) + { + _delay = Scheduler.Normalize(parent._dueTime); + ScheduleDrain(); } } + } + } - public void OnCompleted() + internal static class Delay + { + internal class Selector : Producer + { + protected readonly IObservable _source; + private readonly Func> _delaySelector; + + public Selector(IObservable source, Func> delaySelector) { - lock (_gate) - { - _atEnd = true; - _subscription.Dispose(); + _source = source; + _delaySelector = delaySelector; + } - CheckDone(); - } + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) + { + var sink = new _(this, observer, cancel); + setSink(sink); + return sink.Run(this); } - private void CheckDone() + protected class _ : Sink, IObserver + where TParent : Selector { - if (_atEnd && _delays.Count == 0) + private readonly CompositeDisposable _delays = new CompositeDisposable(); + private object _gate = new object(); + + private readonly Func> _delaySelector; + + public _(Selector parent, IObserver observer, IDisposable cancel) + : base(observer, cancel) { - base._observer.OnCompleted(); - base.Dispose(); + _delaySelector = parent._delaySelector; } - } - class SubscriptionDelay : IObserver - { - private readonly _ _parent; + private bool _atEnd; + private IDisposable _subscription; - public SubscriptionDelay(_ parent) + public IDisposable Run(TParent parent) { - _parent = parent; + _atEnd = false; + + _subscription = RunCore(parent); + + return StableCompositeDisposable.Create(_subscription, _delays); } - public void OnNext(TDelay value) + protected virtual IDisposable RunCore(TParent parent) { - _parent.Start(); + return parent._source.SubscribeSafe(this); + } + + public void OnNext(TSource value) + { + var delay = default(IObservable); + try + { + delay = _delaySelector(value); + } + catch (Exception error) + { + lock (_gate) + { + base._observer.OnError(error); + base.Dispose(); + } + + return; + } + + var d = new SingleAssignmentDisposable(); + _delays.Add(d); + d.Disposable = delay.SubscribeSafe(new DelayObserver(this, value, d)); } public void OnError(Exception error) { - _parent._observer.OnError(error); - _parent.Dispose(); + lock (_gate) + { + base._observer.OnError(error); + base.Dispose(); + } } public void OnCompleted() { - _parent.Start(); + lock (_gate) + { + _atEnd = true; + _subscription.Dispose(); + + CheckDone(); + } + } + + private void CheckDone() + { + if (_atEnd && _delays.Count == 0) + { + base._observer.OnCompleted(); + base.Dispose(); + } + } + + private sealed class DelayObserver : IObserver + { + private readonly _ _parent; + private readonly TSource _value; + private readonly IDisposable _self; + + public DelayObserver(_ parent, TSource value, IDisposable self) + { + _parent = parent; + _value = value; + _self = self; + } + + public void OnNext(TDelay value) + { + lock (_parent._gate) + { + _parent._observer.OnNext(_value); + + _parent._delays.Remove(_self); + _parent.CheckDone(); + } + } + + public void OnError(Exception error) + { + lock (_parent._gate) + { + _parent._observer.OnError(error); + _parent.Dispose(); + } + } + + public void OnCompleted() + { + lock (_parent._gate) + { + _parent._observer.OnNext(_value); + + _parent._delays.Remove(_self); + _parent.CheckDone(); + } + } } } + } - class Delta : IObserver + internal sealed class SelectorWithSubscriptionDelay : Selector + { + private readonly IObservable _subscriptionDelay; + + public SelectorWithSubscriptionDelay(IObservable source, IObservable subscriptionDelay, Func> delaySelector) + : base(source, delaySelector) + { + _subscriptionDelay = subscriptionDelay; + } + + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - private readonly _ _parent; - private readonly TSource _value; - private readonly IDisposable _self; + var sink = new _(this, observer, cancel); + setSink(sink); + return sink.Run(this); + } - public Delta(_ parent, TSource value, IDisposable self) + private sealed class _ : _ + { + public _(SelectorWithSubscriptionDelay parent, IObserver observer, IDisposable cancel) + : base(parent, observer, cancel) { - _parent = parent; - _value = value; - _self = self; } - public void OnNext(TDelay value) + protected override IDisposable RunCore(SelectorWithSubscriptionDelay parent) { - lock (_parent._gate) - { - _parent._observer.OnNext(_value); + var subscription = new SerialDisposable(); - _parent._delays.Remove(_self); - _parent.CheckDone(); - } + subscription.Disposable = parent._subscriptionDelay.SubscribeSafe(new SubscriptionDelayObserver(this, parent._source, subscription)); + + return subscription; } - public void OnError(Exception error) + private sealed class SubscriptionDelayObserver : IObserver { - lock (_parent._gate) + private readonly _ _parent; + private readonly IObservable _source; + private readonly SerialDisposable _subscription; + + public SubscriptionDelayObserver(_ parent, IObservable source, SerialDisposable subscription) + { + _parent = parent; + _source = source; + _subscription = subscription; + } + + public void OnNext(TDelay value) + { + _subscription.Disposable = _source.SubscribeSafe(_parent); + } + + public void OnError(Exception error) { _parent._observer.OnError(error); _parent.Dispose(); } - } - public void OnCompleted() - { - lock (_parent._gate) + public void OnCompleted() { - _parent._observer.OnNext(_value); - - _parent._delays.Remove(_self); - _parent.CheckDone(); + _subscription.Disposable = _source.SubscribeSafe(_parent); } } } diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/DelaySubscription.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/DelaySubscription.cs index 2398b88be5..af00c20ff2 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/DelaySubscription.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/DelaySubscription.cs @@ -6,39 +6,50 @@ namespace System.Reactive.Linq.ObservableImpl { - internal sealed class DelaySubscription : Producer + internal abstract class DelaySubscription : Producer { private readonly IObservable _source; - private readonly DateTimeOffset? _dueTimeA; - private readonly TimeSpan? _dueTimeR; private readonly IScheduler _scheduler; - public DelaySubscription(IObservable source, DateTimeOffset dueTime, IScheduler scheduler) + public DelaySubscription(IObservable source, IScheduler scheduler) { _source = source; - _dueTimeA = dueTime; _scheduler = scheduler; } - public DelaySubscription(IObservable source, TimeSpan dueTime, IScheduler scheduler) + internal sealed class Relative : DelaySubscription { - _source = source; - _dueTimeR = dueTime; - _scheduler = scheduler; + private readonly TimeSpan _dueTime; + + public Relative(IObservable source, TimeSpan dueTime, IScheduler scheduler) + : base(source, scheduler) + { + _dueTime = dueTime; + } + + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) + { + var sink = new _(observer, cancel); + setSink(sink); + return _scheduler.Schedule(sink, _dueTime, Subscribe); + } } - protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) + internal sealed class Absolute : DelaySubscription { - var sink = new _(observer, cancel); - setSink(sink); + private readonly DateTimeOffset _dueTime; - if (_dueTimeA.HasValue) + public Absolute(IObservable source, DateTimeOffset dueTime, IScheduler scheduler) + : base(source, scheduler) { - return _scheduler.Schedule(sink, _dueTimeA.Value, Subscribe); + _dueTime = dueTime; } - else + + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - return _scheduler.Schedule(sink, _dueTimeR.Value, Subscribe); + var sink = new _(observer, cancel); + setSink(sink); + return _scheduler.Schedule(sink, _dueTime, Subscribe); } } @@ -47,7 +58,7 @@ private IDisposable Subscribe(IScheduler _, _ sink) return _source.SubscribeSafe(sink); } - class _ : Sink, IObserver + private sealed class _ : Sink, IObserver { public _(IObserver observer, IDisposable cancel) : base(observer, cancel) diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Dematerialize.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Dematerialize.cs index 0bcb6531cf..ebf0e6b6f7 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Dematerialize.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Dematerialize.cs @@ -20,7 +20,7 @@ protected override IDisposable Run(IObserver observer, IDisposable canc return _source.SubscribeSafe(sink); } - class _ : Sink, IObserver> + private sealed class _ : Sink, IObserver> { public _(IObserver observer, IDisposable cancel) : base(observer, cancel) diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Distinct.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Distinct.cs index 1c3ff41eef..392ecb00ca 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Distinct.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Distinct.cs @@ -26,16 +26,16 @@ protected override IDisposable Run(IObserver observer, IDisposable canc return _source.SubscribeSafe(sink); } - class _ : Sink, IObserver + private sealed class _ : Sink, IObserver { - private readonly Distinct _parent; + private readonly Func _keySelector; private HashSet _hashSet; public _(Distinct parent, IObserver observer, IDisposable cancel) : base(observer, cancel) { - _parent = parent; - _hashSet = new HashSet(_parent._comparer); + _keySelector = parent._keySelector; + _hashSet = new HashSet(parent._comparer); } public void OnNext(TSource value) @@ -44,7 +44,7 @@ public void OnNext(TSource value) var hasAdded = false; try { - key = _parent._keySelector(value); + key = _keySelector(value); hasAdded = _hashSet.Add(key); } catch (Exception exception) diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/DistinctUntilChanged.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/DistinctUntilChanged.cs index 85780c5186..a9df10f867 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/DistinctUntilChanged.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/DistinctUntilChanged.cs @@ -26,16 +26,20 @@ protected override IDisposable Run(IObserver observer, IDisposable canc return _source.SubscribeSafe(sink); } - class _ : Sink, IObserver + private sealed class _ : Sink, IObserver { - private readonly DistinctUntilChanged _parent; + private readonly Func _keySelector; + private readonly IEqualityComparer _comparer; + private TKey _currentKey; private bool _hasCurrentKey; public _(DistinctUntilChanged parent, IObserver observer, IDisposable cancel) : base(observer, cancel) { - _parent = parent; + _keySelector = parent._keySelector; + _comparer = parent._comparer; + _currentKey = default(TKey); _hasCurrentKey = false; } @@ -45,7 +49,7 @@ public void OnNext(TSource value) var key = default(TKey); try { - key = _parent._keySelector(value); + key = _keySelector(value); } catch (Exception exception) { @@ -59,7 +63,7 @@ public void OnNext(TSource value) { try { - comparerEquals = _parent._comparer.Equals(_currentKey, key); + comparerEquals = _comparer.Equals(_currentKey, key); } catch (Exception exception) { diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Do.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Do.cs index b7187b5ff5..d73c510bd0 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Do.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Do.cs @@ -4,86 +4,229 @@ namespace System.Reactive.Linq.ObservableImpl { - internal sealed class Do : Producer + internal static class Do { - private readonly IObservable _source; - private readonly Action _onNext; - private readonly Action _onError; - private readonly Action _onCompleted; - - public Do(IObservable source, Action onNext, Action onError, Action onCompleted) - { - _source = source; - _onNext = onNext; - _onError = onError; - _onCompleted = onCompleted; - } - - protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) + internal sealed class OnNext : Producer { - var sink = new _(this, observer, cancel); - setSink(sink); - return _source.SubscribeSafe(sink); - } + private readonly IObservable _source; + private readonly Action _onNext; - class _ : Sink, IObserver - { - private readonly Do _parent; + public OnNext(IObservable source, Action onNext) + { + _source = source; + _onNext = onNext; + } - public _(Do parent, IObserver observer, IDisposable cancel) - : base(observer, cancel) + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - _parent = parent; + var sink = new _(_onNext, observer, cancel); + setSink(sink); + return _source.SubscribeSafe(sink); } - public void OnNext(TSource value) + private sealed class _ : Sink, IObserver { - try + private readonly Action _onNext; + + public _(Action onNext, IObserver observer, IDisposable cancel) + : base(observer, cancel) { - _parent._onNext(value); + _onNext = onNext; } - catch (Exception ex) + + public void OnNext(TSource value) { - base._observer.OnError(ex); + try + { + _onNext(value); + } + catch (Exception ex) + { + base._observer.OnError(ex); + base.Dispose(); + return; + } + + base._observer.OnNext(value); + } + + public void OnError(Exception error) + { + base._observer.OnError(error); base.Dispose(); - return; } - base._observer.OnNext(value); + public void OnCompleted() + { + base._observer.OnCompleted(); + base.Dispose(); + } + } + } + + internal sealed class Observer : Producer + { + private readonly IObservable _source; + private readonly IObserver _observer; + + public Observer(IObservable source, IObserver observer) + { + _source = source; + _observer = observer; + } + + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) + { + var sink = new _(_observer, observer, cancel); + setSink(sink); + return _source.SubscribeSafe(sink); } - public void OnError(Exception error) + private sealed class _ : Sink, IObserver { - try + private readonly IObserver _doObserver; + + public _(IObserver doObserver, IObserver observer, IDisposable cancel) + : base(observer, cancel) + { + _doObserver = doObserver; + } + + public void OnNext(TSource value) { - _parent._onError(error); + try + { + _doObserver.OnNext(value); + } + catch (Exception ex) + { + base._observer.OnError(ex); + base.Dispose(); + return; + } + + base._observer.OnNext(value); } - catch (Exception ex) + + public void OnError(Exception error) { - base._observer.OnError(ex); + try + { + _doObserver.OnError(error); + } + catch (Exception ex) + { + base._observer.OnError(ex); + base.Dispose(); + return; + } + + base._observer.OnError(error); base.Dispose(); - return; } - base._observer.OnError(error); - base.Dispose(); + public void OnCompleted() + { + try + { + _doObserver.OnCompleted(); + } + catch (Exception ex) + { + base._observer.OnError(ex); + base.Dispose(); + return; + } + + base._observer.OnCompleted(); + base.Dispose(); + } } + } + + internal sealed class Actions : Producer + { + private readonly IObservable _source; + private readonly Action _onNext; + private readonly Action _onError; + private readonly Action _onCompleted; - public void OnCompleted() + public Actions(IObservable source, Action onNext, Action onError, Action onCompleted) { - try + _source = source; + _onNext = onNext; + _onError = onError; + _onCompleted = onCompleted; + } + + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) + { + var sink = new _(this, observer, cancel); + setSink(sink); + return _source.SubscribeSafe(sink); + } + + private sealed class _ : Sink, IObserver + { + // CONSIDER: This sink has a parent reference that can be considered for removal. + + private readonly Actions _parent; + + public _(Actions parent, IObserver observer, IDisposable cancel) + : base(observer, cancel) + { + _parent = parent; + } + + public void OnNext(TSource value) { - _parent._onCompleted(); + try + { + _parent._onNext(value); + } + catch (Exception ex) + { + base._observer.OnError(ex); + base.Dispose(); + return; + } + + base._observer.OnNext(value); } - catch (Exception ex) + + public void OnError(Exception error) { - base._observer.OnError(ex); + try + { + _parent._onError(error); + } + catch (Exception ex) + { + base._observer.OnError(ex); + base.Dispose(); + return; + } + + base._observer.OnError(error); base.Dispose(); - return; } - base._observer.OnCompleted(); - base.Dispose(); + public void OnCompleted() + { + try + { + _parent._onCompleted(); + } + catch (Exception ex) + { + base._observer.OnError(ex); + base.Dispose(); + return; + } + + base._observer.OnCompleted(); + base.Dispose(); + } } } } diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/DoWhile.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/DoWhile.cs index 7841a35451..3435d673ba 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/DoWhile.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/DoWhile.cs @@ -31,7 +31,7 @@ public IEnumerable> GetSources() yield return _source; } - class _ : ConcatSink + private sealed class _ : ConcatSink { public _(IObserver observer, IDisposable cancel) : base(observer, cancel) diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/ElementAt.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/ElementAt.cs index f6c5b81c8b..228f3691b4 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/ElementAt.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/ElementAt.cs @@ -8,32 +8,28 @@ internal sealed class ElementAt : Producer { private readonly IObservable _source; private readonly int _index; - private readonly bool _throwOnEmpty; - public ElementAt(IObservable source, int index, bool throwOnEmpty) + public ElementAt(IObservable source, int index) { _source = source; _index = index; - _throwOnEmpty = throwOnEmpty; } protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - var sink = new _(this, observer, cancel); + var sink = new _(_index, observer, cancel); setSink(sink); return _source.SubscribeSafe(sink); } - class _ : Sink, IObserver + private sealed class _ : Sink, IObserver { - private readonly ElementAt _parent; private int _i; - public _(ElementAt parent, IObserver observer, IDisposable cancel) + public _(int index, IObserver observer, IDisposable cancel) : base(observer, cancel) { - _parent = parent; - _i = _parent._index; + _i = index; } public void OnNext(TSource value) @@ -56,16 +52,7 @@ public void OnError(Exception error) public void OnCompleted() { - if (_parent._throwOnEmpty) - { - base._observer.OnError(new ArgumentOutOfRangeException("index")); - } - else - { - base._observer.OnNext(default(TSource)); - base._observer.OnCompleted(); - } - + base._observer.OnError(new ArgumentOutOfRangeException("index")); base.Dispose(); } } diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/ElementAtOrDefault.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/ElementAtOrDefault.cs new file mode 100644 index 0000000000..090ee8ca7f --- /dev/null +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/ElementAtOrDefault.cs @@ -0,0 +1,61 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the Apache 2.0 License. +// See the LICENSE file in the project root for more information. + +namespace System.Reactive.Linq.ObservableImpl +{ + internal sealed class ElementAtOrDefault : Producer + { + private readonly IObservable _source; + private readonly int _index; + + public ElementAtOrDefault(IObservable source, int index) + { + _source = source; + _index = index; + } + + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) + { + var sink = new _(_index, observer, cancel); + setSink(sink); + return _source.SubscribeSafe(sink); + } + + private sealed class _ : Sink, IObserver + { + private int _i; + + public _(int index, IObserver observer, IDisposable cancel) + : base(observer, cancel) + { + _i = index; + } + + public void OnNext(TSource value) + { + if (_i == 0) + { + base._observer.OnNext(value); + base._observer.OnCompleted(); + base.Dispose(); + } + + _i--; + } + + public void OnError(Exception error) + { + base._observer.OnError(error); + base.Dispose(); + } + + public void OnCompleted() + { + base._observer.OnNext(default(TSource)); + base._observer.OnCompleted(); + base.Dispose(); + } + } + } +} diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Empty.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Empty.cs index c01838c747..d3fa379107 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Empty.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Empty.cs @@ -17,24 +17,21 @@ public Empty(IScheduler scheduler) protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - var sink = new _(this, observer, cancel); + var sink = new _(observer, cancel); setSink(sink); - return sink.Run(); + return sink.Run(_scheduler); } - class _ : Sink + private sealed class _ : Sink { - private readonly Empty _parent; - - public _(Empty parent, IObserver observer, IDisposable cancel) + public _(IObserver observer, IDisposable cancel) : base(observer, cancel) { - _parent = parent; } - public IDisposable Run() + public IDisposable Run(IScheduler scheduler) { - return _parent._scheduler.Schedule(Invoke); + return scheduler.Schedule(Invoke); } private void Invoke() diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Finally.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Finally.cs index e3698b1d50..25b7a23c74 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Finally.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Finally.cs @@ -19,24 +19,24 @@ public Finally(IObservable source, Action finallyAction) protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - var sink = new _(this, observer, cancel); + var sink = new _(_finallyAction, observer, cancel); setSink(sink); - return sink.Run(); + return sink.Run(_source); } - class _ : Sink, IObserver + private sealed class _ : Sink, IObserver { - private readonly Finally _parent; + private readonly Action _finallyAction; - public _(Finally parent, IObserver observer, IDisposable cancel) + public _(Action finallyAction, IObserver observer, IDisposable cancel) : base(observer, cancel) { - _parent = parent; + _finallyAction = finallyAction; } - public IDisposable Run() + public IDisposable Run(IObservable source) { - var subscription = _parent._source.SubscribeSafe(this); + var subscription = source.SubscribeSafe(this); return Disposable.Create(() => { @@ -46,7 +46,7 @@ public IDisposable Run() } finally { - _parent._finallyAction(); + _finallyAction(); } }); } diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/FirstAsync.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/FirstAsync.cs index 92d9aaddea..71f5ed95af 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/FirstAsync.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/FirstAsync.cs @@ -4,126 +4,114 @@ namespace System.Reactive.Linq.ObservableImpl { - internal sealed class FirstAsync : Producer + internal static class FirstAsync { - private readonly IObservable _source; - private readonly Func _predicate; - private readonly bool _throwOnEmpty; - - public FirstAsync(IObservable source, Func predicate, bool throwOnEmpty) + internal sealed class Sequence : Producer { - _source = source; - _predicate = predicate; - _throwOnEmpty = throwOnEmpty; - } + private readonly IObservable _source; - protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) - { - if (_predicate != null) + public Sequence(IObservable source) { - var sink = new FirstAsyncImpl(this, observer, cancel); - setSink(sink); - return _source.SubscribeSafe(sink); + _source = source; } - else + + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - var sink = new _(this, observer, cancel); + var sink = new _(observer, cancel); setSink(sink); return _source.SubscribeSafe(sink); } - } - class _ : Sink, IObserver - { - private readonly FirstAsync _parent; - - public _(FirstAsync parent, IObserver observer, IDisposable cancel) - : base(observer, cancel) - { - _parent = parent; - } - - public void OnNext(TSource value) + private sealed class _ : Sink, IObserver { - base._observer.OnNext(value); - base._observer.OnCompleted(); - base.Dispose(); - } - - public void OnError(Exception error) - { - base._observer.OnError(error); - base.Dispose(); - } - - public void OnCompleted() - { - if (_parent._throwOnEmpty) + public _(IObserver observer, IDisposable cancel) + : base(observer, cancel) { - base._observer.OnError(new InvalidOperationException(Strings_Linq.NO_ELEMENTS)); } - else + + public void OnNext(TSource value) { - base._observer.OnNext(default(TSource)); + base._observer.OnNext(value); base._observer.OnCompleted(); + base.Dispose(); } - base.Dispose(); + public void OnError(Exception error) + { + base._observer.OnError(error); + base.Dispose(); + } + + public void OnCompleted() + { + base._observer.OnError(new InvalidOperationException(Strings_Linq.NO_ELEMENTS)); + base.Dispose(); + } } } - class FirstAsyncImpl : Sink, IObserver + internal sealed class Predicate : Producer { - private readonly FirstAsync _parent; + private readonly IObservable _source; + private readonly Func _predicate; + + public Predicate(IObservable source, Func predicate) + { + _source = source; + _predicate = predicate; + } - public FirstAsyncImpl(FirstAsync parent, IObserver observer, IDisposable cancel) - : base(observer, cancel) + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - _parent = parent; + var sink = new _(_predicate, observer, cancel); + setSink(sink); + return _source.SubscribeSafe(sink); } - public void OnNext(TSource value) + private sealed class _ : Sink, IObserver { - var b = false; + private readonly Func _predicate; - try + public _(Func predicate, IObserver observer, IDisposable cancel) + : base(observer, cancel) { - b = _parent._predicate(value); + _predicate = predicate; } - catch (Exception ex) + + public void OnNext(TSource value) { - base._observer.OnError(ex); - base.Dispose(); - return; + var b = false; + + try + { + b = _predicate(value); + } + catch (Exception ex) + { + base._observer.OnError(ex); + base.Dispose(); + return; + } + + if (b) + { + base._observer.OnNext(value); + base._observer.OnCompleted(); + base.Dispose(); + } } - if (b) + public void OnError(Exception error) { - base._observer.OnNext(value); - base._observer.OnCompleted(); + base._observer.OnError(error); base.Dispose(); } - } - - public void OnError(Exception error) - { - base._observer.OnError(error); - base.Dispose(); - } - public void OnCompleted() - { - if (_parent._throwOnEmpty) + public void OnCompleted() { base._observer.OnError(new InvalidOperationException(Strings_Linq.NO_MATCHING_ELEMENTS)); + base.Dispose(); } - else - { - base._observer.OnNext(default(TSource)); - base._observer.OnCompleted(); - } - - base.Dispose(); } } } diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/FirstOrDefaultAsync.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/FirstOrDefaultAsync.cs new file mode 100644 index 0000000000..820045afd8 --- /dev/null +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/FirstOrDefaultAsync.cs @@ -0,0 +1,120 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the Apache 2.0 License. +// See the LICENSE file in the project root for more information. + +namespace System.Reactive.Linq.ObservableImpl +{ + internal static class FirstOrDefaultAsync + { + internal sealed class Sequence : Producer + { + private readonly IObservable _source; + + public Sequence(IObservable source) + { + _source = source; + } + + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) + { + var sink = new _(observer, cancel); + setSink(sink); + return _source.SubscribeSafe(sink); + } + + private sealed class _ : Sink, IObserver + { + public _(IObserver observer, IDisposable cancel) + : base(observer, cancel) + { + } + + public void OnNext(TSource value) + { + base._observer.OnNext(value); + base._observer.OnCompleted(); + base.Dispose(); + } + + public void OnError(Exception error) + { + base._observer.OnError(error); + base.Dispose(); + } + + public void OnCompleted() + { + base._observer.OnNext(default(TSource)); + base._observer.OnCompleted(); + base.Dispose(); + } + } + } + + internal sealed class Predicate : Producer + { + private readonly IObservable _source; + private readonly Func _predicate; + + public Predicate(IObservable source, Func predicate) + { + _source = source; + _predicate = predicate; + } + + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) + { + var sink = new _(_predicate, observer, cancel); + setSink(sink); + return _source.SubscribeSafe(sink); + } + + private sealed class _ : Sink, IObserver + { + private readonly Func _predicate; + + public _(Func predicate, IObserver observer, IDisposable cancel) + : base(observer, cancel) + { + _predicate = predicate; + } + + public void OnNext(TSource value) + { + var b = false; + + try + { + b = _predicate(value); + } + catch (Exception ex) + { + base._observer.OnError(ex); + base.Dispose(); + return; + } + + if (b) + { + base._observer.OnNext(value); + base._observer.OnCompleted(); + base.Dispose(); + } + } + + public void OnError(Exception error) + { + base._observer.OnError(error); + base.Dispose(); + } + + public void OnCompleted() + { + base._observer.OnNext(default(TSource)); + base._observer.OnCompleted(); + base.Dispose(); + } + } + } + } +} diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/For.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/For.cs index 546a52eca2..472efcb565 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/For.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/For.cs @@ -30,7 +30,7 @@ public IEnumerable> GetSources() yield return _resultSelector(item); } - class _ : ConcatSink + private sealed class _ : ConcatSink { public _(IObserver observer, IDisposable cancel) : base(observer, cancel) diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/ForEach.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/ForEach.cs index f2933952f4..18cd3b5a4a 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/ForEach.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/ForEach.cs @@ -8,7 +8,7 @@ namespace System.Reactive.Linq.ObservableImpl { internal sealed class ForEach { - public class _ : IObserver + public sealed class Observer : IObserver { private readonly Action _onNext; private readonly Action _done; @@ -16,7 +16,7 @@ public class _ : IObserver private Exception _exception; private int _stopped; - public _(Action onNext, Action done) + public Observer(Action onNext, Action done) { _onNext = onNext; _done = done; @@ -24,10 +24,7 @@ public _(Action onNext, Action done) _stopped = 0; } - public Exception Error - { - get { return _exception; } - } + public Exception Error => _exception; public void OnNext(TSource value) { @@ -62,7 +59,7 @@ public void OnCompleted() } } - public class ForEachImpl : IObserver + public sealed class ObserverIndexed : IObserver { private readonly Action _onNext; private readonly Action _done; @@ -71,19 +68,16 @@ public class ForEachImpl : IObserver private Exception _exception; private int _stopped; - public ForEachImpl(Action onNext, Action done) + public ObserverIndexed(Action onNext, Action done) { _onNext = onNext; _done = done; - + _index = 0; _stopped = 0; } - public Exception Error - { - get { return _exception; } - } + public Exception Error => _exception; public void OnNext(TSource value) { diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/FromEvent.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/FromEvent.cs index 4499b52450..d6074e4ccc 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/FromEvent.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/FromEvent.cs @@ -190,7 +190,7 @@ protected override TDelegate GetHandler(Action onNext) } } - abstract class EventProducer : Producer + internal abstract class EventProducer : Producer { private readonly IScheduler _scheduler; private readonly object _gate; @@ -229,7 +229,7 @@ protected override IDisposable Run(IObserver observer, IDisposable cancel return connection; } - class Session + private sealed class Session { private readonly EventProducer _parent; private readonly Subject _subject; @@ -346,7 +346,7 @@ private IDisposable AddHandler(IScheduler self, TDelegate onNext) } } - abstract class ClassicEventProducer : EventProducer + internal abstract class ClassicEventProducer : EventProducer { private readonly Action _addHandler; private readonly Action _removeHandler; diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/FromEventPattern.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/FromEventPattern.cs index 696f44b900..bc243ac6e1 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/FromEventPattern.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/FromEventPattern.cs @@ -15,7 +15,7 @@ namespace System.Reactive.Linq.ObservableImpl { internal sealed class FromEventPattern { - public class Impl : ClassicEventProducer> + public sealed class Impl : ClassicEventProducer> { private readonly Func, TDelegate> _conversion; @@ -48,7 +48,7 @@ protected override TDelegate GetHandler(Action> onNext) } } - public class Impl : ClassicEventProducer> + public sealed class Impl : ClassicEventProducer> { public Impl(Action addHandler, Action removeHandler, IScheduler scheduler) : base(addHandler, removeHandler, scheduler) @@ -62,7 +62,7 @@ protected override TDelegate GetHandler(Action } } - public class Handler : EventProducer + public sealed class Handler : EventProducer { private readonly object _target; private readonly Type _delegateType; @@ -103,14 +103,12 @@ protected override IDisposable AddHandler(Delegate handler) #if HAS_WINRT if (_isWinRT) { - var token = _addMethod.Invoke(_target, new object[] { handler }); - removeHandler = () => _removeMethod.Invoke(_target, new object[] { token }); + removeHandler = AddHandlerCoreWinRT(handler); } else #endif { - _addMethod.Invoke(_target, new object[] { handler }); - removeHandler = () => _removeMethod.Invoke(_target, new object[] { handler }); + removeHandler = AddHandlerCore(handler); } } catch (TargetInvocationException tie) @@ -130,6 +128,20 @@ protected override IDisposable AddHandler(Delegate handler) } }); } + + private Action AddHandlerCore(Delegate handler) + { + _addMethod.Invoke(_target, new object[] { handler }); + return () => _removeMethod.Invoke(_target, new object[] { handler }); + } + +#if HAS_WINRT + private Action AddHandlerCoreWinRT(Delegate handler) + { + var token = _addMethod.Invoke(_target, new object[] { handler }); + return () => _removeMethod.Invoke(_target, new object[] { token }); + } +#endif } } } diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Generate.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Generate.cs index 4d740a5d70..cab69ce32d 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Generate.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Generate.cs @@ -7,281 +7,347 @@ namespace System.Reactive.Linq.ObservableImpl { - internal sealed class Generate : Producer + internal static class Generate { - private readonly TState _initialState; - private readonly Func _condition; - private readonly Func _iterate; - private readonly Func _resultSelector; - private readonly Func _timeSelectorA; - private readonly Func _timeSelectorR; - private readonly IScheduler _scheduler; - - public Generate(TState initialState, Func condition, Func iterate, Func resultSelector, IScheduler scheduler) + internal sealed class NoTime : Producer { - _initialState = initialState; - _condition = condition; - _iterate = iterate; - _resultSelector = resultSelector; - _scheduler = scheduler; - } - - public Generate(TState initialState, Func condition, Func iterate, Func resultSelector, Func timeSelector, IScheduler scheduler) - { - _initialState = initialState; - _condition = condition; - _iterate = iterate; - _resultSelector = resultSelector; - _timeSelectorA = timeSelector; - _scheduler = scheduler; - } - - public Generate(TState initialState, Func condition, Func iterate, Func resultSelector, Func timeSelector, IScheduler scheduler) - { - _initialState = initialState; - _condition = condition; - _iterate = iterate; - _resultSelector = resultSelector; - _timeSelectorR = timeSelector; - _scheduler = scheduler; - } + private readonly TState _initialState; + private readonly Func _condition; + private readonly Func _iterate; + private readonly Func _resultSelector; + private readonly IScheduler _scheduler; - protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) - { - if (_timeSelectorA != null) - { - var sink = new SelectorA(this, observer, cancel); - setSink(sink); - return sink.Run(); - } - else if (_timeSelectorR != null) + public NoTime(TState initialState, Func condition, Func iterate, Func resultSelector, IScheduler scheduler) { - var sink = new Delta(this, observer, cancel); - setSink(sink); - return sink.Run(); + _initialState = initialState; + _condition = condition; + _iterate = iterate; + _resultSelector = resultSelector; + _scheduler = scheduler; } - else + + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { var sink = new _(this, observer, cancel); setSink(sink); return sink.Run(); } - } - - class SelectorA : Sink - { - private readonly Generate _parent; - public SelectorA(Generate parent, IObserver observer, IDisposable cancel) - : base(observer, cancel) + private sealed class _ : Sink { - _parent = parent; - } - - private bool _first; - private bool _hasResult; - private TResult _result; + // CONSIDER: This sink has a parent reference that can be considered for removal. - public IDisposable Run() - { - _first = true; - _hasResult = false; - _result = default(TResult); + private readonly NoTime _parent; - return _parent._scheduler.Schedule(_parent._initialState, InvokeRec); - } + public _(NoTime parent, IObserver observer, IDisposable cancel) + : base(observer, cancel) + { + _parent = parent; + } - private IDisposable InvokeRec(IScheduler self, TState state) - { - var time = default(DateTimeOffset); + private TState _state; + private bool _first; - if (_hasResult) - base._observer.OnNext(_result); - try + public IDisposable Run() { - if (_first) - _first = false; + _state = _parent._initialState; + _first = true; + + var longRunning = _parent._scheduler.AsLongRunning(); + if (longRunning != null) + { + return longRunning.ScheduleLongRunning(Loop); + } else - state = _parent._iterate(state); - _hasResult = _parent._condition(state); - if (_hasResult) { - _result = _parent._resultSelector(state); - time = _parent._timeSelectorA(state); + return _parent._scheduler.Schedule(LoopRec); } } - catch (Exception exception) + + private void Loop(ICancelable cancel) { - base._observer.OnError(exception); + while (!cancel.IsDisposed) + { + var hasResult = false; + var result = default(TResult); + try + { + if (_first) + { + _first = false; + } + else + { + _state = _parent._iterate(_state); + } + + hasResult = _parent._condition(_state); + + if (hasResult) + { + result = _parent._resultSelector(_state); + } + } + catch (Exception exception) + { + base._observer.OnError(exception); + base.Dispose(); + return; + } + + if (hasResult) + { + base._observer.OnNext(result); + } + else + { + break; + } + } + + if (!cancel.IsDisposed) + { + base._observer.OnCompleted(); + } + base.Dispose(); - return Disposable.Empty; } - if (!_hasResult) + private void LoopRec(Action recurse) { - base._observer.OnCompleted(); - base.Dispose(); - return Disposable.Empty; - } + var hasResult = false; + var result = default(TResult); + try + { + if (_first) + { + _first = false; + } + else + { + _state = _parent._iterate(_state); + } + + hasResult = _parent._condition(_state); + + if (hasResult) + { + result = _parent._resultSelector(_state); + } + } + catch (Exception exception) + { + base._observer.OnError(exception); + base.Dispose(); + return; + } - return self.Schedule(state, time, InvokeRec); + if (hasResult) + { + base._observer.OnNext(result); + recurse(); + } + else + { + base._observer.OnCompleted(); + base.Dispose(); + } + } } } - class Delta : Sink + internal sealed class Absolute : Producer { - private readonly Generate _parent; - - public Delta(Generate parent, IObserver observer, IDisposable cancel) - : base(observer, cancel) + private readonly TState _initialState; + private readonly Func _condition; + private readonly Func _iterate; + private readonly Func _resultSelector; + private readonly Func _timeSelector; + private readonly IScheduler _scheduler; + + public Absolute(TState initialState, Func condition, Func iterate, Func resultSelector, Func timeSelector, IScheduler scheduler) { - _parent = parent; + _initialState = initialState; + _condition = condition; + _iterate = iterate; + _resultSelector = resultSelector; + _timeSelector = timeSelector; + _scheduler = scheduler; } - private bool _first; - private bool _hasResult; - private TResult _result; - - public IDisposable Run() + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - _first = true; - _hasResult = false; - _result = default(TResult); - - return _parent._scheduler.Schedule(_parent._initialState, InvokeRec); + var sink = new _(this, observer, cancel); + setSink(sink); + return sink.Run(); } - private IDisposable InvokeRec(IScheduler self, TState state) + private sealed class _ : Sink { - var time = default(TimeSpan); + // CONSIDER: This sink has a parent reference that can be considered for removal. + + private readonly Absolute _parent; - if (_hasResult) - base._observer.OnNext(_result); - try + public _(Absolute parent, IObserver observer, IDisposable cancel) + : base(observer, cancel) { - if (_first) - _first = false; - else - state = _parent._iterate(state); - _hasResult = _parent._condition(state); - if (_hasResult) - { - _result = _parent._resultSelector(state); - time = _parent._timeSelectorR(state); - } + _parent = parent; } - catch (Exception exception) + + private bool _first; + private bool _hasResult; + private TResult _result; + + public IDisposable Run() { - base._observer.OnError(exception); - base.Dispose(); - return Disposable.Empty; + _first = true; + _hasResult = false; + _result = default(TResult); + + return _parent._scheduler.Schedule(_parent._initialState, InvokeRec); } - if (!_hasResult) + private IDisposable InvokeRec(IScheduler self, TState state) { - base._observer.OnCompleted(); - base.Dispose(); - return Disposable.Empty; - } + var time = default(DateTimeOffset); + + if (_hasResult) + { + base._observer.OnNext(_result); + } + + try + { + if (_first) + { + _first = false; + } + else + { + state = _parent._iterate(state); + } + + _hasResult = _parent._condition(state); + + if (_hasResult) + { + _result = _parent._resultSelector(state); + time = _parent._timeSelector(state); + } + } + catch (Exception exception) + { + base._observer.OnError(exception); + base.Dispose(); + return Disposable.Empty; + } - return self.Schedule(state, time, InvokeRec); + if (!_hasResult) + { + base._observer.OnCompleted(); + base.Dispose(); + return Disposable.Empty; + } + + return self.Schedule(state, time, InvokeRec); + } } } - class _ : Sink + internal sealed class Relative : Producer { - private readonly Generate _parent; - - public _(Generate parent, IObserver observer, IDisposable cancel) - : base(observer, cancel) + private readonly TState _initialState; + private readonly Func _condition; + private readonly Func _iterate; + private readonly Func _resultSelector; + private readonly Func _timeSelector; + private readonly IScheduler _scheduler; + + public Relative(TState initialState, Func condition, Func iterate, Func resultSelector, Func timeSelector, IScheduler scheduler) { - _parent = parent; + _initialState = initialState; + _condition = condition; + _iterate = iterate; + _resultSelector = resultSelector; + _timeSelector = timeSelector; + _scheduler = scheduler; } - private TState _state; - private bool _first; + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) + { + var sink = new _(this, observer, cancel); + setSink(sink); + return sink.Run(); + } - public IDisposable Run() + private sealed class _ : Sink { - _state = _parent._initialState; - _first = true; + // CONSIDER: This sink has a parent reference that can be considered for removal. + + private readonly Relative _parent; - var longRunning = _parent._scheduler.AsLongRunning(); - if (longRunning != null) + public _(Relative parent, IObserver observer, IDisposable cancel) + : base(observer, cancel) { - return longRunning.ScheduleLongRunning(Loop); + _parent = parent; } - else + + private bool _first; + private bool _hasResult; + private TResult _result; + + public IDisposable Run() { - return _parent._scheduler.Schedule(LoopRec); + _first = true; + _hasResult = false; + _result = default(TResult); + + return _parent._scheduler.Schedule(_parent._initialState, InvokeRec); } - } - private void Loop(ICancelable cancel) - { - while (!cancel.IsDisposed) + private IDisposable InvokeRec(IScheduler self, TState state) { - var hasResult = false; - var result = default(TResult); + var time = default(TimeSpan); + + if (_hasResult) + { + base._observer.OnNext(_result); + } + try { if (_first) + { _first = false; + } else - _state = _parent._iterate(_state); - hasResult = _parent._condition(_state); - if (hasResult) - result = _parent._resultSelector(_state); + { + state = _parent._iterate(state); + } + + _hasResult = _parent._condition(state); + + if (_hasResult) + { + _result = _parent._resultSelector(state); + time = _parent._timeSelector(state); + } } catch (Exception exception) { base._observer.OnError(exception); base.Dispose(); - return; + return Disposable.Empty; } - if (hasResult) - base._observer.OnNext(result); - else - break; - } - - if (!cancel.IsDisposed) - base._observer.OnCompleted(); - - base.Dispose(); - } - - private void LoopRec(Action recurse) - { - var hasResult = false; - var result = default(TResult); - try - { - if (_first) - _first = false; - else - _state = _parent._iterate(_state); - hasResult = _parent._condition(_state); - if (hasResult) - result = _parent._resultSelector(_state); - } - catch (Exception exception) - { - base._observer.OnError(exception); - base.Dispose(); - return; - } + if (!_hasResult) + { + base._observer.OnCompleted(); + base.Dispose(); + return Disposable.Empty; + } - if (hasResult) - { - base._observer.OnNext(result); - recurse(); - } - else - { - base._observer.OnCompleted(); - base.Dispose(); + return self.Schedule(state, time, InvokeRec); } } } diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/GetEnumerator.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/GetEnumerator.cs index b29fab8a06..d25dfa9aa1 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/GetEnumerator.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/GetEnumerator.cs @@ -75,15 +75,9 @@ public bool MoveNext() return false; } - public TSource Current - { - get { return _current; } - } + public TSource Current => _current; - object Collections.IEnumerator.Current - { - get { return _current; } - } + object Collections.IEnumerator.Current => _current; public void Dispose() { diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/GroupBy.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/GroupBy.cs index fce92ec7ff..4607567058 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/GroupBy.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/GroupBy.cs @@ -25,48 +25,52 @@ public GroupBy(IObservable source, Func keySelector, Fun _comparer = comparer; } - private CompositeDisposable _groupDisposable; - private RefCountDisposable _refCountDisposable; - protected override IDisposable Run(IObserver> observer, IDisposable cancel, Action setSink) { - _groupDisposable = new CompositeDisposable(); - _refCountDisposable = new RefCountDisposable(_groupDisposable); - var sink = new _(this, observer, cancel); setSink(sink); - _groupDisposable.Add(_source.SubscribeSafe(sink)); - - return _refCountDisposable; + return sink.Run(_source); } - class _ : Sink>, IObserver + private sealed class _ : Sink>, IObserver { - private readonly GroupBy _parent; - private readonly Dictionary> _map; - private ISubject _null; + private readonly Func _keySelector; + private readonly Func _elementSelector; + private readonly Dictionary> _map; + + private RefCountDisposable _refCountDisposable; + private Subject _null; public _(GroupBy parent, IObserver> observer, IDisposable cancel) : base(observer, cancel) { - _parent = parent; + _keySelector = parent._keySelector; + _elementSelector = parent._elementSelector; - if (_parent._capacity.HasValue) + if (parent._capacity.HasValue) { - _map = new Dictionary>(_parent._capacity.Value, _parent._comparer); + _map = new Dictionary>(parent._capacity.Value, parent._comparer); } else { - _map = new Dictionary>(_parent._comparer); + _map = new Dictionary>(parent._comparer); } } + public IDisposable Run(IObservable source) + { + var sourceSubscription = new SingleAssignmentDisposable(); + _refCountDisposable = new RefCountDisposable(sourceSubscription); + sourceSubscription.Disposable = source.SubscribeSafe(this); + return _refCountDisposable; + } + public void OnNext(TSource value) { var key = default(TKey); try { - key = _parent._keySelector(value); + key = _keySelector(value); } catch (Exception exception) { @@ -75,7 +79,7 @@ public void OnNext(TSource value) } var fireNewMapEntry = false; - var writer = default(ISubject); + var writer = default(Subject); try { // @@ -124,14 +128,14 @@ public void OnNext(TSource value) if (fireNewMapEntry) { - var group = new GroupedObservable(key, writer, _parent._refCountDisposable); + var group = new GroupedObservable(key, writer, _refCountDisposable); _observer.OnNext(group); } var element = default(TElement); try { - element = _parent._elementSelector(value); + element = _elementSelector(value); } catch (Exception exception) { @@ -149,8 +153,7 @@ public void OnError(Exception error) public void OnCompleted() { - if (_null != null) - _null.OnCompleted(); + _null?.OnCompleted(); foreach (var w in _map.Values) w.OnCompleted(); @@ -161,8 +164,7 @@ public void OnCompleted() private void Error(Exception exception) { - if (_null != null) - _null.OnError(exception); + _null?.OnError(exception); foreach (var w in _map.Values) w.OnError(exception); diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/GroupByUntil.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/GroupByUntil.cs index a3a5796795..f26d69a496 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/GroupByUntil.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/GroupByUntil.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the Apache 2.0 License. // See the LICENSE file in the project root for more information. +using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Reactive.Disposables; @@ -28,34 +29,42 @@ public GroupByUntil(IObservable source, Func keySelector _comparer = comparer; } - private CompositeDisposable _groupDisposable; - private RefCountDisposable _refCountDisposable; - protected override IDisposable Run(IObserver> observer, IDisposable cancel, Action setSink) { - _groupDisposable = new CompositeDisposable(); - _refCountDisposable = new RefCountDisposable(_groupDisposable); - var sink = new _(this, observer, cancel); setSink(sink); - _groupDisposable.Add(_source.SubscribeSafe(sink)); - - return _refCountDisposable; + return sink.Run(_source); } - class _ : Sink>, IObserver + private sealed class _ : Sink>, IObserver { - private readonly GroupByUntil _parent; + private readonly object _nullGate = new object(); + private readonly CompositeDisposable _groupDisposable = new CompositeDisposable(); + private readonly RefCountDisposable _refCountDisposable; private readonly Map> _map; + + private readonly Func _keySelector; + private readonly Func _elementSelector; + private readonly Func, IObservable> _durationSelector; + private ISubject _null; - private object _nullGate; public _(GroupByUntil parent, IObserver> observer, IDisposable cancel) : base(observer, cancel) { - _parent = parent; - _map = new Map>(_parent._capacity, _parent._comparer); - _nullGate = new object(); + _refCountDisposable = new RefCountDisposable(_groupDisposable); + _map = new Map>(parent._capacity, parent._comparer); + + _keySelector = parent._keySelector; + _elementSelector = parent._elementSelector; + _durationSelector = parent._durationSelector; + } + + public IDisposable Run(IObservable source) + { + _groupDisposable.Add(source.SubscribeSafe(this)); + + return _refCountDisposable; } private ISubject NewSubject() @@ -70,7 +79,7 @@ public void OnNext(TSource value) var key = default(TKey); try { - key = _parent._keySelector(value); + key = _keySelector(value); } catch (Exception exception) { @@ -116,14 +125,14 @@ public void OnNext(TSource value) if (fireNewMapEntry) { - var group = new GroupedObservable(key, writer, _parent._refCountDisposable); + var group = new GroupedObservable(key, writer, _refCountDisposable); var duration = default(IObservable); var durationGroup = new GroupedObservable(key, writer); try { - duration = _parent._durationSelector(durationGroup); + duration = _durationSelector(durationGroup); } catch (Exception exception) { @@ -135,14 +144,14 @@ public void OnNext(TSource value) base._observer.OnNext(group); var md = new SingleAssignmentDisposable(); - _parent._groupDisposable.Add(md); - md.Disposable = duration.SubscribeSafe(new Delta(this, key, writer, md)); + _groupDisposable.Add(md); + md.Disposable = duration.SubscribeSafe(new DurationObserver(this, key, writer, md)); } var element = default(TElement); try { - element = _parent._elementSelector(value); + element = _elementSelector(value); } catch (Exception exception) { @@ -171,14 +180,14 @@ public void OnNext(TSource value) writer.OnNext(element); } - class Delta : IObserver + private sealed class DurationObserver : IObserver { private readonly _ _parent; private readonly TKey _key; private readonly ISubject _writer; private readonly IDisposable _self; - public Delta(_ parent, TKey key, ISubject writer, IDisposable self) + public DurationObserver(_ parent, TKey key, ISubject writer, IDisposable self) { _parent = parent; _key = key; @@ -218,7 +227,7 @@ public void OnCompleted() } } - _parent._parent._groupDisposable.Remove(_self); + _parent._groupDisposable.Remove(_self); } } @@ -238,8 +247,7 @@ public void OnCompleted() lock (_nullGate) @null = _null; - if (@null != null) - @null.OnCompleted(); + @null?.OnCompleted(); foreach (var w in _map.Values) w.OnCompleted(); @@ -261,8 +269,7 @@ private void Error(Exception exception) lock (_nullGate) @null = _null; - if (@null != null) - @null.OnError(exception); + @null?.OnError(exception); foreach (var w in _map.Values) w.OnError(exception); @@ -286,22 +293,19 @@ internal sealed class Map // compromise. private const int DEFAULT_CONCURRENCY_MULTIPLIER = 4; - private static int DefaultConcurrencyLevel - { - get { return DEFAULT_CONCURRENCY_MULTIPLIER * Environment.ProcessorCount; } - } + private static int DefaultConcurrencyLevel => DEFAULT_CONCURRENCY_MULTIPLIER * Environment.ProcessorCount; - private readonly System.Collections.Concurrent.ConcurrentDictionary _map; + private readonly ConcurrentDictionary _map; public Map(int? capacity, IEqualityComparer comparer) { if (capacity.HasValue) { - _map = new System.Collections.Concurrent.ConcurrentDictionary(DefaultConcurrencyLevel, capacity.Value, comparer); + _map = new ConcurrentDictionary(DefaultConcurrencyLevel, capacity.Value, comparer); } else { - _map = new System.Collections.Concurrent.ConcurrentDictionary(comparer); + _map = new ConcurrentDictionary(comparer); } } @@ -334,13 +338,7 @@ public TValue GetOrAdd(TKey key, Func valueFactory, out bool added) return value; } - public IEnumerable Values - { - get - { - return _map.Values.ToArray(); - } - } + public IEnumerable Values => _map.Values.ToArray(); public bool Remove(TKey key) { diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/GroupJoin.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/GroupJoin.cs index 54d2c3c39e..fbca0dd735 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/GroupJoin.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/GroupJoin.cs @@ -29,52 +29,53 @@ protected override IDisposable Run(IObserver observer, IDisposable canc { var sink = new _(this, observer, cancel); setSink(sink); - return sink.Run(); + return sink.Run(this); } - class _ : Sink + private sealed class _ : Sink { - private readonly GroupJoin _parent; + private readonly object _gate = new object(); + private readonly CompositeDisposable _group = new CompositeDisposable(); + private readonly RefCountDisposable _refCount; + private readonly SortedDictionary> _leftMap = new SortedDictionary>(); + private readonly SortedDictionary _rightMap = new SortedDictionary(); + + private readonly Func> _leftDurationSelector; + private readonly Func> _rightDurationSelector; + private readonly Func, TResult> _resultSelector; public _(GroupJoin parent, IObserver observer, IDisposable cancel) : base(observer, cancel) { - _parent = parent; - } + _refCount = new RefCountDisposable(_group); + _leftMap = new SortedDictionary>(); + _rightMap = new SortedDictionary(); - private object _gate; - private CompositeDisposable _group; - private RefCountDisposable _refCount; + _leftDurationSelector = parent._leftDurationSelector; + _rightDurationSelector = parent._rightDurationSelector; + _resultSelector = parent._resultSelector; + } private int _leftID; - private SortedDictionary> _leftMap; - private int _rightID; - private SortedDictionary _rightMap; - public IDisposable Run() + public IDisposable Run(GroupJoin parent) { - _gate = new object(); - _group = new CompositeDisposable(); - _refCount = new RefCountDisposable(_group); - var leftSubscription = new SingleAssignmentDisposable(); _group.Add(leftSubscription); _leftID = 0; - _leftMap = new SortedDictionary>(); var rightSubscription = new SingleAssignmentDisposable(); _group.Add(rightSubscription); _rightID = 0; - _rightMap = new SortedDictionary(); - leftSubscription.Disposable = _parent._left.SubscribeSafe(new LeftObserver(this, leftSubscription)); - rightSubscription.Disposable = _parent._right.SubscribeSafe(new RightObserver(this, rightSubscription)); + leftSubscription.Disposable = parent._left.SubscribeSafe(new LeftObserver(this, leftSubscription)); + rightSubscription.Disposable = parent._right.SubscribeSafe(new RightObserver(this, rightSubscription)); return _refCount; } - class LeftObserver : IObserver + private sealed class LeftObserver : IObserver { private readonly _ _parent; private readonly IDisposable _self; @@ -119,7 +120,7 @@ public void OnNext(TLeft value) var duration = default(IObservable); try { - duration = _parent._parent._leftDurationSelector(value); + duration = _parent._leftDurationSelector(value); } catch (Exception exception) { @@ -128,12 +129,12 @@ public void OnNext(TLeft value) } // BREAKING CHANGE v2 > v1.x - The duration sequence is subscribed to before the result sequence is evaluated. - md.Disposable = duration.SubscribeSafe(new Delta(this, id, s, md)); + md.Disposable = duration.SubscribeSafe(new DurationObserver(this, id, s, md)); var result = default(TResult); try { - result = _parent._parent._resultSelector(value, window); + result = _parent._resultSelector(value, window); } catch (Exception exception) { @@ -155,14 +156,14 @@ public void OnNext(TLeft value) } } - class Delta : IObserver + private sealed class DurationObserver : IObserver { private readonly LeftObserver _parent; private readonly int _id; private readonly IObserver _group; private readonly IDisposable _self; - public Delta(LeftObserver parent, int id, IObserver group, IDisposable self) + public DurationObserver(LeftObserver parent, int id, IObserver group, IDisposable self) { _parent = parent; _id = id; @@ -212,7 +213,7 @@ public void OnCompleted() } } - class RightObserver : IObserver + private sealed class RightObserver : IObserver { private readonly _ _parent; private readonly IDisposable _self; @@ -250,7 +251,7 @@ public void OnNext(TRight value) var duration = default(IObservable); try { - duration = _parent._parent._rightDurationSelector(value); + duration = _parent._rightDurationSelector(value); } catch (Exception exception) { @@ -258,7 +259,7 @@ public void OnNext(TRight value) return; } - md.Disposable = duration.SubscribeSafe(new Delta(this, id, md)); + md.Disposable = duration.SubscribeSafe(new DurationObserver(this, id, md)); lock (_parent._gate) { @@ -272,13 +273,13 @@ public void OnNext(TRight value) } } - class Delta : IObserver + private sealed class DurationObserver : IObserver { private readonly RightObserver _parent; private readonly int _id; private readonly IDisposable _self; - public Delta(RightObserver parent, int id, IDisposable self) + public DurationObserver(RightObserver parent, int id, IDisposable self) { _parent = parent; _id = id; diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/If.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/If.cs index 3171bc9c33..f024906bd0 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/If.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/If.cs @@ -19,10 +19,7 @@ public If(Func condition, IObservable thenSource, IObservable Eval() - { - return _condition() ? _thenSource : _elseSource; - } + public IObservable Eval() => _condition() ? _thenSource : _elseSource; protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { @@ -31,7 +28,7 @@ protected override IDisposable Run(IObserver observer, IDisposable canc return sink.Run(); } - class _ : Sink, IObserver + private sealed class _ : Sink, IObserver { private readonly If _parent; diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/IgnoreElements.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/IgnoreElements.cs index 62f9af9a2d..f56fc516e0 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/IgnoreElements.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/IgnoreElements.cs @@ -20,7 +20,7 @@ protected override IDisposable Run(IObserver observer, IDisposable canc return _source.SubscribeSafe(sink); } - class _ : Sink, IObserver + private sealed class _ : Sink, IObserver { public _(IObserver observer, IDisposable cancel) : base(observer, cancel) diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/IsEmpty.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/IsEmpty.cs index f43b90abc9..a5d36c6db8 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/IsEmpty.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/IsEmpty.cs @@ -20,7 +20,7 @@ protected override IDisposable Run(IObserver observer, IDisposable cancel, return _source.SubscribeSafe(sink); } - class _ : Sink, IObserver + private sealed class _ : Sink, IObserver { public _(IObserver observer, IDisposable cancel) : base(observer, cancel) diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Join.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Join.cs index fb8064e440..cb2ee58aa3 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Join.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Join.cs @@ -28,54 +28,53 @@ protected override IDisposable Run(IObserver observer, IDisposable canc { var sink = new _(this, observer, cancel); setSink(sink); - return sink.Run(); + return sink.Run(this); } - class _ : Sink + private sealed class _ : Sink { - private readonly Join _parent; + private readonly object _gate = new object(); + private readonly CompositeDisposable _group = new CompositeDisposable(); + private readonly SortedDictionary _leftMap = new SortedDictionary(); + private readonly SortedDictionary _rightMap = new SortedDictionary(); + + private readonly Func> _leftDurationSelector; + private readonly Func> _rightDurationSelector; + private readonly Func _resultSelector; public _(Join parent, IObserver observer, IDisposable cancel) : base(observer, cancel) { - _parent = parent; + _leftDurationSelector = parent._leftDurationSelector; + _rightDurationSelector = parent._rightDurationSelector; + _resultSelector = parent._resultSelector; } - private object _gate; - private CompositeDisposable _group; - private bool _leftDone; private int _leftID; - private SortedDictionary _leftMap; - + private bool _rightDone; private int _rightID; - private SortedDictionary _rightMap; - public IDisposable Run() + public IDisposable Run(Join parent) { - _gate = new object(); - _group = new CompositeDisposable(); - var leftSubscription = new SingleAssignmentDisposable(); _group.Add(leftSubscription); _leftDone = false; _leftID = 0; - _leftMap = new SortedDictionary(); var rightSubscription = new SingleAssignmentDisposable(); _group.Add(rightSubscription); _rightDone = false; _rightID = 0; - _rightMap = new SortedDictionary(); - leftSubscription.Disposable = _parent._left.SubscribeSafe(new LeftObserver(this, leftSubscription)); - rightSubscription.Disposable = _parent._right.SubscribeSafe(new RightObserver(this, rightSubscription)); + leftSubscription.Disposable = parent._left.SubscribeSafe(new LeftObserver(this, leftSubscription)); + rightSubscription.Disposable = parent._right.SubscribeSafe(new RightObserver(this, rightSubscription)); return _group; } - class LeftObserver : IObserver + private sealed class LeftObserver : IObserver { private readonly _ _parent; private readonly IDisposable _self; @@ -117,7 +116,7 @@ public void OnNext(TLeft value) var duration = default(IObservable); try { - duration = _parent._parent._leftDurationSelector(value); + duration = _parent._leftDurationSelector(value); } catch (Exception exception) { @@ -126,7 +125,7 @@ public void OnNext(TLeft value) return; } - md.Disposable = duration.SubscribeSafe(new Delta(this, id, md)); + md.Disposable = duration.SubscribeSafe(new DurationObserver(this, id, md)); lock (_parent._gate) { @@ -137,7 +136,7 @@ public void OnNext(TLeft value) var result = default(TResult); try { - result = _parent._parent._resultSelector(value, rightValue.Value); + result = _parent._resultSelector(value, rightValue.Value); } catch (Exception exception) { @@ -152,13 +151,13 @@ public void OnNext(TLeft value) } } - class Delta : IObserver + private sealed class DurationObserver : IObserver { private readonly LeftObserver _parent; private readonly int _id; private readonly IDisposable _self; - public Delta(LeftObserver parent, int id, IDisposable self) + public DurationObserver(LeftObserver parent, int id, IDisposable self) { _parent = parent; _id = id; @@ -208,7 +207,7 @@ public void OnCompleted() } } - class RightObserver : IObserver + private sealed class RightObserver : IObserver { private readonly _ _parent; private readonly IDisposable _self; @@ -250,7 +249,7 @@ public void OnNext(TRight value) var duration = default(IObservable); try { - duration = _parent._parent._rightDurationSelector(value); + duration = _parent._rightDurationSelector(value); } catch (Exception exception) { @@ -259,7 +258,7 @@ public void OnNext(TRight value) return; } - md.Disposable = duration.SubscribeSafe(new Delta(this, id, md)); + md.Disposable = duration.SubscribeSafe(new DurationObserver(this, id, md)); lock (_parent._gate) { @@ -270,7 +269,7 @@ public void OnNext(TRight value) var result = default(TResult); try { - result = _parent._parent._resultSelector(leftValue.Value, value); + result = _parent._resultSelector(leftValue.Value, value); } catch (Exception exception) { @@ -285,13 +284,13 @@ public void OnNext(TRight value) } } - class Delta : IObserver + private sealed class DurationObserver : IObserver { private readonly RightObserver _parent; private readonly int _id; private readonly IDisposable _self; - public Delta(RightObserver parent, int id, IDisposable self) + public DurationObserver(RightObserver parent, int id, IDisposable self) { _parent = parent; _id = id; diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/LastAsync.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/LastAsync.cs index 460baff76d..eb84b9e74c 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/LastAsync.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/LastAsync.cs @@ -4,134 +4,140 @@ namespace System.Reactive.Linq.ObservableImpl { - internal sealed class LastAsync : Producer + internal static class LastAsync { - private readonly IObservable _source; - private readonly Func _predicate; - private readonly bool _throwOnEmpty; - - public LastAsync(IObservable source, Func predicate, bool throwOnEmpty) + internal sealed class Sequence : Producer { - _source = source; - _predicate = predicate; - _throwOnEmpty = throwOnEmpty; - } + private readonly IObservable _source; - protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) - { - if (_predicate != null) + public Sequence(IObservable source) { - var sink = new LastAsyncImpl(this, observer, cancel); - setSink(sink); - return _source.SubscribeSafe(sink); + _source = source; } - else + + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - var sink = new _(this, observer, cancel); + var sink = new _(observer, cancel); setSink(sink); return _source.SubscribeSafe(sink); } - } - - class _ : Sink, IObserver - { - private readonly LastAsync _parent; - private TSource _value; - private bool _seenValue; - - public _(LastAsync parent, IObserver observer, IDisposable cancel) - : base(observer, cancel) - { - _parent = parent; - - _value = default(TSource); - _seenValue = false; - } - public void OnNext(TSource value) + private sealed class _ : Sink, IObserver { - _value = value; - _seenValue = true; - } + private TSource _value; + private bool _seenValue; - public void OnError(Exception error) - { - base._observer.OnError(error); - base.Dispose(); - } + public _(IObserver observer, IDisposable cancel) + : base(observer, cancel) + { + _value = default(TSource); + _seenValue = false; + } - public void OnCompleted() - { - if (!_seenValue && _parent._throwOnEmpty) + public void OnNext(TSource value) { - base._observer.OnError(new InvalidOperationException(Strings_Linq.NO_ELEMENTS)); + _value = value; + _seenValue = true; } - else + + public void OnError(Exception error) { - base._observer.OnNext(_value); - base._observer.OnCompleted(); + base._observer.OnError(error); + base.Dispose(); } - base.Dispose(); + public void OnCompleted() + { + if (!_seenValue) + { + base._observer.OnError(new InvalidOperationException(Strings_Linq.NO_ELEMENTS)); + } + else + { + base._observer.OnNext(_value); + base._observer.OnCompleted(); + } + + base.Dispose(); + } } } - class LastAsyncImpl : Sink, IObserver + internal sealed class Predicate : Producer { - private readonly LastAsync _parent; - private TSource _value; - private bool _seenValue; + private readonly IObservable _source; + private readonly Func _predicate; - public LastAsyncImpl(LastAsync parent, IObserver observer, IDisposable cancel) - : base(observer, cancel) + public Predicate(IObservable source, Func predicate) { - _parent = parent; + _source = source; + _predicate = predicate; + } - _value = default(TSource); - _seenValue = false; + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) + { + var sink = new _(_predicate, observer, cancel); + setSink(sink); + return _source.SubscribeSafe(sink); } - public void OnNext(TSource value) + private sealed class _ : Sink, IObserver { - var b = false; + private readonly Func _predicate; + private TSource _value; + private bool _seenValue; - try - { - b = _parent._predicate(value); - } - catch (Exception ex) + public _(Func predicate, IObserver observer, IDisposable cancel) + : base(observer, cancel) { - base._observer.OnError(ex); - base.Dispose(); - return; + _predicate = predicate; + + _value = default(TSource); + _seenValue = false; } - if (b) + public void OnNext(TSource value) { - _value = value; - _seenValue = true; + var b = false; + + try + { + b = _predicate(value); + } + catch (Exception ex) + { + base._observer.OnError(ex); + base.Dispose(); + return; + } + + if (b) + { + _value = value; + _seenValue = true; + } } - } - - public void OnError(Exception error) - { - base._observer.OnError(error); - base.Dispose(); - } - public void OnCompleted() - { - if (!_seenValue && _parent._throwOnEmpty) + public void OnError(Exception error) { - base._observer.OnError(new InvalidOperationException(Strings_Linq.NO_MATCHING_ELEMENTS)); + base._observer.OnError(error); + base.Dispose(); } - else + + public void OnCompleted() { - base._observer.OnNext(_value); - base._observer.OnCompleted(); - } + if (!_seenValue) + { + base._observer.OnError(new InvalidOperationException(Strings_Linq.NO_MATCHING_ELEMENTS)); + } + else + { + base._observer.OnNext(_value); + base._observer.OnCompleted(); + } - base.Dispose(); + base.Dispose(); + } } } } diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/LastOrDefaultAsync.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/LastOrDefaultAsync.cs new file mode 100644 index 0000000000..d4f99a02de --- /dev/null +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/LastOrDefaultAsync.cs @@ -0,0 +1,122 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the Apache 2.0 License. +// See the LICENSE file in the project root for more information. + +namespace System.Reactive.Linq.ObservableImpl +{ + internal static class LastOrDefaultAsync + { + internal sealed class Sequence : Producer + { + private readonly IObservable _source; + + public Sequence(IObservable source) + { + _source = source; + } + + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) + { + var sink = new _(observer, cancel); + setSink(sink); + return _source.SubscribeSafe(sink); + } + + private sealed class _ : Sink, IObserver + { + private TSource _value; + + public _(IObserver observer, IDisposable cancel) + : base(observer, cancel) + { + _value = default(TSource); + } + + public void OnNext(TSource value) + { + _value = value; + } + + public void OnError(Exception error) + { + base._observer.OnError(error); + base.Dispose(); + } + + public void OnCompleted() + { + base._observer.OnNext(_value); + base._observer.OnCompleted(); + base.Dispose(); + } + } + } + + internal sealed class Predicate : Producer + { + private readonly IObservable _source; + private readonly Func _predicate; + + public Predicate(IObservable source, Func predicate) + { + _source = source; + _predicate = predicate; + } + + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) + { + var sink = new _(_predicate, observer, cancel); + setSink(sink); + return _source.SubscribeSafe(sink); + } + + private sealed class _ : Sink, IObserver + { + private readonly Func _predicate; + private TSource _value; + + public _(Func predicate, IObserver observer, IDisposable cancel) + : base(observer, cancel) + { + _predicate = predicate; + + _value = default(TSource); + } + + public void OnNext(TSource value) + { + var b = false; + + try + { + b = _predicate(value); + } + catch (Exception ex) + { + base._observer.OnError(ex); + base.Dispose(); + return; + } + + if (b) + { + _value = value; + } + } + + public void OnError(Exception error) + { + base._observer.OnError(error); + base.Dispose(); + } + + public void OnCompleted() + { + base._observer.OnNext(_value); + base._observer.OnCompleted(); + base.Dispose(); + } + } + } + } +} diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Latest.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Latest.cs index c0cccdf3ec..e71c03cc33 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Latest.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Latest.cs @@ -18,7 +18,7 @@ protected override PushToPullSink Run(IDisposable subscription return new _(subscription); } - class _ : PushToPullSink + private sealed class _ : PushToPullSink { private readonly object _gate; private readonly SemaphoreSlim _semaphore; diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/LongCount.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/LongCount.cs index ab033788dc..20f10c5dc9 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/LongCount.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/LongCount.cs @@ -4,118 +4,126 @@ namespace System.Reactive.Linq.ObservableImpl { - internal sealed class LongCount : Producer + internal static class LongCount { - private readonly IObservable _source; - private readonly Func _predicate; - - public LongCount(IObservable source) + internal sealed class All : Producer { - _source = source; - } + private readonly IObservable _source; - public LongCount(IObservable source, Func predicate) - { - _source = source; - _predicate = predicate; - } - - protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) - { - if (_predicate == null) + public All(IObservable source) { - var sink = new _(observer, cancel); - setSink(sink); - return _source.SubscribeSafe(sink); + _source = source; } - else + + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - var sink = new LongCountImpl(this, observer, cancel); + var sink = new _(observer, cancel); setSink(sink); return _source.SubscribeSafe(sink); } - } - - class _ : Sink, IObserver - { - private long _count; - public _(IObserver observer, IDisposable cancel) - : base(observer, cancel) + private sealed class _ : Sink, IObserver { - _count = 0L; - } + private long _count; - public void OnNext(TSource value) - { - try + public _(IObserver observer, IDisposable cancel) + : base(observer, cancel) { - checked + _count = 0L; + } + + public void OnNext(TSource value) + { + try { - _count++; + checked + { + _count++; + } + } + catch (Exception ex) + { + base._observer.OnError(ex); + base.Dispose(); } } - catch (Exception ex) + + public void OnError(Exception error) { - base._observer.OnError(ex); + base._observer.OnError(error); base.Dispose(); } - } - - public void OnError(Exception error) - { - base._observer.OnError(error); - base.Dispose(); - } - public void OnCompleted() - { - base._observer.OnNext(_count); - base._observer.OnCompleted(); - base.Dispose(); + public void OnCompleted() + { + base._observer.OnNext(_count); + base._observer.OnCompleted(); + base.Dispose(); + } } } - class LongCountImpl : Sink, IObserver + internal sealed class Predicate : Producer { - private readonly LongCount _parent; - private long _count; + private readonly IObservable _source; + private readonly Func _predicate; - public LongCountImpl(LongCount parent, IObserver observer, IDisposable cancel) - : base(observer, cancel) + public Predicate(IObservable source, Func predicate) { - _parent = parent; - _count = 0L; + _source = source; + _predicate = predicate; } - public void OnNext(TSource value) + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - try + var sink = new _(_predicate, observer, cancel); + setSink(sink); + return _source.SubscribeSafe(sink); + } + + private sealed class _ : Sink, IObserver + { + private readonly Func _predicate; + private long _count; + + public _(Func predicate, IObserver observer, IDisposable cancel) + : base(observer, cancel) + { + _predicate = predicate; + _count = 0L; + } + + public void OnNext(TSource value) { - checked + try { - if (_parent._predicate(value)) - _count++; + checked + { + if (_predicate(value)) + { + _count++; + } + } + } + catch (Exception ex) + { + base._observer.OnError(ex); + base.Dispose(); } } - catch (Exception ex) + + public void OnError(Exception error) { - base._observer.OnError(ex); + base._observer.OnError(error); base.Dispose(); } - } - public void OnError(Exception error) - { - base._observer.OnError(error); - base.Dispose(); - } - - public void OnCompleted() - { - base._observer.OnNext(_count); - base._observer.OnCompleted(); - base.Dispose(); + public void OnCompleted() + { + base._observer.OnNext(_count); + base._observer.OnCompleted(); + base.Dispose(); + } } } } diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Materialize.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Materialize.cs index f1fa7bd385..5c5c124951 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Materialize.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Materialize.cs @@ -13,10 +13,7 @@ public Materialize(IObservable source) _source = source; } - public IObservable Dematerialize() - { - return _source.AsObservable(); - } + public IObservable Dematerialize() => _source.AsObservable(); protected override IDisposable Run(IObserver> observer, IDisposable cancel, Action setSink) { @@ -25,7 +22,7 @@ protected override IDisposable Run(IObserver> observer, ID return _source.SubscribeSafe(sink); } - class _ : Sink>, IObserver + private sealed class _ : Sink>, IObserver { public _(IObserver> observer, IDisposable cancel) : base(observer, cancel) diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Max.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Max.cs index bf035fa554..fa1e5b596a 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Max.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Max.cs @@ -22,28 +22,28 @@ protected override IDisposable Run(IObserver observer, IDisposable canc // LINQ to Objects makes this distinction in order to make [Max|Max] of an empty collection of reference type objects equal to null. if (default(TSource) == null) { - var sink = new _(this, observer, cancel); + var sink = new Null(_comparer, observer, cancel); setSink(sink); return _source.SubscribeSafe(sink); } else { - var sink = new Delta(this, observer, cancel); + var sink = new NonNull(_comparer, observer, cancel); setSink(sink); return _source.SubscribeSafe(sink); } } - class Delta : Sink, IObserver + private sealed class NonNull : Sink, IObserver { - private readonly Max _parent; + private readonly IComparer _comparer; private bool _hasValue; private TSource _lastValue; - public Delta(Max parent, IObserver observer, IDisposable cancel) + public NonNull(IComparer comparer, IObserver observer, IDisposable cancel) : base(observer, cancel) { - _parent = parent; + _comparer = comparer; _hasValue = false; _lastValue = default(TSource); @@ -57,7 +57,7 @@ public void OnNext(TSource value) try { - comparison = _parent._comparer.Compare(value, _lastValue); + comparison = _comparer.Compare(value, _lastValue); } catch (Exception ex) { @@ -100,15 +100,15 @@ public void OnCompleted() } } - class _ : Sink, IObserver + private sealed class Null : Sink, IObserver { - private readonly Max _parent; + private readonly IComparer _comparer; private TSource _lastValue; - public _(Max parent, IObserver observer, IDisposable cancel) + public Null(IComparer comparer, IObserver observer, IDisposable cancel) : base(observer, cancel) { - _parent = parent; + _comparer = comparer; _lastValue = default(TSource); } @@ -127,7 +127,7 @@ public void OnNext(TSource value) try { - comparison = _parent._comparer.Compare(value, _lastValue); + comparison = _comparer.Compare(value, _lastValue); } catch (Exception ex) { @@ -175,7 +175,7 @@ protected override IDisposable Run(IObserver observer, IDisposable cance return _source.SubscribeSafe(sink); } - class _ : Sink, IObserver + private sealed class _ : Sink, IObserver { private bool _hasValue; private double _lastValue; @@ -242,7 +242,7 @@ protected override IDisposable Run(IObserver observer, IDisposable cancel return _source.SubscribeSafe(sink); } - class _ : Sink, IObserver + private sealed class _ : Sink, IObserver { private bool _hasValue; private float _lastValue; @@ -309,7 +309,7 @@ protected override IDisposable Run(IObserver observer, IDisposable canc return _source.SubscribeSafe(sink); } - class _ : Sink, IObserver + private sealed class _ : Sink, IObserver { private bool _hasValue; private decimal _lastValue; @@ -376,7 +376,7 @@ protected override IDisposable Run(IObserver observer, IDisposable cancel, return _source.SubscribeSafe(sink); } - class _ : Sink, IObserver + private sealed class _ : Sink, IObserver { private bool _hasValue; private int _lastValue; @@ -443,7 +443,7 @@ protected override IDisposable Run(IObserver observer, IDisposable cancel, return _source.SubscribeSafe(sink); } - class _ : Sink, IObserver + private sealed class _ : Sink, IObserver { private bool _hasValue; private long _lastValue; @@ -510,7 +510,7 @@ protected override IDisposable Run(IObserver observer, IDisposable canc return _source.SubscribeSafe(sink); } - class _ : Sink, IObserver + private sealed class _ : Sink, IObserver { private double? _lastValue; @@ -569,7 +569,7 @@ protected override IDisposable Run(IObserver observer, IDisposable cance return _source.SubscribeSafe(sink); } - class _ : Sink, IObserver + private sealed class _ : Sink, IObserver { private float? _lastValue; @@ -628,7 +628,7 @@ protected override IDisposable Run(IObserver observer, IDisposable can return _source.SubscribeSafe(sink); } - class _ : Sink, IObserver + private sealed class _ : Sink, IObserver { private decimal? _lastValue; @@ -687,7 +687,7 @@ protected override IDisposable Run(IObserver observer, IDisposable cancel, return _source.SubscribeSafe(sink); } - class _ : Sink, IObserver + private sealed class _ : Sink, IObserver { private int? _lastValue; @@ -746,7 +746,7 @@ protected override IDisposable Run(IObserver observer, IDisposable cancel return _source.SubscribeSafe(sink); } - class _ : Sink, IObserver + private sealed class _ : Sink, IObserver { private long? _lastValue; diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/MaxBy.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/MaxBy.cs index d63788078a..dbf5d37eb8 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/MaxBy.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/MaxBy.cs @@ -26,7 +26,7 @@ protected override IDisposable Run(IObserver> observer, IDisposab return _source.SubscribeSafe(sink); } - class _ : Sink>, IObserver + private sealed class _ : Sink>, IObserver { private readonly MaxBy _parent; private bool _hasValue; diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Merge.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Merge.cs index 2329a2ccd2..7df0ca784c 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Merge.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Merge.cs @@ -9,285 +9,276 @@ namespace System.Reactive.Linq.ObservableImpl { - internal sealed class Merge : Producer + internal static class Merge { - private readonly IObservable> _sources; - private readonly IObservable> _sourcesT; - private readonly int _maxConcurrent; - - public Merge(IObservable> sources) - { - _sources = sources; - } - - public Merge(IObservable> sources, int maxConcurrent) + internal sealed class ObservablesMaxConcurrency : Producer { - _sources = sources; - _maxConcurrent = maxConcurrent; - } + private readonly IObservable> _sources; + private readonly int _maxConcurrent; - public Merge(IObservable> sources) - { - _sourcesT = sources; - } - - protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) - { - if (_maxConcurrent > 0) - { - var sink = new MergeConcurrent(this, observer, cancel); - setSink(sink); - return sink.Run(); - } - else if (_sourcesT != null) + public ObservablesMaxConcurrency(IObservable> sources, int maxConcurrent) { - var sink = new MergeImpl(this, observer, cancel); - setSink(sink); - return sink.Run(); + _sources = sources; + _maxConcurrent = maxConcurrent; } - else + + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - var sink = new _(this, observer, cancel); + var sink = new _(_maxConcurrent, observer, cancel); setSink(sink); - return sink.Run(); + return sink.Run(this); } - } - - class _ : Sink, IObserver> - { - private readonly Merge _parent; - public _(Merge parent, IObserver observer, IDisposable cancel) - : base(observer, cancel) + private sealed class _ : Sink, IObserver> { - _parent = parent; - } + private readonly int _maxConcurrent; - private object _gate; - private bool _isStopped; - private CompositeDisposable _group; - private SingleAssignmentDisposable _sourceSubscription; + public _(int maxConcurrent, IObserver observer, IDisposable cancel) + : base(observer, cancel) + { + _maxConcurrent = maxConcurrent; + } - public IDisposable Run() - { - _gate = new object(); - _isStopped = false; - _group = new CompositeDisposable(); + private object _gate; + private Queue> _q; + private bool _isStopped; + private SingleAssignmentDisposable _sourceSubscription; + private CompositeDisposable _group; + private int _activeCount = 0; - _sourceSubscription = new SingleAssignmentDisposable(); - _group.Add(_sourceSubscription); - _sourceSubscription.Disposable = _parent._sources.SubscribeSafe(this); + public IDisposable Run(ObservablesMaxConcurrency parent) + { + _gate = new object(); + _q = new Queue>(); + _isStopped = false; + _activeCount = 0; - return _group; - } + _group = new CompositeDisposable(); + _sourceSubscription = new SingleAssignmentDisposable(); + _sourceSubscription.Disposable = parent._sources.SubscribeSafe(this); + _group.Add(_sourceSubscription); - public void OnNext(IObservable value) - { - var innerSubscription = new SingleAssignmentDisposable(); - _group.Add(innerSubscription); - innerSubscription.Disposable = value.SubscribeSafe(new Iter(this, innerSubscription)); - } + return _group; + } - public void OnError(Exception error) - { - lock (_gate) + public void OnNext(IObservable value) { - base._observer.OnError(error); - base.Dispose(); + lock (_gate) + { + if (_activeCount < _maxConcurrent) + { + _activeCount++; + Subscribe(value); + } + else + _q.Enqueue(value); + } } - } - public void OnCompleted() - { - _isStopped = true; - if (_group.Count == 1) + public void OnError(Exception error) { - // - // Notice there can be a race between OnCompleted of the source and any - // of the inner sequences, where both see _group.Count == 1, and one is - // waiting for the lock. There won't be a double OnCompleted observation - // though, because the call to Dispose silences the observer by swapping - // in a NopObserver. - // lock (_gate) { - base._observer.OnCompleted(); + base._observer.OnError(error); base.Dispose(); } } - else - { - _sourceSubscription.Dispose(); - } - } - class Iter : IObserver - { - private readonly _ _parent; - private readonly IDisposable _self; - - public Iter(_ parent, IDisposable self) + public void OnCompleted() { - _parent = parent; - _self = self; + lock (_gate) + { + _isStopped = true; + if (_activeCount == 0) + { + base._observer.OnCompleted(); + base.Dispose(); + } + else + { + _sourceSubscription.Dispose(); + } + } } - public void OnNext(TSource value) + private void Subscribe(IObservable innerSource) { - lock (_parent._gate) - _parent._observer.OnNext(value); + var subscription = new SingleAssignmentDisposable(); + _group.Add(subscription); + subscription.Disposable = innerSource.SubscribeSafe(new InnerObserver(this, subscription)); } - public void OnError(Exception error) + private sealed class InnerObserver : IObserver { - lock (_parent._gate) + private readonly _ _parent; + private readonly IDisposable _self; + + public InnerObserver(_ parent, IDisposable self) { - _parent._observer.OnError(error); - _parent.Dispose(); + _parent = parent; + _self = self; } - } - public void OnCompleted() - { - _parent._group.Remove(_self); - if (_parent._isStopped && _parent._group.Count == 1) + public void OnNext(TSource value) + { + lock (_parent._gate) + _parent._observer.OnNext(value); + } + + public void OnError(Exception error) { - // - // Notice there can be a race between OnCompleted of the source and any - // of the inner sequences, where both see _group.Count == 1, and one is - // waiting for the lock. There won't be a double OnCompleted observation - // though, because the call to Dispose silences the observer by swapping - // in a NopObserver. - // lock (_parent._gate) { - _parent._observer.OnCompleted(); + _parent._observer.OnError(error); _parent.Dispose(); } } + + public void OnCompleted() + { + _parent._group.Remove(_self); + lock (_parent._gate) + { + if (_parent._q.Count > 0) + { + var s = _parent._q.Dequeue(); + _parent.Subscribe(s); + } + else + { + _parent._activeCount--; + if (_parent._isStopped && _parent._activeCount == 0) + { + _parent._observer.OnCompleted(); + _parent.Dispose(); + } + } + } + } } } } - class MergeConcurrent : Sink, IObserver> + internal sealed class Observables : Producer { - private readonly Merge _parent; + private readonly IObservable> _sources; - public MergeConcurrent(Merge parent, IObserver observer, IDisposable cancel) - : base(observer, cancel) + public Observables(IObservable> sources) { - _parent = parent; + _sources = sources; } - private object _gate; - private Queue> _q; - private bool _isStopped; - private SingleAssignmentDisposable _sourceSubscription; - private CompositeDisposable _group; - private int _activeCount = 0; + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) + { + var sink = new _(observer, cancel); + setSink(sink); + return sink.Run(this); + } - public IDisposable Run() + private sealed class _ : Sink, IObserver> { - _gate = new object(); - _q = new Queue>(); - _isStopped = false; - _activeCount = 0; + public _(IObserver observer, IDisposable cancel) + : base(observer, cancel) + { + } - _group = new CompositeDisposable(); - _sourceSubscription = new SingleAssignmentDisposable(); - _sourceSubscription.Disposable = _parent._sources.SubscribeSafe(this); - _group.Add(_sourceSubscription); + private object _gate; + private bool _isStopped; + private CompositeDisposable _group; + private SingleAssignmentDisposable _sourceSubscription; - return _group; - } + public IDisposable Run(Observables parent) + { + _gate = new object(); + _isStopped = false; + _group = new CompositeDisposable(); - public void OnNext(IObservable value) - { - lock (_gate) + _sourceSubscription = new SingleAssignmentDisposable(); + _group.Add(_sourceSubscription); + _sourceSubscription.Disposable = parent._sources.SubscribeSafe(this); + + return _group; + } + + public void OnNext(IObservable value) { - if (_activeCount < _parent._maxConcurrent) - { - _activeCount++; - Subscribe(value); - } - else - _q.Enqueue(value); + var innerSubscription = new SingleAssignmentDisposable(); + _group.Add(innerSubscription); + innerSubscription.Disposable = value.SubscribeSafe(new InnerObserver(this, innerSubscription)); } - } - public void OnError(Exception error) - { - lock (_gate) + public void OnError(Exception error) { - base._observer.OnError(error); - base.Dispose(); + lock (_gate) + { + base._observer.OnError(error); + base.Dispose(); + } } - } - public void OnCompleted() - { - lock (_gate) + public void OnCompleted() { _isStopped = true; - if (_activeCount == 0) + if (_group.Count == 1) { - base._observer.OnCompleted(); - base.Dispose(); + // + // Notice there can be a race between OnCompleted of the source and any + // of the inner sequences, where both see _group.Count == 1, and one is + // waiting for the lock. There won't be a double OnCompleted observation + // though, because the call to Dispose silences the observer by swapping + // in a NopObserver. + // + lock (_gate) + { + base._observer.OnCompleted(); + base.Dispose(); + } } else { _sourceSubscription.Dispose(); } } - } - - private void Subscribe(IObservable innerSource) - { - var subscription = new SingleAssignmentDisposable(); - _group.Add(subscription); - subscription.Disposable = innerSource.SubscribeSafe(new Iter(this, subscription)); - } - class Iter : IObserver - { - private readonly MergeConcurrent _parent; - private readonly IDisposable _self; - - public Iter(MergeConcurrent parent, IDisposable self) + private sealed class InnerObserver : IObserver { - _parent = parent; - _self = self; - } + private readonly _ _parent; + private readonly IDisposable _self; - public void OnNext(TSource value) - { - lock (_parent._gate) - _parent._observer.OnNext(value); - } + public InnerObserver(_ parent, IDisposable self) + { + _parent = parent; + _self = self; + } - public void OnError(Exception error) - { - lock (_parent._gate) + public void OnNext(TSource value) { - _parent._observer.OnError(error); - _parent.Dispose(); + lock (_parent._gate) + _parent._observer.OnNext(value); } - } - public void OnCompleted() - { - _parent._group.Remove(_self); - lock (_parent._gate) + public void OnError(Exception error) { - if (_parent._q.Count > 0) + lock (_parent._gate) { - var s = _parent._q.Dequeue(); - _parent.Subscribe(s); + _parent._observer.OnError(error); + _parent.Dispose(); } - else + } + + public void OnCompleted() + { + _parent._group.Remove(_self); + if (_parent._isStopped && _parent._group.Count == 1) { - _parent._activeCount--; - if (_parent._isStopped && _parent._activeCount == 0) + // + // Notice there can be a race between OnCompleted of the source and any + // of the inner sequences, where both see _group.Count == 1, and one is + // waiting for the lock. There won't be a double OnCompleted observation + // though, because the call to Dispose silences the observer by swapping + // in a NopObserver. + // + lock (_parent._gate) { _parent._observer.OnCompleted(); _parent.Dispose(); @@ -298,90 +289,104 @@ public void OnCompleted() } } - class MergeImpl : Sink, IObserver> + internal sealed class Tasks : Producer { - private readonly Merge _parent; + private readonly IObservable> _sources; - public MergeImpl(Merge parent, IObserver observer, IDisposable cancel) - : base(observer, cancel) + public Tasks(IObservable> sources) { - _parent = parent; + _sources = sources; } - private object _gate; - private volatile int _count; - - public IDisposable Run() + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - _gate = new object(); - _count = 1; - - return _parent._sourcesT.SubscribeSafe(this); + var sink = new _(observer, cancel); + setSink(sink); + return sink.Run(this); } - public void OnNext(Task value) + private sealed class _ : Sink, IObserver> { - Interlocked.Increment(ref _count); - if (value.IsCompleted) + public _(IObserver observer, IDisposable cancel) + : base(observer, cancel) { - OnCompletedTask(value); } - else + + private object _gate; + private volatile int _count; + + public IDisposable Run(Tasks parent) { - value.ContinueWith(OnCompletedTask); + _gate = new object(); + _count = 1; + + return parent._sources.SubscribeSafe(this); } - } - private void OnCompletedTask(Task task) - { - switch (task.Status) + public void OnNext(Task value) { - case TaskStatus.RanToCompletion: - { - lock (_gate) - base._observer.OnNext(task.Result); + Interlocked.Increment(ref _count); + if (value.IsCompleted) + { + OnCompletedTask(value); + } + else + { + value.ContinueWith(OnCompletedTask); + } + } - OnCompleted(); - } - break; - case TaskStatus.Faulted: - { - lock (_gate) + private void OnCompletedTask(Task task) + { + switch (task.Status) + { + case TaskStatus.RanToCompletion: { - base._observer.OnError(task.Exception.InnerException); - base.Dispose(); + lock (_gate) + base._observer.OnNext(task.Result); + + OnCompleted(); } - } - break; - case TaskStatus.Canceled: - { - lock (_gate) + break; + case TaskStatus.Faulted: { - base._observer.OnError(new TaskCanceledException(task)); - base.Dispose(); + lock (_gate) + { + base._observer.OnError(task.Exception.InnerException); + base.Dispose(); + } } - } - break; + break; + case TaskStatus.Canceled: + { + lock (_gate) + { + base._observer.OnError(new TaskCanceledException(task)); + base.Dispose(); + } + } + break; + } } - } - public void OnError(Exception error) - { - lock (_gate) + public void OnError(Exception error) { - base._observer.OnError(error); - base.Dispose(); + lock (_gate) + { + base._observer.OnError(error); + base.Dispose(); + } } - } - public void OnCompleted() - { - if (Interlocked.Decrement(ref _count) == 0) + public void OnCompleted() { - lock (_gate) + if (Interlocked.Decrement(ref _count) == 0) { - base._observer.OnCompleted(); - base.Dispose(); + lock (_gate) + { + base._observer.OnCompleted(); + base.Dispose(); + } } } } diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Min.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Min.cs index 265d0b2443..7417b0f818 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Min.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Min.cs @@ -22,28 +22,28 @@ protected override IDisposable Run(IObserver observer, IDisposable canc // LINQ to Objects makes this distinction in order to make [Min|Max] of an empty collection of reference type objects equal to null. if (default(TSource) == null) { - var sink = new _(this, observer, cancel); + var sink = new Null(_comparer, observer, cancel); setSink(sink); return _source.SubscribeSafe(sink); } else { - var sink = new Delta(this, observer, cancel); + var sink = new NonNull(_comparer, observer, cancel); setSink(sink); return _source.SubscribeSafe(sink); } } - class Delta : Sink, IObserver + private sealed class NonNull : Sink, IObserver { - private readonly Min _parent; + private readonly IComparer _comparer; private bool _hasValue; private TSource _lastValue; - public Delta(Min parent, IObserver observer, IDisposable cancel) + public NonNull(IComparer comparer, IObserver observer, IDisposable cancel) : base(observer, cancel) { - _parent = parent; + _comparer = comparer; _hasValue = false; _lastValue = default(TSource); @@ -57,7 +57,7 @@ public void OnNext(TSource value) try { - comparison = _parent._comparer.Compare(value, _lastValue); + comparison = _comparer.Compare(value, _lastValue); } catch (Exception ex) { @@ -100,15 +100,15 @@ public void OnCompleted() } } - class _ : Sink, IObserver + private sealed class Null : Sink, IObserver { - private readonly Min _parent; + private readonly IComparer _comparer; private TSource _lastValue; - public _(Min parent, IObserver observer, IDisposable cancel) + public Null(IComparer comparer, IObserver observer, IDisposable cancel) : base(observer, cancel) { - _parent = parent; + _comparer = comparer; _lastValue = default(TSource); } @@ -127,7 +127,7 @@ public void OnNext(TSource value) try { - comparison = _parent._comparer.Compare(value, _lastValue); + comparison = _comparer.Compare(value, _lastValue); } catch (Exception ex) { @@ -175,7 +175,7 @@ protected override IDisposable Run(IObserver observer, IDisposable cance return _source.SubscribeSafe(sink); } - class _ : Sink, IObserver + private sealed class _ : Sink, IObserver { private bool _hasValue; private double _lastValue; @@ -242,7 +242,7 @@ protected override IDisposable Run(IObserver observer, IDisposable cancel return _source.SubscribeSafe(sink); } - class _ : Sink, IObserver + private sealed class _ : Sink, IObserver { private bool _hasValue; private float _lastValue; @@ -309,7 +309,7 @@ protected override IDisposable Run(IObserver observer, IDisposable canc return _source.SubscribeSafe(sink); } - class _ : Sink, IObserver + private sealed class _ : Sink, IObserver { private bool _hasValue; private decimal _lastValue; @@ -376,7 +376,7 @@ protected override IDisposable Run(IObserver observer, IDisposable cancel, return _source.SubscribeSafe(sink); } - class _ : Sink, IObserver + private sealed class _ : Sink, IObserver { private bool _hasValue; private int _lastValue; @@ -443,7 +443,7 @@ protected override IDisposable Run(IObserver observer, IDisposable cancel, return _source.SubscribeSafe(sink); } - class _ : Sink, IObserver + private sealed class _ : Sink, IObserver { private bool _hasValue; private long _lastValue; @@ -510,7 +510,7 @@ protected override IDisposable Run(IObserver observer, IDisposable canc return _source.SubscribeSafe(sink); } - class _ : Sink, IObserver + private sealed class _ : Sink, IObserver { private double? _lastValue; @@ -569,7 +569,7 @@ protected override IDisposable Run(IObserver observer, IDisposable cance return _source.SubscribeSafe(sink); } - class _ : Sink, IObserver + private sealed class _ : Sink, IObserver { private float? _lastValue; @@ -628,7 +628,7 @@ protected override IDisposable Run(IObserver observer, IDisposable can return _source.SubscribeSafe(sink); } - class _ : Sink, IObserver + private sealed class _ : Sink, IObserver { private decimal? _lastValue; @@ -687,7 +687,7 @@ protected override IDisposable Run(IObserver observer, IDisposable cancel, return _source.SubscribeSafe(sink); } - class _ : Sink, IObserver + private sealed class _ : Sink, IObserver { private int? _lastValue; @@ -746,7 +746,7 @@ protected override IDisposable Run(IObserver observer, IDisposable cancel return _source.SubscribeSafe(sink); } - class _ : Sink, IObserver + private sealed class _ : Sink, IObserver { private long? _lastValue; diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/MinBy.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/MinBy.cs index fd9ee815e8..a9e1da432e 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/MinBy.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/MinBy.cs @@ -26,7 +26,7 @@ protected override IDisposable Run(IObserver> observer, IDisposab return _source.SubscribeSafe(sink); } - class _ : Sink>, IObserver + private sealed class _ : Sink>, IObserver { private readonly MinBy _parent; private bool _hasValue; diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/MostRecent.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/MostRecent.cs index 045dc97194..0aaf9c789f 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/MostRecent.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/MostRecent.cs @@ -19,7 +19,7 @@ protected override PushToPullSink Run(IDisposable subscription return new _(_initialValue, subscription); } - class _ : PushToPullSink + private sealed class _ : PushToPullSink { public _(TSource initialValue, IDisposable subscription) : base(subscription) diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Multicast.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Multicast.cs index bd1d1ec6c6..6cacb9afbf 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Multicast.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Multicast.cs @@ -22,30 +22,27 @@ public Multicast(IObservable source, Func observer, IDisposable cancel, Action setSink) { - var sink = new _(this, observer, cancel); + var sink = new _(observer, cancel); setSink(sink); - return sink.Run(); + return sink.Run(this); } - class _ : Sink, IObserver + private sealed class _ : Sink, IObserver { - private readonly Multicast _parent; - - public _(Multicast parent, IObserver observer, IDisposable cancel) + public _(IObserver observer, IDisposable cancel) : base(observer, cancel) { - _parent = parent; } - public IDisposable Run() + public IDisposable Run(Multicast parent) { var observable = default(IObservable); var connectable = default(IConnectableObservable); try { - var subject = _parent._subjectSelector(); - connectable = new ConnectableObservable(_parent._source, subject); - observable = _parent._selector(connectable); + var subject =parent._subjectSelector(); + connectable = new ConnectableObservable(parent._source, subject); + observable = parent._selector(connectable); } catch (Exception exception) { diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Next.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Next.cs index 0343c25360..18efcda1bf 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Next.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Next.cs @@ -18,7 +18,7 @@ protected override PushToPullSink Run(IDisposable subscription return new _(subscription); } - class _ : PushToPullSink + private sealed class _ : PushToPullSink { private readonly object _gate; private readonly SemaphoreSlim _semaphore; diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/ObserveOn.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/ObserveOn.cs deleted file mode 100644 index ad2f486bee..0000000000 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/ObserveOn.cs +++ /dev/null @@ -1,81 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the Apache 2.0 License. -// See the LICENSE file in the project root for more information. - -using System.Reactive.Concurrency; -using System.Threading; - -namespace System.Reactive.Linq.ObservableImpl -{ - internal sealed class ObserveOn : Producer - { - private readonly IObservable _source; - private readonly IScheduler _scheduler; - private readonly SynchronizationContext _context; - - public ObserveOn(IObservable source, IScheduler scheduler) - { - _source = source; - _scheduler = scheduler; - } - - public ObserveOn(IObservable source, SynchronizationContext context) - { - _source = source; - _context = context; - } - - protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) - { - if (_context != null) - { - var sink = new ObserveOnImpl(this, observer, cancel); - setSink(sink); - return _source.Subscribe(sink); - } - else - { - var sink = new ObserveOnObserver(_scheduler, observer, cancel); - setSink(sink); - return _source.Subscribe(sink); - } - } - - class ObserveOnImpl : Sink, IObserver - { - private readonly ObserveOn _parent; - - public ObserveOnImpl(ObserveOn parent, IObserver observer, IDisposable cancel) - : base(observer, cancel) - { - _parent = parent; - } - - public void OnNext(TSource value) - { - _parent._context.PostWithStartComplete(() => - { - base._observer.OnNext(value); - }); - } - - public void OnError(Exception error) - { - _parent._context.PostWithStartComplete(() => - { - base._observer.OnError(error); - base.Dispose(); - }); - } - - public void OnCompleted() - { - _parent._context.PostWithStartComplete(() => - { - base._observer.OnCompleted(); - base.Dispose(); - }); - } - } - } -} diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/OfType.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/OfType.cs index 837af05110..06f0960c61 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/OfType.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/OfType.cs @@ -20,7 +20,7 @@ protected override IDisposable Run(IObserver observer, IDisposable canc return _source.SubscribeSafe(sink); } - class _ : Sink, IObserver + private sealed class _ : Sink, IObserver { public _(IObserver observer, IDisposable cancel) : base(observer, cancel) diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/OnErrorResumeNext.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/OnErrorResumeNext.cs index 53e5626b2d..052faf13b0 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/OnErrorResumeNext.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/OnErrorResumeNext.cs @@ -22,7 +22,7 @@ protected override IDisposable Run(IObserver observer, IDisposable canc return sink.Run(_sources); } - class _ : TailRecursiveSink + private sealed class _ : TailRecursiveSink { public _(IObserver observer, IDisposable cancel) : base(observer, cancel) diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/PushToPullAdapter.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/PushToPullAdapter.cs index 5faa9a7201..c35f2f729d 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/PushToPullAdapter.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/PushToPullAdapter.cs @@ -8,7 +8,7 @@ namespace System.Reactive.Linq.ObservableImpl { - abstract class PushToPullAdapter : IEnumerable + internal abstract class PushToPullAdapter : IEnumerable { private readonly IObservable _source; @@ -17,10 +17,7 @@ public PushToPullAdapter(IObservable source) _source = source; } - IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); public IEnumerator GetEnumerator() { @@ -33,7 +30,7 @@ public IEnumerator GetEnumerator() protected abstract PushToPullSink Run(IDisposable subscription); } - abstract class PushToPullSink : IObserver, IEnumerator, IDisposable + internal abstract class PushToPullSink : IObserver, IEnumerator, IDisposable { private readonly IDisposable _subscription; @@ -76,10 +73,7 @@ public TResult Current private set; } - object IEnumerator.Current - { - get { return Current; } - } + object IEnumerator.Current => Current; public void Reset() { diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Range.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Range.cs index e6bd49f23c..bafac0a3f9 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Range.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Range.cs @@ -24,37 +24,39 @@ protected override IDisposable Run(IObserver observer, IDisposable cancel, { var sink = new _(this, observer, cancel); setSink(sink); - return sink.Run(); + return sink.Run(_scheduler); } - class _ : Sink + private sealed class _ : Sink { - private readonly Range _parent; + private readonly int _start; + private readonly int _count; public _(Range parent, IObserver observer, IDisposable cancel) : base(observer, cancel) { - _parent = parent; + _start = parent._start; + _count = parent._count; } - public IDisposable Run() + public IDisposable Run(IScheduler scheduler) { - var longRunning = _parent._scheduler.AsLongRunning(); + var longRunning = scheduler.AsLongRunning(); if (longRunning != null) { return longRunning.ScheduleLongRunning(0, Loop); } else { - return _parent._scheduler.Schedule(0, LoopRec); + return scheduler.Schedule(0, LoopRec); } } private void Loop(int i, ICancelable cancel) { - while (!cancel.IsDisposed && i < _parent._count) + while (!cancel.IsDisposed && i < _count) { - base._observer.OnNext(_parent._start + i); + base._observer.OnNext(_start + i); i++; } @@ -66,9 +68,9 @@ private void Loop(int i, ICancelable cancel) private void LoopRec(int i, Action recurse) { - if (i < _parent._count) + if (i < _count) { - base._observer.OnNext(_parent._start + i); + base._observer.OnNext(_start + i); recurse(i + 1); } else diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/RefCount.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/RefCount.cs index e6fd9e883c..4a53e7ae9c 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/RefCount.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/RefCount.cs @@ -25,30 +25,27 @@ public RefCount(IConnectableObservable source) protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - var sink = new _(this, observer, cancel); + var sink = new _(observer, cancel); setSink(sink); - return sink.Run(); + return sink.Run(this); } - class _ : Sink, IObserver + private sealed class _ : Sink, IObserver { - private readonly RefCount _parent; - - public _(RefCount parent, IObserver observer, IDisposable cancel) + public _(IObserver observer, IDisposable cancel) : base(observer, cancel) { - _parent = parent; } - public IDisposable Run() + public IDisposable Run(RefCount parent) { - var subscription = _parent._source.SubscribeSafe(this); + var subscription = parent._source.SubscribeSafe(this); - lock (_parent._gate) + lock (parent._gate) { - if (++_parent._count == 1) + if (++parent._count == 1) { - _parent._connectableSubscription = _parent._source.Connect(); + parent._connectableSubscription = parent._source.Connect(); } } @@ -56,11 +53,11 @@ public IDisposable Run() { subscription.Dispose(); - lock (_parent._gate) + lock (parent._gate) { - if (--_parent._count == 0) + if (--parent._count == 0) { - _parent._connectableSubscription.Dispose(); + parent._connectableSubscription.Dispose(); } } }); diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Repeat.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Repeat.cs index 180fc5711c..0c5c47961a 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Repeat.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Repeat.cs @@ -7,119 +7,141 @@ namespace System.Reactive.Linq.ObservableImpl { - internal sealed class Repeat : Producer + internal static class Repeat { - private readonly TResult _value; - private readonly int? _repeatCount; - private readonly IScheduler _scheduler; - - public Repeat(TResult value, int? repeatCount, IScheduler scheduler) + internal sealed class Forever : Producer { - _value = value; - _repeatCount = repeatCount; - _scheduler = scheduler; - } - - protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) - { - var sink = new _(this, observer, cancel); - setSink(sink); - return sink.Run(); - } + private readonly TResult _value; + private readonly IScheduler _scheduler; - class _ : Sink - { - private readonly Repeat _parent; + public Forever(TResult value, IScheduler scheduler) + { + _value = value; + _scheduler = scheduler; + } - public _(Repeat parent, IObserver observer, IDisposable cancel) - : base(observer, cancel) + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - _parent = parent; + var sink = new _(_value, observer, cancel); + setSink(sink); + return sink.Run(this); } - public IDisposable Run() + private sealed class _ : Sink { - var longRunning = _parent._scheduler.AsLongRunning(); - if (longRunning != null) + private readonly TResult _value; + + public _(TResult value, IObserver observer, IDisposable cancel) + : base(observer, cancel) { - return Run(longRunning); + _value = value; } - else + + public IDisposable Run(Forever parent) { - return Run(_parent._scheduler); + var longRunning = parent._scheduler.AsLongRunning(); + if (longRunning != null) + { + return longRunning.ScheduleLongRunning(LoopInf); + } + else + { + return parent._scheduler.Schedule(LoopRecInf); + } } - } - private IDisposable Run(IScheduler scheduler) - { - if (_parent._repeatCount == null) + private void LoopRecInf(Action recurse) { - return scheduler.Schedule(LoopRecInf); + base._observer.OnNext(_value); + recurse(); } - else + + private void LoopInf(ICancelable cancel) { - return scheduler.Schedule(_parent._repeatCount.Value, LoopRec); + var value = _value; + while (!cancel.IsDisposed) + base._observer.OnNext(value); + + base.Dispose(); } } + } + + internal sealed class Count : Producer + { + private readonly TResult _value; + private readonly IScheduler _scheduler; + private readonly int _repeatCount; - private void LoopRecInf(Action recurse) + public Count(TResult value, int repeatCount, IScheduler scheduler) { - base._observer.OnNext(_parent._value); - recurse(); + _value = value; + _scheduler = scheduler; + _repeatCount = repeatCount; } - private void LoopRec(int n, Action recurse) + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - if (n > 0) - { - base._observer.OnNext(_parent._value); - n--; - } - - if (n == 0) - { - base._observer.OnCompleted(); - base.Dispose(); - return; - } - - recurse(n); + var sink = new _(_value, observer, cancel); + setSink(sink); + return sink.Run(this); } - private IDisposable Run(ISchedulerLongRunning scheduler) + private sealed class _ : Sink { - if (_parent._repeatCount == null) + private readonly TResult _value; + + public _(TResult value, IObserver observer, IDisposable cancel) + : base(observer, cancel) { - return scheduler.ScheduleLongRunning(LoopInf); + _value = value; } - else + + public IDisposable Run(Count parent) { - return scheduler.ScheduleLongRunning(_parent._repeatCount.Value, Loop); + var longRunning = parent._scheduler.AsLongRunning(); + if (longRunning != null) + { + return longRunning.ScheduleLongRunning(parent._repeatCount, Loop); + } + else + { + return parent._scheduler.Schedule(parent._repeatCount, LoopRec); + } } - } - private void LoopInf(ICancelable cancel) - { - var value = _parent._value; - while (!cancel.IsDisposed) - base._observer.OnNext(value); - - base.Dispose(); - } - - private void Loop(int n, ICancelable cancel) - { - var value = _parent._value; - while (n > 0 && !cancel.IsDisposed) + private void LoopRec(int n, Action recurse) { - base._observer.OnNext(value); - n--; + if (n > 0) + { + base._observer.OnNext(_value); + n--; + } + + if (n == 0) + { + base._observer.OnCompleted(); + base.Dispose(); + return; + } + + recurse(n); } - if (!cancel.IsDisposed) - base._observer.OnCompleted(); + private void Loop(int n, ICancelable cancel) + { + var value = _value; + while (n > 0 && !cancel.IsDisposed) + { + base._observer.OnNext(value); + n--; + } + + if (!cancel.IsDisposed) + base._observer.OnCompleted(); - base.Dispose(); + base.Dispose(); + } } } } diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Return.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Return.cs index 4796319062..061b583ffa 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Return.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Return.cs @@ -19,29 +19,29 @@ public Return(TResult value, IScheduler scheduler) protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - var sink = new _(this, observer, cancel); + var sink = new _(_value, observer, cancel); setSink(sink); - return sink.Run(); + return sink.Run(_scheduler); } - class _ : Sink + private sealed class _ : Sink { - private readonly Return _parent; + private readonly TResult _value; - public _(Return parent, IObserver observer, IDisposable cancel) + public _(TResult value, IObserver observer, IDisposable cancel) : base(observer, cancel) { - _parent = parent; + _value = value; } - public IDisposable Run() + public IDisposable Run(IScheduler scheduler) { - return _parent._scheduler.Schedule(Invoke); + return scheduler.Schedule(Invoke); } private void Invoke() { - base._observer.OnNext(_parent._value); + base._observer.OnNext(_value); base._observer.OnCompleted(); base.Dispose(); } diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Sample.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Sample.cs index 83b75f11e1..ebf87772e6 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Sample.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Sample.cs @@ -20,38 +20,33 @@ public Sample(IObservable source, IObservable sampler) protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - var sink = new _(this, observer, cancel); + var sink = new _(observer, cancel); setSink(sink); - return sink.Run(); + return sink.Run(this); } - class _ : Sink, IObserver + private sealed class _ : Sink, IObserver { - private readonly Sample _parent; + private readonly object _gate = new object(); - public _(Sample parent, IObserver observer, IDisposable cancel) + public _(IObserver observer, IDisposable cancel) : base(observer, cancel) { - _parent = parent; } - private object _gate; - private IDisposable _sourceSubscription; private bool _hasValue; private TSource _value; private bool _atEnd; - public IDisposable Run() + public IDisposable Run(Sample parent) { - _gate = new object(); - var sourceSubscription = new SingleAssignmentDisposable(); _sourceSubscription = sourceSubscription; - sourceSubscription.Disposable = _parent._source.SubscribeSafe(this); + sourceSubscription.Disposable = parent._source.SubscribeSafe(this); - var samplerSubscription = _parent._sampler.SubscribeSafe(new SampleImpl(this)); + var samplerSubscription = parent._sampler.SubscribeSafe(new SampleObserver(this)); return StableCompositeDisposable.Create(_sourceSubscription, samplerSubscription); } @@ -83,11 +78,11 @@ public void OnCompleted() } } - class SampleImpl : IObserver + private sealed class SampleObserver : IObserver { private readonly _ _parent; - public SampleImpl(_ parent) + public SampleObserver(_ parent) { _parent = parent; } @@ -156,40 +151,35 @@ public Sample(IObservable source, TimeSpan interval, IScheduler schedul protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - var sink = new _(this, observer, cancel); + var sink = new _(observer, cancel); setSink(sink); - return sink.Run(); + return sink.Run(this); } - class _ : Sink, IObserver + private sealed class _ : Sink, IObserver { - private readonly Sample _parent; + private object _gate = new object(); - public _(Sample parent, IObserver observer, IDisposable cancel) + public _(IObserver observer, IDisposable cancel) : base(observer, cancel) { - _parent = parent; } - private object _gate; - private IDisposable _sourceSubscription; private bool _hasValue; private TSource _value; private bool _atEnd; - public IDisposable Run() + public IDisposable Run(Sample parent) { - _gate = new object(); - var sourceSubscription = new SingleAssignmentDisposable(); _sourceSubscription = sourceSubscription; - sourceSubscription.Disposable = _parent._source.SubscribeSafe(this); + sourceSubscription.Disposable = parent._source.SubscribeSafe(this); return StableCompositeDisposable.Create( sourceSubscription, - _parent._scheduler.SchedulePeriodic(_parent._interval, Tick) + parent._scheduler.SchedulePeriodic(parent._interval, Tick) ); } diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Scan.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Scan.cs index 426f398321..b9d2448931 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Scan.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Scan.cs @@ -24,31 +24,23 @@ protected override IDisposable Run(IObserver observer, IDisposable return _source.SubscribeSafe(sink); } - class _ : Sink, IObserver + private sealed class _ : Sink, IObserver { - private readonly Scan _parent; + private readonly Func _accumulator; private TAccumulate _accumulation; - private bool _hasAccumulation; public _(Scan parent, IObserver observer, IDisposable cancel) : base(observer, cancel) { - _parent = parent; - _accumulation = default(TAccumulate); - _hasAccumulation = false; + _accumulator = parent._accumulator; + _accumulation = parent._seed; } public void OnNext(TSource value) { try { - if (_hasAccumulation) - _accumulation = _parent._accumulator(_accumulation, value); - else - { - _accumulation = _parent._accumulator(_parent._seed, value); - _hasAccumulation = true; - } + _accumulation = _accumulator(_accumulation, value); } catch (Exception exception) { @@ -87,21 +79,21 @@ public Scan(IObservable source, Func accumul protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - var sink = new _(this, observer, cancel); + var sink = new _(_accumulator, observer, cancel); setSink(sink); return _source.SubscribeSafe(sink); } - class _ : Sink, IObserver + private sealed class _ : Sink, IObserver { - private readonly Scan _parent; + private readonly Func _accumulator; private TSource _accumulation; private bool _hasAccumulation; - public _(Scan parent, IObserver observer, IDisposable cancel) + public _(Func accumulator, IObserver observer, IDisposable cancel) : base(observer, cancel) { - _parent = parent; + _accumulator = accumulator; _accumulation = default(TSource); _hasAccumulation = false; } @@ -111,7 +103,9 @@ public void OnNext(TSource value) try { if (_hasAccumulation) - _accumulation = _parent._accumulator(_accumulation, value); + { + _accumulation = _accumulator(_accumulation, value); + } else { _accumulation = value; diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Select.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Select.cs index 4fd33eb579..cc7833039c 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Select.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Select.cs @@ -4,119 +4,125 @@ namespace System.Reactive.Linq.ObservableImpl { - internal sealed class Select : Producer + internal static class Select { - private readonly IObservable _source; - private readonly Func _selector; - private readonly Func _selectorI; - - public Select(IObservable source, Func selector) - { - _source = source; - _selector = selector; - } - - public Select(IObservable source, Func selector) + internal sealed class Selector : Producer { - _source = source; - _selectorI = selector; - } + private readonly IObservable _source; + private readonly Func _selector; - protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) - { - if (_selector != null) + public Selector(IObservable source, Func selector) { - var sink = new _(this, observer, cancel); - setSink(sink); - return _source.SubscribeSafe(sink); + _source = source; + _selector = selector; } - else + + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - var sink = new SelectImpl(this, observer, cancel); + var sink = new _(_selector, observer, cancel); setSink(sink); return _source.SubscribeSafe(sink); } - } - - class _ : Sink, IObserver - { - private readonly Select _parent; - public _(Select parent, IObserver observer, IDisposable cancel) - : base(observer, cancel) + private sealed class _ : Sink, IObserver { - _parent = parent; - } + private readonly Func _selector; - public void OnNext(TSource value) - { - var result = default(TResult); - try + public _(Func selector, IObserver observer, IDisposable cancel) + : base(observer, cancel) { - result = _parent._selector(value); + _selector = selector; } - catch (Exception exception) + + public void OnNext(TSource value) { - base._observer.OnError(exception); + var result = default(TResult); + try + { + result = _selector(value); + } + catch (Exception exception) + { + base._observer.OnError(exception); + base.Dispose(); + return; + } + + base._observer.OnNext(result); + } + + public void OnError(Exception error) + { + base._observer.OnError(error); base.Dispose(); - return; } - base._observer.OnNext(result); + public void OnCompleted() + { + base._observer.OnCompleted(); + base.Dispose(); + } } + } - public void OnError(Exception error) - { - base._observer.OnError(error); - base.Dispose(); - } + internal sealed class SelectorIndexed : Producer + { + private readonly IObservable _source; + private readonly Func _selector; - public void OnCompleted() + public SelectorIndexed(IObservable source, Func selector) { - base._observer.OnCompleted(); - base.Dispose(); + _source = source; + _selector = selector; } - } - - class SelectImpl : Sink, IObserver - { - private readonly Select _parent; - private int _index; - public SelectImpl(Select parent, IObserver observer, IDisposable cancel) - : base(observer, cancel) + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - _parent = parent; - _index = 0; + var sink = new _(_selector, observer, cancel); + setSink(sink); + return _source.SubscribeSafe(sink); } - public void OnNext(TSource value) + private sealed class _ : Sink, IObserver { - var result = default(TResult); - try + private readonly Func _selector; + private int _index; + + public _(Func selector, IObserver observer, IDisposable cancel) + : base(observer, cancel) { - result = _parent._selectorI(value, checked(_index++)); + _selector = selector; + _index = 0; } - catch (Exception exception) + + public void OnNext(TSource value) { - base._observer.OnError(exception); - base.Dispose(); - return; + var result = default(TResult); + try + { + result = _selector(value, checked(_index++)); + } + catch (Exception exception) + { + base._observer.OnError(exception); + base.Dispose(); + return; + } + + base._observer.OnNext(result); } - base._observer.OnNext(result); - } - - public void OnError(Exception error) - { - base._observer.OnError(error); - base.Dispose(); - } + public void OnError(Exception error) + { + base._observer.OnError(error); + base.Dispose(); + } - public void OnCompleted() - { - base._observer.OnCompleted(); - base.Dispose(); + public void OnCompleted() + { + base._observer.OnCompleted(); + base.Dispose(); + } } } } diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/SelectMany.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/SelectMany.cs index 14ffe01562..903b1b86b6 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/SelectMany.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/SelectMany.cs @@ -9,233 +9,93 @@ namespace System.Reactive.Linq.ObservableImpl { - internal sealed class SelectMany : Producer + internal static class SelectMany { - private readonly IObservable _source; - private readonly Func> _collectionSelector; - private readonly Func> _collectionSelectorI; - private readonly Func> _collectionSelectorE; - private readonly Func> _collectionSelectorEI; - private readonly Func _resultSelector; - private readonly Func _resultSelectorI; - private readonly Func> _collectionSelectorT; - private readonly Func> _collectionSelectorTI; - private readonly Func _resultSelectorTI; - - public SelectMany(IObservable source, Func> collectionSelector, Func resultSelector) + internal sealed class ObservableSelector : Producer { - _source = source; - _collectionSelector = collectionSelector; - _resultSelector = resultSelector; - } - - public SelectMany(IObservable source, Func> collectionSelector, Func resultSelector) - { - _source = source; - _collectionSelectorI = collectionSelector; - _resultSelectorI = resultSelector; - } - - public SelectMany(IObservable source, Func> collectionSelector, Func resultSelector) - { - _source = source; - _collectionSelectorE = collectionSelector; - _resultSelector = resultSelector; - } - - public SelectMany(IObservable source, Func> collectionSelector, Func resultSelector) - { - _source = source; - _collectionSelectorEI = collectionSelector; - _resultSelectorI = resultSelector; - } - - public SelectMany(IObservable source, Func> collectionSelector, Func resultSelector) - { - _source = source; - _collectionSelectorT = collectionSelector; - _resultSelector = resultSelector; - } - - public SelectMany(IObservable source, Func> collectionSelector, Func resultSelector) - { - _source = source; - _collectionSelectorTI = collectionSelector; - _resultSelectorTI = resultSelector; - } + private readonly IObservable _source; + private readonly Func> _collectionSelector; + private readonly Func _resultSelector; - protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) - { - if (_collectionSelector != null) - { - var sink = new _(this, observer, cancel); - setSink(sink); - return sink.Run(); - } - else if (_collectionSelectorI != null) - { - var sink = new IndexSelectorImpl(this, observer, cancel); - setSink(sink); - return sink.Run(); - } - else if (_collectionSelectorT != null) - { - var sink = new SelectManyImpl(this, observer, cancel); - setSink(sink); - return sink.Run(); - } - else if (_collectionSelectorTI != null) - { - var sink = new Sigma(this, observer, cancel); - setSink(sink); - return sink.Run(); - } - else if (_collectionSelectorE != null) - { - var sink = new NoSelectorImpl(this, observer, cancel); - setSink(sink); - return _source.SubscribeSafe(sink); - } - else + public ObservableSelector(IObservable source, Func> collectionSelector, Func resultSelector) { - var sink = new Omega(this, observer, cancel); - setSink(sink); - return _source.SubscribeSafe(sink); + _source = source; + _collectionSelector = collectionSelector; + _resultSelector = resultSelector; } - } - - class _ : Sink, IObserver - { - private readonly SelectMany _parent; - public _(SelectMany parent, IObserver observer, IDisposable cancel) - : base(observer, cancel) + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - _parent = parent; + var sink = new _(this, observer, cancel); + setSink(sink); + return sink.Run(_source); } - private object _gate; - private bool _isStopped; - private CompositeDisposable _group; - private SingleAssignmentDisposable _sourceSubscription; - - public IDisposable Run() + private sealed class _ : Sink, IObserver { - _gate = new object(); - _isStopped = false; - _group = new CompositeDisposable(); - - _sourceSubscription = new SingleAssignmentDisposable(); - _group.Add(_sourceSubscription); - _sourceSubscription.Disposable = _parent._source.SubscribeSafe(this); - - return _group; - } + private readonly object _gate = new object(); + private readonly SingleAssignmentDisposable _sourceSubscription = new SingleAssignmentDisposable(); + private readonly CompositeDisposable _group = new CompositeDisposable(); - public void OnNext(TSource value) - { - var collection = default(IObservable); + private readonly Func> _collectionSelector; + private readonly Func _resultSelector; - try - { - collection = _parent._collectionSelector(value); - } - catch (Exception ex) + public _(ObservableSelector parent, IObserver observer, IDisposable cancel) + : base(observer, cancel) { - lock (_gate) - { - base._observer.OnError(ex); - base.Dispose(); - } - return; - } - - var innerSubscription = new SingleAssignmentDisposable(); - _group.Add(innerSubscription); - innerSubscription.Disposable = collection.SubscribeSafe(new Iter(this, value, innerSubscription)); - } + _collectionSelector = parent._collectionSelector; + _resultSelector = parent._resultSelector; - public void OnError(Exception error) - { - lock (_gate) - { - base._observer.OnError(error); - base.Dispose(); + _group.Add(_sourceSubscription); } - } - public void OnCompleted() - { - _isStopped = true; - if (_group.Count == 1) - { - // - // Notice there can be a race between OnCompleted of the source and any - // of the inner sequences, where both see _group.Count == 1, and one is - // waiting for the lock. There won't be a double OnCompleted observation - // though, because the call to Dispose silences the observer by swapping - // in a NopObserver. - // - lock (_gate) - { - base._observer.OnCompleted(); - base.Dispose(); - } - } - else + private bool _isStopped; + + public IDisposable Run(IObservable source) { - _sourceSubscription.Dispose(); - } - } + _isStopped = false; - class Iter : IObserver - { - private readonly _ _parent; - private readonly TSource _value; - private readonly IDisposable _self; + _sourceSubscription.Disposable = source.SubscribeSafe(this); - public Iter(_ parent, TSource value, IDisposable self) - { - _parent = parent; - _value = value; - _self = self; + return _group; } - public void OnNext(TCollection value) + public void OnNext(TSource value) { - var res = default(TResult); + var collection = default(IObservable); try { - res = _parent._parent._resultSelector(_value, value); + collection = _collectionSelector(value); } catch (Exception ex) { - lock (_parent._gate) + lock (_gate) { - _parent._observer.OnError(ex); - _parent.Dispose(); + base._observer.OnError(ex); + base.Dispose(); } return; } - lock (_parent._gate) - _parent._observer.OnNext(res); + var innerSubscription = new SingleAssignmentDisposable(); + _group.Add(innerSubscription); + innerSubscription.Disposable = collection.SubscribeSafe(new InnerObserver(this, value, innerSubscription)); } public void OnError(Exception error) { - lock (_parent._gate) + lock (_gate) { - _parent._observer.OnError(error); - _parent.Dispose(); + base._observer.OnError(error); + base.Dispose(); } } public void OnCompleted() { - _parent._group.Remove(_self); - if (_parent._isStopped && _parent._group.Count == 1) + _isStopped = true; + if (_group.Count == 1) { // // Notice there can be a race between OnCompleted of the source and any @@ -244,154 +104,172 @@ public void OnCompleted() // though, because the call to Dispose silences the observer by swapping // in a NopObserver. // - lock (_parent._gate) + lock (_gate) { - _parent._observer.OnCompleted(); - _parent.Dispose(); + base._observer.OnCompleted(); + base.Dispose(); } } + else + { + _sourceSubscription.Dispose(); + } } - } - } - - class IndexSelectorImpl : Sink, IObserver - { - private readonly SelectMany _parent; - public IndexSelectorImpl(SelectMany parent, IObserver observer, IDisposable cancel) - : base(observer, cancel) - { - _parent = parent; - } + private sealed class InnerObserver : IObserver + { + private readonly _ _parent; + private readonly TSource _value; + private readonly IDisposable _self; - private object _gate; - private bool _isStopped; - private CompositeDisposable _group; - private SingleAssignmentDisposable _sourceSubscription; - private int _index; + public InnerObserver(_ parent, TSource value, IDisposable self) + { + _parent = parent; + _value = value; + _self = self; + } - public IDisposable Run() - { - _gate = new object(); - _isStopped = false; - _group = new CompositeDisposable(); + public void OnNext(TCollection value) + { + var res = default(TResult); - _sourceSubscription = new SingleAssignmentDisposable(); - _group.Add(_sourceSubscription); - _sourceSubscription.Disposable = _parent._source.SubscribeSafe(this); + try + { + res = _parent._resultSelector(_value, value); + } + catch (Exception ex) + { + lock (_parent._gate) + { + _parent._observer.OnError(ex); + _parent.Dispose(); + } + return; + } - return _group; - } + lock (_parent._gate) + _parent._observer.OnNext(res); + } - public void OnNext(TSource value) - { - var index = checked(_index++); - var collection = default(IObservable); + public void OnError(Exception error) + { + lock (_parent._gate) + { + _parent._observer.OnError(error); + _parent.Dispose(); + } + } - try - { - collection = _parent._collectionSelectorI(value, index); - } - catch (Exception ex) - { - lock (_gate) + public void OnCompleted() { - base._observer.OnError(ex); - base.Dispose(); + _parent._group.Remove(_self); + if (_parent._isStopped && _parent._group.Count == 1) + { + // + // Notice there can be a race between OnCompleted of the source and any + // of the inner sequences, where both see _group.Count == 1, and one is + // waiting for the lock. There won't be a double OnCompleted observation + // though, because the call to Dispose silences the observer by swapping + // in a NopObserver. + // + lock (_parent._gate) + { + _parent._observer.OnCompleted(); + _parent.Dispose(); + } + } } - return; } - - var innerSubscription = new SingleAssignmentDisposable(); - _group.Add(innerSubscription); - innerSubscription.Disposable = collection.SubscribeSafe(new Iter(this, value, index, innerSubscription)); } + } - public void OnError(Exception error) + internal sealed class ObservableSelectorIndexed : Producer + { + private readonly IObservable _source; + private readonly Func> _collectionSelector; + private readonly Func _resultSelector; + + public ObservableSelectorIndexed(IObservable source, Func> collectionSelector, Func resultSelector) { - lock (_gate) - { - base._observer.OnError(error); - base.Dispose(); - } + _source = source; + _collectionSelector = collectionSelector; + _resultSelector = resultSelector; } - public void OnCompleted() + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - _isStopped = true; - if (_group.Count == 1) - { - // - // Notice there can be a race between OnCompleted of the source and any - // of the inner sequences, where both see _group.Count == 1, and one is - // waiting for the lock. There won't be a double OnCompleted observation - // though, because the call to Dispose silences the observer by swapping - // in a NopObserver. - // - lock (_gate) - { - base._observer.OnCompleted(); - base.Dispose(); - } - } - else - { - _sourceSubscription.Dispose(); - } + var sink = new _(this, observer, cancel); + setSink(sink); + return sink.Run(_source); } - class Iter : IObserver + private sealed class _ : Sink, IObserver { - private readonly IndexSelectorImpl _parent; - private readonly TSource _value; - private readonly int _valueIndex; - private readonly IDisposable _self; + private readonly object _gate = new object(); + private readonly SingleAssignmentDisposable _sourceSubscription = new SingleAssignmentDisposable(); + private readonly CompositeDisposable _group = new CompositeDisposable(); - public Iter(IndexSelectorImpl parent, TSource value, int index, IDisposable self) + private readonly Func> _collectionSelector; + private readonly Func _resultSelector; + + public _(ObservableSelectorIndexed parent, IObserver observer, IDisposable cancel) + : base(observer, cancel) { - _parent = parent; - _value = value; - _valueIndex = index; - _self = self; + _collectionSelector = parent._collectionSelector; + _resultSelector = parent._resultSelector; + + _group.Add(_sourceSubscription); } + private bool _isStopped; private int _index; - public void OnNext(TCollection value) + public IDisposable Run(IObservable source) + { + _isStopped = false; + + _sourceSubscription.Disposable = source.SubscribeSafe(this); + + return _group; + } + + public void OnNext(TSource value) { - var res = default(TResult); + var index = checked(_index++); + var collection = default(IObservable); try { - res = _parent._parent._resultSelectorI(_value, _valueIndex, value, checked(_index++)); + collection = _collectionSelector(value, index); } catch (Exception ex) { - lock (_parent._gate) + lock (_gate) { - _parent._observer.OnError(ex); - _parent.Dispose(); + base._observer.OnError(ex); + base.Dispose(); } return; } - lock (_parent._gate) - _parent._observer.OnNext(res); + var innerSubscription = new SingleAssignmentDisposable(); + _group.Add(innerSubscription); + innerSubscription.Disposable = collection.SubscribeSafe(new InnerObserver(this, value, index, innerSubscription)); } public void OnError(Exception error) { - lock (_parent._gate) + lock (_gate) { - _parent._observer.OnError(error); - _parent.Dispose(); + base._observer.OnError(error); + base.Dispose(); } } public void OnCompleted() { - _parent._group.Remove(_self); - if (_parent._isStopped && _parent._group.Count == 1) + _isStopped = true; + if (_group.Count == 1) { // // Notice there can be a race between OnCompleted of the source and any @@ -400,617 +278,672 @@ public void OnCompleted() // though, because the call to Dispose silences the observer by swapping // in a NopObserver. // - lock (_parent._gate) + lock (_gate) { - _parent._observer.OnCompleted(); - _parent.Dispose(); + base._observer.OnCompleted(); + base.Dispose(); } } + else + { + _sourceSubscription.Dispose(); + } } - } - } - - class NoSelectorImpl : Sink, IObserver - { - private readonly SelectMany _parent; - - public NoSelectorImpl(SelectMany parent, IObserver observer, IDisposable cancel) - : base(observer, cancel) - { - _parent = parent; - } - public void OnNext(TSource value) - { - var xs = default(IEnumerable); - try - { - xs = _parent._collectionSelectorE(value); - } - catch (Exception exception) + private sealed class InnerObserver : IObserver { - base._observer.OnError(exception); - base.Dispose(); - return; - } + private readonly _ _parent; + private readonly TSource _value; + private readonly int _valueIndex; + private readonly IDisposable _self; - var e = default(IEnumerator); - try - { - e = xs.GetEnumerator(); - } - catch (Exception exception) - { - base._observer.OnError(exception); - base.Dispose(); - return; - } + public InnerObserver(_ parent, TSource value, int index, IDisposable self) + { + _parent = parent; + _value = value; + _valueIndex = index; + _self = self; + } - try - { - var hasNext = true; - while (hasNext) + private int _index; + + public void OnNext(TCollection value) { - hasNext = false; - var current = default(TResult); + var res = default(TResult); try { - hasNext = e.MoveNext(); - if (hasNext) - current = _parent._resultSelector(value, e.Current); + res = _parent._resultSelector(_value, _valueIndex, value, checked(_index++)); } - catch (Exception exception) + catch (Exception ex) { - base._observer.OnError(exception); - base.Dispose(); + lock (_parent._gate) + { + _parent._observer.OnError(ex); + _parent.Dispose(); + } return; } - if (hasNext) - base._observer.OnNext(current); + lock (_parent._gate) + _parent._observer.OnNext(res); } - } - finally - { - if (e != null) - e.Dispose(); - } - } - - public void OnError(Exception error) - { - base._observer.OnError(error); - base.Dispose(); - } - - public void OnCompleted() - { - base._observer.OnCompleted(); - base.Dispose(); - } - } - - class Omega : Sink, IObserver - { - private readonly SelectMany _parent; - - public Omega(SelectMany parent, IObserver observer, IDisposable cancel) - : base(observer, cancel) - { - _parent = parent; - } - - private int _index; - - public void OnNext(TSource value) - { - var index = checked(_index++); - - var xs = default(IEnumerable); - try - { - xs = _parent._collectionSelectorEI(value, index); - } - catch (Exception exception) - { - base._observer.OnError(exception); - base.Dispose(); - return; - } - - var e = default(IEnumerator); - try - { - e = xs.GetEnumerator(); - } - catch (Exception exception) - { - base._observer.OnError(exception); - base.Dispose(); - return; - } - try - { - var eIndex = 0; - var hasNext = true; - while (hasNext) + public void OnError(Exception error) { - hasNext = false; - var current = default(TResult); - - try + lock (_parent._gate) { - hasNext = e.MoveNext(); - if (hasNext) - current = _parent._resultSelectorI(value, index, e.Current, checked(eIndex++)); + _parent._observer.OnError(error); + _parent.Dispose(); } - catch (Exception exception) + } + + public void OnCompleted() + { + _parent._group.Remove(_self); + if (_parent._isStopped && _parent._group.Count == 1) { - base._observer.OnError(exception); - base.Dispose(); - return; + // + // Notice there can be a race between OnCompleted of the source and any + // of the inner sequences, where both see _group.Count == 1, and one is + // waiting for the lock. There won't be a double OnCompleted observation + // though, because the call to Dispose silences the observer by swapping + // in a NopObserver. + // + lock (_parent._gate) + { + _parent._observer.OnCompleted(); + _parent.Dispose(); + } } - - if (hasNext) - base._observer.OnNext(current); } } - finally - { - if (e != null) - e.Dispose(); - } - } - - public void OnError(Exception error) - { - base._observer.OnError(error); - base.Dispose(); - } - - public void OnCompleted() - { - base._observer.OnCompleted(); - base.Dispose(); } } - class SelectManyImpl : Sink, IObserver + internal sealed class EnumerableSelector : Producer { - private readonly SelectMany _parent; + private readonly IObservable _source; + private readonly Func> _collectionSelector; + private readonly Func _resultSelector; - public SelectManyImpl(SelectMany parent, IObserver observer, IDisposable cancel) - : base(observer, cancel) + public EnumerableSelector(IObservable source, Func> collectionSelector, Func resultSelector) { - _parent = parent; + _source = source; + _collectionSelector = collectionSelector; + _resultSelector = resultSelector; } - private object _gate; - private CancellationDisposable _cancel; - private volatile int _count; - - public IDisposable Run() + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - _gate = new object(); - _cancel = new CancellationDisposable(); - _count = 1; - - return StableCompositeDisposable.Create(_parent._source.SubscribeSafe(this), _cancel); + var sink = new _(this, observer, cancel); + setSink(sink); + return _source.SubscribeSafe(sink); } - public void OnNext(TSource value) + private sealed class _ : Sink, IObserver { - var task = default(Task); - try + private readonly Func> _collectionSelector; + private readonly Func _resultSelector; + + public _(EnumerableSelector parent, IObserver observer, IDisposable cancel) + : base(observer, cancel) { - Interlocked.Increment(ref _count); - task = _parent._collectionSelectorT(value, _cancel.Token); + _collectionSelector = parent._collectionSelector; + _resultSelector = parent._resultSelector; } - catch (Exception ex) + + public void OnNext(TSource value) { - lock (_gate) + var xs = default(IEnumerable); + try { - base._observer.OnError(ex); - base.Dispose(); + xs = _collectionSelector(value); } + catch (Exception exception) + { + base._observer.OnError(exception); + base.Dispose(); + return; + } + + var e = default(IEnumerator); + try + { + e = xs.GetEnumerator(); + } + catch (Exception exception) + { + base._observer.OnError(exception); + base.Dispose(); + return; + } + + try + { + var hasNext = true; + while (hasNext) + { + hasNext = false; + var current = default(TResult); - return; + try + { + hasNext = e.MoveNext(); + if (hasNext) + current = _resultSelector(value, e.Current); + } + catch (Exception exception) + { + base._observer.OnError(exception); + base.Dispose(); + return; + } + + if (hasNext) + base._observer.OnNext(current); + } + } + finally + { + if (e != null) + e.Dispose(); + } } - if (task.IsCompleted) + public void OnError(Exception error) { - OnCompletedTask(value, task); + base._observer.OnError(error); + base.Dispose(); } - else + + public void OnCompleted() { - AttachContinuation(value, task); + base._observer.OnCompleted(); + base.Dispose(); } } + } + + internal sealed class EnumerableSelectorIndexed : Producer + { + private readonly IObservable _source; + private readonly Func> _collectionSelector; + private readonly Func _resultSelector; + + public EnumerableSelectorIndexed(IObservable source, Func> collectionSelector, Func resultSelector) + { + _source = source; + _collectionSelector = collectionSelector; + _resultSelector = resultSelector; + } - private void AttachContinuation(TSource value, Task task) + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - // - // Separate method to avoid closure in synchronous completion case. - // - task.ContinueWith(t => OnCompletedTask(value, t)); + var sink = new _(this, observer, cancel); + setSink(sink); + return _source.SubscribeSafe(sink); } - private void OnCompletedTask(TSource value, Task task) + private sealed class _ : Sink, IObserver { - switch (task.Status) + private readonly Func> _collectionSelector; + private readonly Func _resultSelector; + + public _(EnumerableSelectorIndexed parent, IObserver observer, IDisposable cancel) + : base(observer, cancel) { - case TaskStatus.RanToCompletion: - { - var res = default(TResult); - try - { - res = _parent._resultSelector(value, task.Result); - } - catch (Exception ex) - { - lock (_gate) - { - base._observer.OnError(ex); - base.Dispose(); - } + _collectionSelector = parent._collectionSelector; + _resultSelector = parent._resultSelector; + } - return; - } + private int _index; - lock (_gate) - base._observer.OnNext(res); + public void OnNext(TSource value) + { + var index = checked(_index++); - OnCompleted(); - } - break; - case TaskStatus.Faulted: + var xs = default(IEnumerable); + try + { + xs = _collectionSelector(value, index); + } + catch (Exception exception) + { + base._observer.OnError(exception); + base.Dispose(); + return; + } + + var e = default(IEnumerator); + try + { + e = xs.GetEnumerator(); + } + catch (Exception exception) + { + base._observer.OnError(exception); + base.Dispose(); + return; + } + + try + { + var eIndex = 0; + var hasNext = true; + while (hasNext) { - lock (_gate) + hasNext = false; + var current = default(TResult); + + try { - base._observer.OnError(task.Exception.InnerException); - base.Dispose(); + hasNext = e.MoveNext(); + if (hasNext) + current = _resultSelector(value, index, e.Current, checked(eIndex++)); } - } - break; - case TaskStatus.Canceled: - { - if (!_cancel.IsDisposed) + catch (Exception exception) { - lock (_gate) - { - base._observer.OnError(new TaskCanceledException(task)); - base.Dispose(); - } + base._observer.OnError(exception); + base.Dispose(); + return; } + + if (hasNext) + base._observer.OnNext(current); } - break; + } + finally + { + if (e != null) + e.Dispose(); + } } - } - public void OnError(Exception error) - { - lock (_gate) + public void OnError(Exception error) { base._observer.OnError(error); base.Dispose(); } - } - public void OnCompleted() - { - if (Interlocked.Decrement(ref _count) == 0) + public void OnCompleted() { - lock (_gate) - { - base._observer.OnCompleted(); - base.Dispose(); - } + base._observer.OnCompleted(); + base.Dispose(); } } } - class Sigma : Sink, IObserver + internal sealed class TaskSelector : Producer { - private readonly SelectMany _parent; + private readonly IObservable _source; + private readonly Func> _collectionSelector; + private readonly Func _resultSelector; - public Sigma(SelectMany parent, IObserver observer, IDisposable cancel) - : base(observer, cancel) + public TaskSelector(IObservable source, Func> collectionSelector, Func resultSelector) { - _parent = parent; + _source = source; + _collectionSelector = collectionSelector; + _resultSelector = resultSelector; } - private object _gate; - private CancellationDisposable _cancel; - private volatile int _count; - private int _index; - - public IDisposable Run() + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - _gate = new object(); - _cancel = new CancellationDisposable(); - _count = 1; - - return StableCompositeDisposable.Create(_parent._source.SubscribeSafe(this), _cancel); + var sink = new _(this, observer, cancel); + setSink(sink); + return sink.Run(_source); } - public void OnNext(TSource value) + private sealed class _ : Sink, IObserver { - var index = checked(_index++); + private readonly object _gate = new object(); + private readonly CancellationDisposable _cancel = new CancellationDisposable(); - var task = default(Task); - try + private readonly Func> _collectionSelector; + private readonly Func _resultSelector; + + public _(TaskSelector parent, IObserver observer, IDisposable cancel) + : base(observer, cancel) { - Interlocked.Increment(ref _count); - task = _parent._collectionSelectorTI(value, index, _cancel.Token); + _collectionSelector = parent._collectionSelector; + _resultSelector = parent._resultSelector; } - catch (Exception ex) + + private volatile int _count; + + public IDisposable Run(IObservable source) { - lock (_gate) - { - base._observer.OnError(ex); - base.Dispose(); - } + _count = 1; - return; + return StableCompositeDisposable.Create(source.SubscribeSafe(this), _cancel); } - if (task.IsCompleted) + public void OnNext(TSource value) { - OnCompletedTask(value, index, task); + var task = default(Task); + try + { + Interlocked.Increment(ref _count); + task = _collectionSelector(value, _cancel.Token); + } + catch (Exception ex) + { + lock (_gate) + { + base._observer.OnError(ex); + base.Dispose(); + } + + return; + } + + if (task.IsCompleted) + { + OnCompletedTask(value, task); + } + else + { + AttachContinuation(value, task); + } } - else + + private void AttachContinuation(TSource value, Task task) { - AttachContinuation(value, index, task); + // + // Separate method to avoid closure in synchronous completion case. + // + task.ContinueWith(t => OnCompletedTask(value, t)); } - } - - private void AttachContinuation(TSource value, int index, Task task) - { - // - // Separate method to avoid closure in synchronous completion case. - // - task.ContinueWith(t => OnCompletedTask(value, index, t)); - } - private void OnCompletedTask(TSource value, int index, Task task) - { - switch (task.Status) + private void OnCompletedTask(TSource value, Task task) { - case TaskStatus.RanToCompletion: - { - var res = default(TResult); - try - { - res = _parent._resultSelectorTI(value, index, task.Result); - } - catch (Exception ex) + switch (task.Status) + { + case TaskStatus.RanToCompletion: { - lock (_gate) + var res = default(TResult); + try { - base._observer.OnError(ex); - base.Dispose(); + res = _resultSelector(value, task.Result); } + catch (Exception ex) + { + lock (_gate) + { + base._observer.OnError(ex); + base.Dispose(); + } - return; - } + return; + } - lock (_gate) - base._observer.OnNext(res); + lock (_gate) + base._observer.OnNext(res); - OnCompleted(); - } - break; - case TaskStatus.Faulted: - { - lock (_gate) - { - base._observer.OnError(task.Exception.InnerException); - base.Dispose(); + OnCompleted(); } - } - break; - case TaskStatus.Canceled: - { - if (!_cancel.IsDisposed) + break; + case TaskStatus.Faulted: { lock (_gate) { - base._observer.OnError(new TaskCanceledException(task)); + base._observer.OnError(task.Exception.InnerException); base.Dispose(); } } - } - break; + break; + case TaskStatus.Canceled: + { + if (!_cancel.IsDisposed) + { + lock (_gate) + { + base._observer.OnError(new TaskCanceledException(task)); + base.Dispose(); + } + } + } + break; + } } - } - public void OnError(Exception error) - { - lock (_gate) + public void OnError(Exception error) { - base._observer.OnError(error); - base.Dispose(); + lock (_gate) + { + base._observer.OnError(error); + base.Dispose(); + } } - } - public void OnCompleted() - { - if (Interlocked.Decrement(ref _count) == 0) + public void OnCompleted() { - lock (_gate) + if (Interlocked.Decrement(ref _count) == 0) { - base._observer.OnCompleted(); - base.Dispose(); + lock (_gate) + { + base._observer.OnCompleted(); + base.Dispose(); + } } } } } - } - internal sealed class SelectMany : Producer - { - private readonly IObservable _source; - private readonly Func> _selector; - private readonly Func> _selectorI; - private readonly Func> _selectorOnError; - private readonly Func> _selectorOnCompleted; - private readonly Func> _selectorE; - private readonly Func> _selectorEI; - private readonly Func> _selectorT; - private readonly Func> _selectorTI; - - public SelectMany(IObservable source, Func> selector) + internal sealed class TaskSelectorIndexed : Producer { - _source = source; - _selector = selector; - } + private readonly IObservable _source; + private readonly Func> _collectionSelector; + private readonly Func _resultSelector; - public SelectMany(IObservable source, Func> selector) - { - _source = source; - _selectorI = selector; - } + public TaskSelectorIndexed(IObservable source, Func> collectionSelector, Func resultSelector) + { + _source = source; + _collectionSelector = collectionSelector; + _resultSelector = resultSelector; + } - public SelectMany(IObservable source, Func> selector, Func> selectorOnError, Func> selectorOnCompleted) - { - _source = source; - _selector = selector; - _selectorOnError = selectorOnError; - _selectorOnCompleted = selectorOnCompleted; - } + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) + { + var sink = new _(this, observer, cancel); + setSink(sink); + return sink.Run(_source); + } - public SelectMany(IObservable source, Func> selector, Func> selectorOnError, Func> selectorOnCompleted) - { - _source = source; - _selectorI = selector; - _selectorOnError = selectorOnError; - _selectorOnCompleted = selectorOnCompleted; - } + private sealed class _ : Sink, IObserver + { + private readonly object _gate = new object(); + private readonly CancellationDisposable _cancel = new CancellationDisposable(); - public SelectMany(IObservable source, Func> selector) - { - _source = source; - _selectorE = selector; - } + private readonly Func> _collectionSelector; + private readonly Func _resultSelector; - public SelectMany(IObservable source, Func> selector) - { - _source = source; - _selectorEI = selector; - } + public _(TaskSelectorIndexed parent, IObserver observer, IDisposable cancel) + : base(observer, cancel) + { + _collectionSelector = parent._collectionSelector; + _resultSelector = parent._resultSelector; + } - public SelectMany(IObservable source, Func> selector) - { - _source = source; - _selectorT = selector; - } + private volatile int _count; + private int _index; - public SelectMany(IObservable source, Func> selector) - { - _source = source; - _selectorTI = selector; - } + public IDisposable Run(IObservable source) + { + _count = 1; - protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) - { - if (_selector != null) - { - var sink = new _(this, observer, cancel); - setSink(sink); - return sink.Run(); - } - else if (_selectorI != null) - { - var sink = new IndexSelectorImpl(this, observer, cancel); - setSink(sink); - return sink.Run(); - } - else if (_selectorT != null) - { - var sink = new SelectManyImpl(this, observer, cancel); - setSink(sink); - return sink.Run(); - } - else if (_selectorTI != null) - { - var sink = new Sigma(this, observer, cancel); - setSink(sink); - return sink.Run(); - } - else if (_selectorE != null) - { - var sink = new NoSelectorImpl(this, observer, cancel); - setSink(sink); - return _source.SubscribeSafe(sink); - } - else - { - var sink = new Omega(this, observer, cancel); - setSink(sink); - return _source.SubscribeSafe(sink); + return StableCompositeDisposable.Create(source.SubscribeSafe(this), _cancel); + } + + public void OnNext(TSource value) + { + var index = checked(_index++); + + var task = default(Task); + try + { + Interlocked.Increment(ref _count); + task = _collectionSelector(value, index, _cancel.Token); + } + catch (Exception ex) + { + lock (_gate) + { + base._observer.OnError(ex); + base.Dispose(); + } + + return; + } + + if (task.IsCompleted) + { + OnCompletedTask(value, index, task); + } + else + { + AttachContinuation(value, index, task); + } + } + + private void AttachContinuation(TSource value, int index, Task task) + { + // + // Separate method to avoid closure in synchronous completion case. + // + task.ContinueWith(t => OnCompletedTask(value, index, t)); + } + + private void OnCompletedTask(TSource value, int index, Task task) + { + switch (task.Status) + { + case TaskStatus.RanToCompletion: + { + var res = default(TResult); + try + { + res = _resultSelector(value, index, task.Result); + } + catch (Exception ex) + { + lock (_gate) + { + base._observer.OnError(ex); + base.Dispose(); + } + + return; + } + + lock (_gate) + base._observer.OnNext(res); + + OnCompleted(); + } + break; + case TaskStatus.Faulted: + { + lock (_gate) + { + base._observer.OnError(task.Exception.InnerException); + base.Dispose(); + } + } + break; + case TaskStatus.Canceled: + { + if (!_cancel.IsDisposed) + { + lock (_gate) + { + base._observer.OnError(new TaskCanceledException(task)); + base.Dispose(); + } + } + } + break; + } + } + + public void OnError(Exception error) + { + lock (_gate) + { + base._observer.OnError(error); + base.Dispose(); + } + } + + public void OnCompleted() + { + if (Interlocked.Decrement(ref _count) == 0) + { + lock (_gate) + { + base._observer.OnCompleted(); + base.Dispose(); + } + } + } } } + } - class _ : Sink, IObserver + internal static class SelectMany + { + internal class ObservableSelector : Producer { - private readonly SelectMany _parent; + protected readonly IObservable _source; + protected readonly Func> _selector; - public _(SelectMany parent, IObserver observer, IDisposable cancel) - : base(observer, cancel) + public ObservableSelector(IObservable source, Func> selector) { - _parent = parent; + _source = source; + _selector = selector; } - private object _gate; - private bool _isStopped; - private CompositeDisposable _group; - private SingleAssignmentDisposable _sourceSubscription; - - public IDisposable Run() + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - _gate = new object(); - _isStopped = false; - _group = new CompositeDisposable(); - - _sourceSubscription = new SingleAssignmentDisposable(); - _group.Add(_sourceSubscription); - _sourceSubscription.Disposable = _parent._source.SubscribeSafe(this); - - return _group; + var sink = new _(this, observer, cancel); + setSink(sink); + return sink.Run(_source); } - public void OnNext(TSource value) + protected class _ : Sink, IObserver { - var inner = default(IObservable); + protected readonly object _gate = new object(); + private readonly SingleAssignmentDisposable _sourceSubscription = new SingleAssignmentDisposable(); + private readonly CompositeDisposable _group = new CompositeDisposable(); - try + private readonly Func> _selector; + + public _(ObservableSelector parent, IObserver observer, IDisposable cancel) + : base(observer, cancel) { - inner = _parent._selector(value); + _selector = parent._selector; + + _group.Add(_sourceSubscription); } - catch (Exception ex) + + private bool _isStopped; + + public IDisposable Run(IObservable source) { - lock (_gate) - { - base._observer.OnError(ex); - base.Dispose(); - } - return; - } + _isStopped = false; - SubscribeInner(inner); - } + _sourceSubscription.Disposable = source.SubscribeSafe(this); - public void OnError(Exception error) - { - if (_parent._selectorOnError != null) + return _group; + } + + public void OnNext(TSource value) { var inner = default(IObservable); try { - inner = _parent._selectorOnError(error); + inner = _selector(value); } catch (Exception ex) { @@ -1023,10 +956,9 @@ public void OnError(Exception error) } SubscribeInner(inner); - - Final(); } - else + + public virtual void OnError(Exception error) { lock (_gate) { @@ -1034,172 +966,234 @@ public void OnError(Exception error) base.Dispose(); } } - } - public void OnCompleted() - { - if (_parent._selectorOnCompleted != null) + public virtual void OnCompleted() { - var inner = default(IObservable); + Final(); + } - try - { - inner = _parent._selectorOnCompleted(); - } - catch (Exception ex) + protected void Final() + { + _isStopped = true; + if (_group.Count == 1) { + // + // Notice there can be a race between OnCompleted of the source and any + // of the inner sequences, where both see _group.Count == 1, and one is + // waiting for the lock. There won't be a double OnCompleted observation + // though, because the call to Dispose silences the observer by swapping + // in a NopObserver. + // lock (_gate) { - base._observer.OnError(ex); + base._observer.OnCompleted(); base.Dispose(); } - return; } - - SubscribeInner(inner); + else + { + _sourceSubscription.Dispose(); + } } - Final(); - } + protected void SubscribeInner(IObservable inner) + { + var innerSubscription = new SingleAssignmentDisposable(); + _group.Add(innerSubscription); + innerSubscription.Disposable = inner.SubscribeSafe(new InnerObserver(this, innerSubscription)); + } - private void Final() - { - _isStopped = true; - if (_group.Count == 1) + private sealed class InnerObserver : IObserver { - // - // Notice there can be a race between OnCompleted of the source and any - // of the inner sequences, where both see _group.Count == 1, and one is - // waiting for the lock. There won't be a double OnCompleted observation - // though, because the call to Dispose silences the observer by swapping - // in a NopObserver. - // - lock (_gate) + private readonly _ _parent; + private readonly IDisposable _self; + + public InnerObserver(_ parent, IDisposable self) { - base._observer.OnCompleted(); - base.Dispose(); + _parent = parent; + _self = self; + } + + public void OnNext(TResult value) + { + lock (_parent._gate) + _parent._observer.OnNext(value); + } + + public void OnError(Exception error) + { + lock (_parent._gate) + { + _parent._observer.OnError(error); + _parent.Dispose(); + } + } + + public void OnCompleted() + { + _parent._group.Remove(_self); + if (_parent._isStopped && _parent._group.Count == 1) + { + // + // Notice there can be a race between OnCompleted of the source and any + // of the inner sequences, where both see _group.Count == 1, and one is + // waiting for the lock. There won't be a double OnCompleted observation + // though, because the call to Dispose silences the observer by swapping + // in a NopObserver. + // + lock (_parent._gate) + { + _parent._observer.OnCompleted(); + _parent.Dispose(); + } + } } } - else - { - _sourceSubscription.Dispose(); - } + } + } + + internal sealed class ObservableSelectors : ObservableSelector + { + private readonly Func> _selectorOnError; + private readonly Func> _selectorOnCompleted; + + public ObservableSelectors(IObservable source, Func> selector, Func> selectorOnError, Func> selectorOnCompleted) + : base(source, selector) + { + _selectorOnError = selectorOnError; + _selectorOnCompleted = selectorOnCompleted; } - private void SubscribeInner(IObservable inner) + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - var innerSubscription = new SingleAssignmentDisposable(); - _group.Add(innerSubscription); - innerSubscription.Disposable = inner.SubscribeSafe(new Iter(this, innerSubscription)); + var sink = new _(this, observer, cancel); + setSink(sink); + return sink.Run(_source); } - class Iter : IObserver + new private sealed class _ : ObservableSelector._ { - private readonly _ _parent; - private readonly IDisposable _self; + private readonly Func> _selectorOnError; + private readonly Func> _selectorOnCompleted; - public Iter(_ parent, IDisposable self) + public _(ObservableSelectors parent, IObserver observer, IDisposable cancel) + : base(parent, observer, cancel) { - _parent = parent; - _self = self; + _selectorOnError = parent._selectorOnError; + _selectorOnCompleted = parent._selectorOnCompleted; } - public void OnNext(TResult value) + public override void OnError(Exception error) { - lock (_parent._gate) - _parent._observer.OnNext(value); - } + if (_selectorOnError != null) + { + var inner = default(IObservable); - public void OnError(Exception error) - { - lock (_parent._gate) + try + { + inner = _selectorOnError(error); + } + catch (Exception ex) + { + lock (_gate) + { + base._observer.OnError(ex); + base.Dispose(); + } + return; + } + + SubscribeInner(inner); + + Final(); + } + else { - _parent._observer.OnError(error); - _parent.Dispose(); + base.OnError(error); } } - public void OnCompleted() + public override void OnCompleted() { - _parent._group.Remove(_self); - if (_parent._isStopped && _parent._group.Count == 1) + if (_selectorOnCompleted != null) { - // - // Notice there can be a race between OnCompleted of the source and any - // of the inner sequences, where both see _group.Count == 1, and one is - // waiting for the lock. There won't be a double OnCompleted observation - // though, because the call to Dispose silences the observer by swapping - // in a NopObserver. - // - lock (_parent._gate) + var inner = default(IObservable); + + try { - _parent._observer.OnCompleted(); - _parent.Dispose(); + inner = _selectorOnCompleted(); + } + catch (Exception ex) + { + lock (_gate) + { + base._observer.OnError(ex); + base.Dispose(); + } + return; } + + SubscribeInner(inner); } + + Final(); } } } - class IndexSelectorImpl : Sink, IObserver + internal class ObservableSelectorIndexed : Producer { - private readonly SelectMany _parent; + protected readonly IObservable _source; + protected readonly Func> _selector; - public IndexSelectorImpl(SelectMany parent, IObserver observer, IDisposable cancel) - : base(observer, cancel) + public ObservableSelectorIndexed(IObservable source, Func> selector) { - _parent = parent; + _source = source; + _selector = selector; } - private object _gate; - private bool _isStopped; - private CompositeDisposable _group; - private SingleAssignmentDisposable _sourceSubscription; - private int _index; - - public IDisposable Run() + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - _gate = new object(); - _isStopped = false; - _group = new CompositeDisposable(); - - _sourceSubscription = new SingleAssignmentDisposable(); - _group.Add(_sourceSubscription); - _sourceSubscription.Disposable = _parent._source.SubscribeSafe(this); - - return _group; + var sink = new _(this, observer, cancel); + setSink(sink); + return sink.Run(_source); } - public void OnNext(TSource value) + protected class _ : Sink, IObserver { - var inner = default(IObservable); + private readonly object _gate = new object(); + private readonly SingleAssignmentDisposable _sourceSubscription = new SingleAssignmentDisposable(); + private readonly CompositeDisposable _group = new CompositeDisposable(); - try + protected readonly Func> _selector; + + public _(ObservableSelectorIndexed parent, IObserver observer, IDisposable cancel) + : base(observer, cancel) { - inner = _parent._selectorI(value, checked(_index++)); + _selector = parent._selector; + + _group.Add(_sourceSubscription); } - catch (Exception ex) + + private bool _isStopped; + private int _index; + + public IDisposable Run(IObservable source) { - lock (_gate) - { - base._observer.OnError(ex); - base.Dispose(); - } - return; - } + _isStopped = false; - SubscribeInner(inner); - } + _sourceSubscription.Disposable = source.SubscribeSafe(this); - public void OnError(Exception error) - { - if (_parent._selectorOnError != null) + return _group; + } + + public void OnNext(TSource value) { var inner = default(IObservable); try { - inner = _parent._selectorOnError(error); + inner = _selector(value, checked(_index++)); } catch (Exception ex) { @@ -1212,10 +1206,9 @@ public void OnError(Exception error) } SubscribeInner(inner); - - Final(); } - else + + public virtual void OnError(Exception error) { lock (_gate) { @@ -1223,493 +1216,641 @@ public void OnError(Exception error) base.Dispose(); } } - } - public void OnCompleted() - { - if (_parent._selectorOnCompleted != null) + public virtual void OnCompleted() { - var inner = default(IObservable); + Final(); + } - try - { - inner = _parent._selectorOnCompleted(); - } - catch (Exception ex) + protected void Final() + { + _isStopped = true; + if (_group.Count == 1) { + // + // Notice there can be a race between OnCompleted of the source and any + // of the inner sequences, where both see _group.Count == 1, and one is + // waiting for the lock. There won't be a double OnCompleted observation + // though, because the call to Dispose silences the observer by swapping + // in a NopObserver. + // lock (_gate) { - base._observer.OnError(ex); + base._observer.OnCompleted(); base.Dispose(); } - return; } - - SubscribeInner(inner); + else + { + _sourceSubscription.Dispose(); + } } - Final(); - } + protected void SubscribeInner(IObservable inner) + { + var innerSubscription = new SingleAssignmentDisposable(); + _group.Add(innerSubscription); + innerSubscription.Disposable = inner.SubscribeSafe(new InnerObserver(this, innerSubscription)); + } - private void Final() - { - _isStopped = true; - if (_group.Count == 1) + private sealed class InnerObserver : IObserver { - // - // Notice there can be a race between OnCompleted of the source and any - // of the inner sequences, where both see _group.Count == 1, and one is - // waiting for the lock. There won't be a double OnCompleted observation - // though, because the call to Dispose silences the observer by swapping - // in a NopObserver. - // - lock (_gate) + private readonly _ _parent; + private readonly IDisposable _self; + + public InnerObserver(_ parent, IDisposable self) { - base._observer.OnCompleted(); - base.Dispose(); + _parent = parent; + _self = self; + } + + public void OnNext(TResult value) + { + lock (_parent._gate) + _parent._observer.OnNext(value); + } + + public void OnError(Exception error) + { + lock (_parent._gate) + { + _parent._observer.OnError(error); + _parent.Dispose(); + } + } + + public void OnCompleted() + { + _parent._group.Remove(_self); + if (_parent._isStopped && _parent._group.Count == 1) + { + // + // Notice there can be a race between OnCompleted of the source and any + // of the inner sequences, where both see _group.Count == 1, and one is + // waiting for the lock. There won't be a double OnCompleted observation + // though, because the call to Dispose silences the observer by swapping + // in a NopObserver. + // + lock (_parent._gate) + { + _parent._observer.OnCompleted(); + _parent.Dispose(); + } + } } } - else - { - _sourceSubscription.Dispose(); - } + } + } + + internal sealed class ObservableSelectorsIndexed : ObservableSelectorIndexed + { + private readonly Func> _selectorOnError; + private readonly Func> _selectorOnCompleted; + + public ObservableSelectorsIndexed(IObservable source, Func> selector, Func> selectorOnError, Func> selectorOnCompleted) + : base(source, selector) + { + _selectorOnError = selectorOnError; + _selectorOnCompleted = selectorOnCompleted; } - private void SubscribeInner(IObservable inner) + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - var innerSubscription = new SingleAssignmentDisposable(); - _group.Add(innerSubscription); - innerSubscription.Disposable = inner.SubscribeSafe(new Iter(this, innerSubscription)); + var sink = new _(this, observer, cancel); + setSink(sink); + return sink.Run(_source); } - class Iter : IObserver + new private sealed class _ : ObservableSelectorIndexed._ { - private readonly IndexSelectorImpl _parent; - private readonly IDisposable _self; + private readonly object _gate = new object(); + private readonly SingleAssignmentDisposable _sourceSubscription = new SingleAssignmentDisposable(); + private readonly CompositeDisposable _group = new CompositeDisposable(); - public Iter(IndexSelectorImpl parent, IDisposable self) - { - _parent = parent; - _self = self; - } + private readonly Func> _selectorOnError; + private readonly Func> _selectorOnCompleted; - public void OnNext(TResult value) + public _(ObservableSelectorsIndexed parent, IObserver observer, IDisposable cancel) + : base(parent, observer, cancel) { - lock (_parent._gate) - _parent._observer.OnNext(value); + _selectorOnError = parent._selectorOnError; + _selectorOnCompleted = parent._selectorOnCompleted; + + _group.Add(_sourceSubscription); } - public void OnError(Exception error) + public override void OnError(Exception error) { - lock (_parent._gate) + if (_selectorOnError != null) + { + var inner = default(IObservable); + + try + { + inner = _selectorOnError(error); + } + catch (Exception ex) + { + lock (_gate) + { + base._observer.OnError(ex); + base.Dispose(); + } + return; + } + + SubscribeInner(inner); + + Final(); + } + else { - _parent._observer.OnError(error); - _parent.Dispose(); + base.OnError(error); } } - public void OnCompleted() + public override void OnCompleted() { - _parent._group.Remove(_self); - if (_parent._isStopped && _parent._group.Count == 1) + if (_selectorOnCompleted != null) { - // - // Notice there can be a race between OnCompleted of the source and any - // of the inner sequences, where both see _group.Count == 1, and one is - // waiting for the lock. There won't be a double OnCompleted observation - // though, because the call to Dispose silences the observer by swapping - // in a NopObserver. - // - lock (_parent._gate) + var inner = default(IObservable); + + try { - _parent._observer.OnCompleted(); - _parent.Dispose(); + inner = _selectorOnCompleted(); + } + catch (Exception ex) + { + lock (_gate) + { + base._observer.OnError(ex); + base.Dispose(); + } + return; } + + SubscribeInner(inner); } + + Final(); } } } - class NoSelectorImpl : Sink, IObserver + internal sealed class EnumerableSelector : Producer { - private readonly SelectMany _parent; + private readonly IObservable _source; + private readonly Func> _selector; - public NoSelectorImpl(SelectMany parent, IObserver observer, IDisposable cancel) - : base(observer, cancel) + public EnumerableSelector(IObservable source, Func> selector) { - _parent = parent; + _source = source; + _selector = selector; } - public void OnNext(TSource value) + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - var xs = default(IEnumerable); - try - { - xs = _parent._selectorE(value); - } - catch (Exception exception) - { - base._observer.OnError(exception); - base.Dispose(); - return; - } + var sink = new _(this, observer, cancel); + setSink(sink); + return _source.SubscribeSafe(sink); + } + + private sealed class _ : Sink, IObserver + { + private readonly Func> _selector; - var e = default(IEnumerator); - try - { - e = xs.GetEnumerator(); - } - catch (Exception exception) + public _(EnumerableSelector parent, IObserver observer, IDisposable cancel) + : base(observer, cancel) { - base._observer.OnError(exception); - base.Dispose(); - return; + _selector = parent._selector; } - try + public void OnNext(TSource value) { - var hasNext = true; - while (hasNext) + var xs = default(IEnumerable); + try + { + xs = _selector(value); + } + catch (Exception exception) { - hasNext = false; - var current = default(TResult); + base._observer.OnError(exception); + base.Dispose(); + return; + } - try + var e = default(IEnumerator); + try + { + e = xs.GetEnumerator(); + } + catch (Exception exception) + { + base._observer.OnError(exception); + base.Dispose(); + return; + } + + try + { + var hasNext = true; + while (hasNext) { - hasNext = e.MoveNext(); + hasNext = false; + var current = default(TResult); + + try + { + hasNext = e.MoveNext(); + if (hasNext) + current = e.Current; + } + catch (Exception exception) + { + base._observer.OnError(exception); + base.Dispose(); + return; + } + if (hasNext) - current = e.Current; - } - catch (Exception exception) - { - base._observer.OnError(exception); - base.Dispose(); - return; + base._observer.OnNext(current); } - - if (hasNext) - base._observer.OnNext(current); + } + finally + { + if (e != null) + e.Dispose(); } } - finally + + public void OnError(Exception error) { - if (e != null) - e.Dispose(); + base._observer.OnError(error); + base.Dispose(); } - } - - public void OnError(Exception error) - { - base._observer.OnError(error); - base.Dispose(); - } - public void OnCompleted() - { - base._observer.OnCompleted(); - base.Dispose(); + public void OnCompleted() + { + base._observer.OnCompleted(); + base.Dispose(); + } } } - class Omega : Sink, IObserver + internal sealed class EnumerableSelectorIndexed : Producer { - private readonly SelectMany _parent; + private readonly IObservable _source; + private readonly Func> _selector; - public Omega(SelectMany parent, IObserver observer, IDisposable cancel) - : base(observer, cancel) + public EnumerableSelectorIndexed(IObservable source, Func> selector) { - _parent = parent; + _source = source; + _selector = selector; } - - private int _index; - public void OnNext(TSource value) + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - var xs = default(IEnumerable); - try - { - xs = _parent._selectorEI(value, checked(_index++)); - } - catch (Exception exception) - { - base._observer.OnError(exception); - base.Dispose(); - return; - } + var sink = new _(this, observer, cancel); + setSink(sink); + return _source.SubscribeSafe(sink); + } - var e = default(IEnumerator); - try - { - e = xs.GetEnumerator(); - } - catch (Exception exception) + private sealed class _ : Sink, IObserver + { + private readonly Func> _selector; + + public _(EnumerableSelectorIndexed parent, IObserver observer, IDisposable cancel) + : base(observer, cancel) { - base._observer.OnError(exception); - base.Dispose(); - return; + _selector = parent._selector; } - try + private int _index; + + public void OnNext(TSource value) { - var hasNext = true; - while (hasNext) + var xs = default(IEnumerable); + try + { + xs = _selector(value, checked(_index++)); + } + catch (Exception exception) { - hasNext = false; - var current = default(TResult); + base._observer.OnError(exception); + base.Dispose(); + return; + } - try + var e = default(IEnumerator); + try + { + e = xs.GetEnumerator(); + } + catch (Exception exception) + { + base._observer.OnError(exception); + base.Dispose(); + return; + } + + try + { + var hasNext = true; + while (hasNext) { - hasNext = e.MoveNext(); + hasNext = false; + var current = default(TResult); + + try + { + hasNext = e.MoveNext(); + if (hasNext) + current = e.Current; + } + catch (Exception exception) + { + base._observer.OnError(exception); + base.Dispose(); + return; + } + if (hasNext) - current = e.Current; - } - catch (Exception exception) - { - base._observer.OnError(exception); - base.Dispose(); - return; + base._observer.OnNext(current); } - - if (hasNext) - base._observer.OnNext(current); + } + finally + { + if (e != null) + e.Dispose(); } } - finally + + public void OnError(Exception error) { - if (e != null) - e.Dispose(); + base._observer.OnError(error); + base.Dispose(); } - } - public void OnError(Exception error) - { - base._observer.OnError(error); - base.Dispose(); - } - - public void OnCompleted() - { - base._observer.OnCompleted(); - base.Dispose(); + public void OnCompleted() + { + base._observer.OnCompleted(); + base.Dispose(); + } } } - class SelectManyImpl : Sink, IObserver + internal sealed class TaskSelector : Producer { - private readonly SelectMany _parent; + private readonly IObservable _source; + private readonly Func> _selector; - public SelectManyImpl(SelectMany parent, IObserver observer, IDisposable cancel) - : base(observer, cancel) + public TaskSelector(IObservable source, Func> selector) { - _parent = parent; + _source = source; + _selector = selector; } - private object _gate; - private CancellationDisposable _cancel; - private volatile int _count; - - public IDisposable Run() + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - _gate = new object(); - _cancel = new CancellationDisposable(); - _count = 1; - - return StableCompositeDisposable.Create(_parent._source.SubscribeSafe(this), _cancel); + var sink = new _(this, observer, cancel); + setSink(sink); + return sink.Run(_source); } - public void OnNext(TSource value) + private sealed class _ : Sink, IObserver { - var task = default(Task); - try - { - Interlocked.Increment(ref _count); - task = _parent._selectorT(value, _cancel.Token); - } - catch (Exception ex) - { - lock (_gate) - { - base._observer.OnError(ex); - base.Dispose(); - } + private readonly object _gate = new object(); + private readonly CancellationDisposable _cancel = new CancellationDisposable(); - return; - } + private readonly Func> _selector; - if (task.IsCompleted) + public _(TaskSelector parent, IObserver observer, IDisposable cancel) + : base(observer, cancel) { - OnCompletedTask(task); + _selector = parent._selector; } - else + + private volatile int _count; + + public IDisposable Run(IObservable source) { - task.ContinueWith(OnCompletedTask); + _count = 1; + + return StableCompositeDisposable.Create(source.SubscribeSafe(this), _cancel); } - } - private void OnCompletedTask(Task task) - { - switch (task.Status) + public void OnNext(TSource value) { - case TaskStatus.RanToCompletion: + var task = default(Task); + try + { + Interlocked.Increment(ref _count); + task = _selector(value, _cancel.Token); + } + catch (Exception ex) + { + lock (_gate) { - lock (_gate) - base._observer.OnNext(task.Result); - - OnCompleted(); + base._observer.OnError(ex); + base.Dispose(); } - break; - case TaskStatus.Faulted: - { - lock (_gate) + + return; + } + + if (task.IsCompleted) + { + OnCompletedTask(task); + } + else + { + task.ContinueWith(OnCompletedTask); + } + } + + private void OnCompletedTask(Task task) + { + switch (task.Status) + { + case TaskStatus.RanToCompletion: { - base._observer.OnError(task.Exception.InnerException); - base.Dispose(); + lock (_gate) + base._observer.OnNext(task.Result); + + OnCompleted(); } - } - break; - case TaskStatus.Canceled: - { - if (!_cancel.IsDisposed) + break; + case TaskStatus.Faulted: { lock (_gate) { - base._observer.OnError(new TaskCanceledException(task)); + base._observer.OnError(task.Exception.InnerException); base.Dispose(); - } + } } - } - break; + break; + case TaskStatus.Canceled: + { + if (!_cancel.IsDisposed) + { + lock (_gate) + { + base._observer.OnError(new TaskCanceledException(task)); + base.Dispose(); + } + } + } + break; + } } - } - public void OnError(Exception error) - { - lock (_gate) + public void OnError(Exception error) { - base._observer.OnError(error); - base.Dispose(); + lock (_gate) + { + base._observer.OnError(error); + base.Dispose(); + } } - } - public void OnCompleted() - { - if (Interlocked.Decrement(ref _count) == 0) + public void OnCompleted() { - lock (_gate) + if (Interlocked.Decrement(ref _count) == 0) { - base._observer.OnCompleted(); - base.Dispose(); + lock (_gate) + { + base._observer.OnCompleted(); + base.Dispose(); + } } } } } - class Sigma : Sink, IObserver + internal sealed class TaskSelectorIndexed : Producer { - private readonly SelectMany _parent; + private readonly IObservable _source; + private readonly Func> _selector; - public Sigma(SelectMany parent, IObserver observer, IDisposable cancel) - : base(observer, cancel) + public TaskSelectorIndexed(IObservable source, Func> selector) { - _parent = parent; + _source = source; + _selector = selector; } - private object _gate; - private CancellationDisposable _cancel; - private volatile int _count; - private int _index; - - public IDisposable Run() + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - _gate = new object(); - _cancel = new CancellationDisposable(); - _count = 1; - - return StableCompositeDisposable.Create(_parent._source.SubscribeSafe(this), _cancel); + var sink = new _(this, observer, cancel); + setSink(sink); + return sink.Run(_source); } - public void OnNext(TSource value) + private sealed class _ : Sink, IObserver { - var task = default(Task); - try - { - Interlocked.Increment(ref _count); - task = _parent._selectorTI(value, checked(_index++), _cancel.Token); - } - catch (Exception ex) - { - lock (_gate) - { - base._observer.OnError(ex); - base.Dispose(); - } + private readonly object _gate = new object(); + private readonly CancellationDisposable _cancel = new CancellationDisposable(); - return; - } + private readonly Func> _selector; - if (task.IsCompleted) + public _(TaskSelectorIndexed parent, IObserver observer, IDisposable cancel) + : base(observer, cancel) { - OnCompletedTask(task); + _selector = parent._selector; } - else + + private volatile int _count; + private int _index; + + public IDisposable Run(IObservable source) { - task.ContinueWith(OnCompletedTask); + _count = 1; + + return StableCompositeDisposable.Create(source.SubscribeSafe(this), _cancel); } - } - private void OnCompletedTask(Task task) - { - switch (task.Status) + public void OnNext(TSource value) { - case TaskStatus.RanToCompletion: + var task = default(Task); + try + { + Interlocked.Increment(ref _count); + task = _selector(value, checked(_index++), _cancel.Token); + } + catch (Exception ex) + { + lock (_gate) { - lock (_gate) - base._observer.OnNext(task.Result); - - OnCompleted(); + base._observer.OnError(ex); + base.Dispose(); } - break; - case TaskStatus.Faulted: - { - lock (_gate) + + return; + } + + if (task.IsCompleted) + { + OnCompletedTask(task); + } + else + { + task.ContinueWith(OnCompletedTask); + } + } + + private void OnCompletedTask(Task task) + { + switch (task.Status) + { + case TaskStatus.RanToCompletion: { - base._observer.OnError(task.Exception.InnerException); - base.Dispose(); + lock (_gate) + base._observer.OnNext(task.Result); + + OnCompleted(); } - } - break; - case TaskStatus.Canceled: - { - if (!_cancel.IsDisposed) + break; + case TaskStatus.Faulted: { lock (_gate) { - base._observer.OnError(new TaskCanceledException(task)); + base._observer.OnError(task.Exception.InnerException); base.Dispose(); } } - } - break; + break; + case TaskStatus.Canceled: + { + if (!_cancel.IsDisposed) + { + lock (_gate) + { + base._observer.OnError(new TaskCanceledException(task)); + base.Dispose(); + } + } + } + break; + } } - } - public void OnError(Exception error) - { - lock (_gate) + public void OnError(Exception error) { - base._observer.OnError(error); - base.Dispose(); + lock (_gate) + { + base._observer.OnError(error); + base.Dispose(); + } } - } - public void OnCompleted() - { - if (Interlocked.Decrement(ref _count) == 0) + public void OnCompleted() { - lock (_gate) + if (Interlocked.Decrement(ref _count) == 0) { - base._observer.OnCompleted(); - base.Dispose(); + lock (_gate) + { + base._observer.OnCompleted(); + base.Dispose(); + } } } } diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/SequenceEqual.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/SequenceEqual.cs index 6cbd3c02b6..312df0fa7e 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/SequenceEqual.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/SequenceEqual.cs @@ -7,224 +7,210 @@ namespace System.Reactive.Linq.ObservableImpl { - internal sealed class SequenceEqual : Producer + internal static class SequenceEqual { - private readonly IObservable _first; - private readonly IObservable _second; - private readonly IEnumerable _secondE; - private readonly IEqualityComparer _comparer; - - public SequenceEqual(IObservable first, IObservable second, IEqualityComparer comparer) - { - _first = first; - _second = second; - _comparer = comparer; - } - - public SequenceEqual(IObservable first, IEnumerable second, IEqualityComparer comparer) + internal sealed class Observable : Producer { - _first = first; - _secondE = second; - _comparer = comparer; - } + private readonly IObservable _first; + private readonly IObservable _second; + private readonly IEqualityComparer _comparer; - protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) - { - if (_second != null) + public Observable(IObservable first, IObservable second, IEqualityComparer comparer) { - var sink = new _(this, observer, cancel); - setSink(sink); - return sink.Run(); + _first = first; + _second = second; + _comparer = comparer; } - else + + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - var sink = new SequenceEqualImpl(this, observer, cancel); + var sink = new _(_comparer, observer, cancel); setSink(sink); - return sink.Run(); + return sink.Run(this); } - } - - class _ : Sink - { - private readonly SequenceEqual _parent; - public _(SequenceEqual parent, IObserver observer, IDisposable cancel) - : base(observer, cancel) + private sealed class _ : Sink { - _parent = parent; - } + private readonly IEqualityComparer _comparer; - private object _gate; - private bool _donel; - private bool _doner; - private Queue _ql; - private Queue _qr; - - public IDisposable Run() - { - _gate = new object(); - _donel = false; - _doner = false; - _ql = new Queue(); - _qr = new Queue(); - - return StableCompositeDisposable.Create - ( - _parent._first.SubscribeSafe(new F(this)), - _parent._second.SubscribeSafe(new S(this)) - ); - } + public _(IEqualityComparer comparer, IObserver observer, IDisposable cancel) + : base(observer, cancel) + { + _comparer = comparer; + } - class F : IObserver - { - private readonly _ _parent; + private object _gate; + private bool _donel; + private bool _doner; + private Queue _ql; + private Queue _qr; - public F(_ parent) + public IDisposable Run(Observable parent) { - _parent = parent; + _gate = new object(); + _donel = false; + _doner = false; + _ql = new Queue(); + _qr = new Queue(); + + return StableCompositeDisposable.Create + ( + parent._first.SubscribeSafe(new FirstObserver(this)), + parent._second.SubscribeSafe(new SecondObserver(this)) + ); } - public void OnNext(TSource value) + private sealed class FirstObserver : IObserver { - lock (_parent._gate) + private readonly _ _parent; + + public FirstObserver(_ parent) { - if (_parent._qr.Count > 0) + _parent = parent; + } + + public void OnNext(TSource value) + { + lock (_parent._gate) { - var equal = false; - var v = _parent._qr.Dequeue(); - try - { - equal = _parent._parent._comparer.Equals(value, v); - } - catch (Exception exception) + if (_parent._qr.Count > 0) { - _parent._observer.OnError(exception); - _parent.Dispose(); - return; + var equal = false; + var v = _parent._qr.Dequeue(); + try + { + equal = _parent._comparer.Equals(value, v); + } + catch (Exception exception) + { + _parent._observer.OnError(exception); + _parent.Dispose(); + return; + } + if (!equal) + { + _parent._observer.OnNext(false); + _parent._observer.OnCompleted(); + _parent.Dispose(); + } } - if (!equal) + else if (_parent._doner) { _parent._observer.OnNext(false); _parent._observer.OnCompleted(); _parent.Dispose(); } + else + _parent._ql.Enqueue(value); } - else if (_parent._doner) - { - _parent._observer.OnNext(false); - _parent._observer.OnCompleted(); - _parent.Dispose(); - } - else - _parent._ql.Enqueue(value); } - } - public void OnError(Exception error) - { - lock (_parent._gate) + public void OnError(Exception error) { - _parent._observer.OnError(error); - _parent.Dispose(); + lock (_parent._gate) + { + _parent._observer.OnError(error); + _parent.Dispose(); + } } - } - public void OnCompleted() - { - lock (_parent._gate) + public void OnCompleted() { - _parent._donel = true; - if (_parent._ql.Count == 0) + lock (_parent._gate) { - if (_parent._qr.Count > 0) - { - _parent._observer.OnNext(false); - _parent._observer.OnCompleted(); - _parent.Dispose(); - } - else if (_parent._doner) + _parent._donel = true; + if (_parent._ql.Count == 0) { - _parent._observer.OnNext(true); - _parent._observer.OnCompleted(); - _parent.Dispose(); + if (_parent._qr.Count > 0) + { + _parent._observer.OnNext(false); + _parent._observer.OnCompleted(); + _parent.Dispose(); + } + else if (_parent._doner) + { + _parent._observer.OnNext(true); + _parent._observer.OnCompleted(); + _parent.Dispose(); + } } } } } - } - - class S : IObserver - { - private readonly _ _parent; - public S(_ parent) + private sealed class SecondObserver : IObserver { - _parent = parent; - } + private readonly _ _parent; - public void OnNext(TSource value) - { - lock (_parent._gate) + public SecondObserver(_ parent) + { + _parent = parent; + } + + public void OnNext(TSource value) { - if (_parent._ql.Count > 0) + lock (_parent._gate) { - var equal = false; - var v = _parent._ql.Dequeue(); - try - { - equal = _parent._parent._comparer.Equals(v, value); - } - catch (Exception exception) + if (_parent._ql.Count > 0) { - _parent._observer.OnError(exception); - _parent.Dispose(); - return; + var equal = false; + var v = _parent._ql.Dequeue(); + try + { + equal = _parent._comparer.Equals(v, value); + } + catch (Exception exception) + { + _parent._observer.OnError(exception); + _parent.Dispose(); + return; + } + if (!equal) + { + _parent._observer.OnNext(false); + _parent._observer.OnCompleted(); + _parent.Dispose(); + } } - if (!equal) + else if (_parent._donel) { _parent._observer.OnNext(false); _parent._observer.OnCompleted(); _parent.Dispose(); } + else + _parent._qr.Enqueue(value); } - else if (_parent._donel) - { - _parent._observer.OnNext(false); - _parent._observer.OnCompleted(); - _parent.Dispose(); - } - else - _parent._qr.Enqueue(value); } - } - public void OnError(Exception error) - { - lock (_parent._gate) + public void OnError(Exception error) { - _parent._observer.OnError(error); - _parent.Dispose(); + lock (_parent._gate) + { + _parent._observer.OnError(error); + _parent.Dispose(); + } } - } - public void OnCompleted() - { - lock (_parent._gate) + public void OnCompleted() { - _parent._doner = true; - if (_parent._qr.Count == 0) + lock (_parent._gate) { - if (_parent._ql.Count > 0) - { - _parent._observer.OnNext(false); - _parent._observer.OnCompleted(); - _parent.Dispose(); - } - else if (_parent._donel) + _parent._doner = true; + if (_parent._qr.Count == 0) { - _parent._observer.OnNext(true); - _parent._observer.OnCompleted(); - _parent.Dispose(); + if (_parent._ql.Count > 0) + { + _parent._observer.OnNext(false); + _parent._observer.OnCompleted(); + _parent.Dispose(); + } + else if (_parent._donel) + { + _parent._observer.OnNext(true); + _parent._observer.OnCompleted(); + _parent.Dispose(); + } } } } @@ -232,95 +218,116 @@ public void OnCompleted() } } - class SequenceEqualImpl : Sink, IObserver + internal sealed class Enumerable : Producer { - private readonly SequenceEqual _parent; + private readonly IObservable _first; + private readonly IEnumerable _second; + private readonly IEqualityComparer _comparer; - public SequenceEqualImpl(SequenceEqual parent, IObserver observer, IDisposable cancel) - : base(observer, cancel) + public Enumerable(IObservable first, IEnumerable second, IEqualityComparer comparer) { - _parent = parent; + _first = first; + _second = second; + _comparer = comparer; } - private IEnumerator _enumerator; + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) + { + var sink = new _(_comparer, observer, cancel); + setSink(sink); + return sink.Run(this); + } - public IDisposable Run() + private sealed class _ : Sink, IObserver { - // - // Notice the evaluation order of obtaining the enumerator and subscribing to the - // observable sequence is reversed compared to the operator's signature. This is - // required to make sure the enumerator is available as soon as the observer can - // be called. Otherwise, we end up having a race for the initialization and use - // of the _rightEnumerator field. - // - try - { - _enumerator = _parent._secondE.GetEnumerator(); - } - catch (Exception exception) + private readonly IEqualityComparer _comparer; + + public _(IEqualityComparer comparer, IObserver observer, IDisposable cancel) + : base(observer, cancel) { - base._observer.OnError(exception); - base.Dispose(); - return Disposable.Empty; + _comparer = comparer; } - return StableCompositeDisposable.Create( - _parent._first.SubscribeSafe(this), - _enumerator - ); - } - - public void OnNext(TSource value) - { - var equal = false; + private IEnumerator _enumerator; - try + public IDisposable Run(Enumerable parent) { - if (_enumerator.MoveNext()) + // + // Notice the evaluation order of obtaining the enumerator and subscribing to the + // observable sequence is reversed compared to the operator's signature. This is + // required to make sure the enumerator is available as soon as the observer can + // be called. Otherwise, we end up having a race for the initialization and use + // of the _rightEnumerator field. + // + try + { + _enumerator = parent._second.GetEnumerator(); + } + catch (Exception exception) { - var current = _enumerator.Current; - equal = _parent._comparer.Equals(value, current); + base._observer.OnError(exception); + base.Dispose(); + return Disposable.Empty; } + + return StableCompositeDisposable.Create( + parent._first.SubscribeSafe(this), + _enumerator + ); } - catch (Exception exception) + + public void OnNext(TSource value) { - base._observer.OnError(exception); - base.Dispose(); - return; + var equal = false; + + try + { + if (_enumerator.MoveNext()) + { + var current = _enumerator.Current; + equal = _comparer.Equals(value, current); + } + } + catch (Exception exception) + { + base._observer.OnError(exception); + base.Dispose(); + return; + } + + if (!equal) + { + base._observer.OnNext(false); + base._observer.OnCompleted(); + base.Dispose(); + } } - if (!equal) + public void OnError(Exception error) { - base._observer.OnNext(false); - base._observer.OnCompleted(); + base._observer.OnError(error); base.Dispose(); } - } - public void OnError(Exception error) - { - base._observer.OnError(error); - base.Dispose(); - } + public void OnCompleted() + { + var hasNext = false; - public void OnCompleted() - { - var hasNext = false; + try + { + hasNext = _enumerator.MoveNext(); + } + catch (Exception exception) + { + base._observer.OnError(exception); + base.Dispose(); + return; + } - try - { - hasNext = _enumerator.MoveNext(); - } - catch (Exception exception) - { - base._observer.OnError(exception); + base._observer.OnNext(!hasNext); + base._observer.OnCompleted(); base.Dispose(); - return; } - - base._observer.OnNext(!hasNext); - base._observer.OnCompleted(); - base.Dispose(); } } } diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/SingleAsync.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/SingleAsync.cs index 782d2e30e7..5e3c4bc2e5 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/SingleAsync.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/SingleAsync.cs @@ -4,148 +4,154 @@ namespace System.Reactive.Linq.ObservableImpl { - internal sealed class SingleAsync : Producer + internal static class SingleAsync { - private readonly IObservable _source; - private readonly Func _predicate; - private readonly bool _throwOnEmpty; - - public SingleAsync(IObservable source, Func predicate, bool throwOnEmpty) + internal sealed class Sequence : Producer { - _source = source; - _predicate = predicate; - _throwOnEmpty = throwOnEmpty; - } + private readonly IObservable _source; - protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) - { - if (_predicate != null) + public Sequence(IObservable source) { - var sink = new SingleAsyncImpl(this, observer, cancel); - setSink(sink); - return _source.SubscribeSafe(sink); + _source = source; } - else + + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - var sink = new _(this, observer, cancel); + var sink = new _(observer, cancel); setSink(sink); return _source.SubscribeSafe(sink); } - } - - class _ : Sink, IObserver - { - private readonly SingleAsync _parent; - private TSource _value; - private bool _seenValue; - public _(SingleAsync parent, IObserver observer, IDisposable cancel) - : base(observer, cancel) + private sealed class _ : Sink, IObserver { - _parent = parent; + private TSource _value; + private bool _seenValue; - _value = default(TSource); - _seenValue = false; - } - - public void OnNext(TSource value) - { - if (_seenValue) + public _(IObserver observer, IDisposable cancel) + : base(observer, cancel) { - base._observer.OnError(new InvalidOperationException(Strings_Linq.MORE_THAN_ONE_ELEMENT)); - base.Dispose(); - return; + _value = default(TSource); + _seenValue = false; } - _value = value; - _seenValue = true; - } + public void OnNext(TSource value) + { + if (_seenValue) + { + base._observer.OnError(new InvalidOperationException(Strings_Linq.MORE_THAN_ONE_ELEMENT)); + base.Dispose(); + return; + } - public void OnError(Exception error) - { - base._observer.OnError(error); - base.Dispose(); - } + _value = value; + _seenValue = true; + } - public void OnCompleted() - { - if (!_seenValue && _parent._throwOnEmpty) + public void OnError(Exception error) { - base._observer.OnError(new InvalidOperationException(Strings_Linq.NO_ELEMENTS)); + base._observer.OnError(error); + base.Dispose(); } - else + + public void OnCompleted() { - base._observer.OnNext(_value); - base._observer.OnCompleted(); - } + if (!_seenValue) + { + base._observer.OnError(new InvalidOperationException(Strings_Linq.NO_ELEMENTS)); + } + else + { + base._observer.OnNext(_value); + base._observer.OnCompleted(); + } - base.Dispose(); + base.Dispose(); + } } } - class SingleAsyncImpl : Sink, IObserver + internal sealed class Predicate : Producer { - private readonly SingleAsync _parent; - private TSource _value; - private bool _seenValue; + private readonly IObservable _source; + private readonly Func _predicate; - public SingleAsyncImpl(SingleAsync parent, IObserver observer, IDisposable cancel) - : base(observer, cancel) + public Predicate(IObservable source, Func predicate) { - _parent = parent; + _source = source; + _predicate = predicate; + } - _value = default(TSource); - _seenValue = false; + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) + { + var sink = new _(_predicate, observer, cancel); + setSink(sink); + return _source.SubscribeSafe(sink); } - public void OnNext(TSource value) + private sealed class _ : Sink, IObserver { - var b = false; + private readonly Func _predicate; + private TSource _value; + private bool _seenValue; - try - { - b = _parent._predicate(value); - } - catch (Exception ex) + public _(Func predicate, IObserver observer, IDisposable cancel) + : base(observer, cancel) { - base._observer.OnError(ex); - base.Dispose(); - return; + _predicate = predicate; + + _value = default(TSource); + _seenValue = false; } - if (b) + public void OnNext(TSource value) { - if (_seenValue) + var b = false; + + try { - base._observer.OnError(new InvalidOperationException(Strings_Linq.MORE_THAN_ONE_MATCHING_ELEMENT)); + b = _predicate(value); + } + catch (Exception ex) + { + base._observer.OnError(ex); base.Dispose(); return; } - _value = value; - _seenValue = true; + if (b) + { + if (_seenValue) + { + base._observer.OnError(new InvalidOperationException(Strings_Linq.MORE_THAN_ONE_MATCHING_ELEMENT)); + base.Dispose(); + return; + } + + _value = value; + _seenValue = true; + } } - } - - public void OnError(Exception error) - { - base._observer.OnError(error); - base.Dispose(); - } - public void OnCompleted() - { - if (!_seenValue && _parent._throwOnEmpty) + public void OnError(Exception error) { - base._observer.OnError(new InvalidOperationException(Strings_Linq.NO_MATCHING_ELEMENTS)); + base._observer.OnError(error); + base.Dispose(); } - else + + public void OnCompleted() { - base._observer.OnNext(_value); - base._observer.OnCompleted(); - } + if (!_seenValue) + { + base._observer.OnError(new InvalidOperationException(Strings_Linq.NO_MATCHING_ELEMENTS)); + } + else + { + base._observer.OnNext(_value); + base._observer.OnCompleted(); + } - base.Dispose(); + base.Dispose(); + } } } } diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/SingleOrDefaultAsync.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/SingleOrDefaultAsync.cs new file mode 100644 index 0000000000..2844329f69 --- /dev/null +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/SingleOrDefaultAsync.cs @@ -0,0 +1,142 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the Apache 2.0 License. +// See the LICENSE file in the project root for more information. + +namespace System.Reactive.Linq.ObservableImpl +{ + internal static class SingleOrDefaultAsync + { + internal sealed class Sequence : Producer + { + private readonly IObservable _source; + + public Sequence(IObservable source) + { + _source = source; + } + + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) + { + var sink = new _(observer, cancel); + setSink(sink); + return _source.SubscribeSafe(sink); + } + + private sealed class _ : Sink, IObserver + { + private TSource _value; + private bool _seenValue; + + public _(IObserver observer, IDisposable cancel) + : base(observer, cancel) + { + _value = default(TSource); + _seenValue = false; + } + + public void OnNext(TSource value) + { + if (_seenValue) + { + base._observer.OnError(new InvalidOperationException(Strings_Linq.MORE_THAN_ONE_ELEMENT)); + base.Dispose(); + return; + } + + _value = value; + _seenValue = true; + } + + public void OnError(Exception error) + { + base._observer.OnError(error); + base.Dispose(); + } + + public void OnCompleted() + { + base._observer.OnNext(_value); + base._observer.OnCompleted(); + base.Dispose(); + } + } + } + + internal sealed class Predicate : Producer + { + private readonly IObservable _source; + private readonly Func _predicate; + + public Predicate(IObservable source, Func predicate) + { + _source = source; + _predicate = predicate; + } + + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) + { + var sink = new _(_predicate, observer, cancel); + setSink(sink); + return _source.SubscribeSafe(sink); + } + + private sealed class _ : Sink, IObserver + { + private readonly Func _predicate; + private TSource _value; + private bool _seenValue; + + public _(Func predicate, IObserver observer, IDisposable cancel) + : base(observer, cancel) + { + _predicate = predicate; + + _value = default(TSource); + _seenValue = false; + } + + public void OnNext(TSource value) + { + var b = false; + + try + { + b = _predicate(value); + } + catch (Exception ex) + { + base._observer.OnError(ex); + base.Dispose(); + return; + } + + if (b) + { + if (_seenValue) + { + base._observer.OnError(new InvalidOperationException(Strings_Linq.MORE_THAN_ONE_MATCHING_ELEMENT)); + base.Dispose(); + return; + } + + _value = value; + _seenValue = true; + } + } + + public void OnError(Exception error) + { + base._observer.OnError(error); + base.Dispose(); + } + + public void OnCompleted() + { + base._observer.OnNext(_value); + base._observer.OnCompleted(); + base.Dispose(); + } + } + } + } +} diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Skip.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Skip.cs index 8d47d300fc..7d051d47ff 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Skip.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Skip.cs @@ -7,143 +7,145 @@ namespace System.Reactive.Linq.ObservableImpl { - internal sealed class Skip : Producer + internal static class Skip { - private readonly IObservable _source; - private readonly int _count; - private readonly TimeSpan _duration; - internal readonly IScheduler _scheduler; - - public Skip(IObservable source, int count) - { - _source = source; - _count = count; - } - - public Skip(IObservable source, TimeSpan duration, IScheduler scheduler) - { - _source = source; - _duration = duration; - _scheduler = scheduler; - } - - public IObservable Combine(int count) - { - // - // Sum semantics: - // - // xs --o--o--o--o--o--o--| xs --o--o--o--o--o--o--| - // xs.Skip(2) --x--x--o--o--o--o--| xs.Skip(3) --x--x--x--o--o--o--| - // xs.Skip(2).Skip(3) --------x--x--x--o--| xs.Skip(3).Skip(2) -----------x--x--o--| - // - return new Skip(_source, _count + count); - } - - public IObservable Combine(TimeSpan duration) - { - // - // Maximum semantics: - // - // t 0--1--2--3--4--5--6--7-> t 0--1--2--3--4--5--6--7-> - // - // xs --o--o--o--o--o--o--| xs --o--o--o--o--o--o--| - // xs.Skip(2s) xxxxxxx-o--o--o--o--| xs.Skip(3s) xxxxxxxxxx-o--o--o--| - // xs.Skip(2s).Skip(3s) xxxxxxxxxx-o--o--o--| xs.Skip(3s).Skip(2s) xxxxxxx----o--o--o--| - // - if (duration <= _duration) - return this; - else - return new Skip(_source, duration, _scheduler); - } - - protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) - { - if (_scheduler == null) - { - var sink = new _(this, observer, cancel); - setSink(sink); - return _source.SubscribeSafe(sink); - } - else - { - var sink = new SkipImpl(this, observer, cancel); - setSink(sink); - return sink.Run(); - } - } - - class _ : Sink, IObserver + internal sealed class Count : Producer { - private readonly Skip _parent; - private int _remaining; + private readonly IObservable _source; + private readonly int _count; - public _(Skip parent, IObserver observer, IDisposable cancel) - : base(observer, cancel) + public Count(IObservable source, int count) { - _parent = parent; - _remaining = _parent._count; + _source = source; + _count = count; } - public void OnNext(TSource value) + public IObservable Combine(int count) { - if (_remaining <= 0) - base._observer.OnNext(value); - else - _remaining--; + // + // Sum semantics: + // + // xs --o--o--o--o--o--o--| xs --o--o--o--o--o--o--| + // xs.Skip(2) --x--x--o--o--o--o--| xs.Skip(3) --x--x--x--o--o--o--| + // xs.Skip(2).Skip(3) --------x--x--x--o--| xs.Skip(3).Skip(2) -----------x--x--o--| + // + return new Count(_source, _count + count); } - public void OnError(Exception error) + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - base._observer.OnError(error); - base.Dispose(); + var sink = new _(_count, observer, cancel); + setSink(sink); + return _source.SubscribeSafe(sink); } - public void OnCompleted() + private sealed class _ : Sink, IObserver { - base._observer.OnCompleted(); - base.Dispose(); + private int _remaining; + + public _(int count, IObserver observer, IDisposable cancel) + : base(observer, cancel) + { + _remaining = count; + } + + public void OnNext(TSource value) + { + if (_remaining <= 0) + base._observer.OnNext(value); + else + _remaining--; + } + + public void OnError(Exception error) + { + base._observer.OnError(error); + base.Dispose(); + } + + public void OnCompleted() + { + base._observer.OnCompleted(); + base.Dispose(); + } } } - class SkipImpl : Sink, IObserver + internal sealed class Time : Producer { - private readonly Skip _parent; - private volatile bool _open; + private readonly IObservable _source; + private readonly TimeSpan _duration; + internal readonly IScheduler _scheduler; - public SkipImpl(Skip parent, IObserver observer, IDisposable cancel) - : base(observer, cancel) + public Time(IObservable source, TimeSpan duration, IScheduler scheduler) { - _parent = parent; + _source = source; + _duration = duration; + _scheduler = scheduler; } - public IDisposable Run() + public IObservable Combine(TimeSpan duration) { - var t = _parent._scheduler.Schedule(_parent._duration, Tick); - var d = _parent._source.SubscribeSafe(this); - return StableCompositeDisposable.Create(t, d); - } - - private void Tick() - { - _open = true; - } - - public void OnNext(TSource value) - { - if (_open) - base._observer.OnNext(value); + // + // Maximum semantics: + // + // t 0--1--2--3--4--5--6--7-> t 0--1--2--3--4--5--6--7-> + // + // xs --o--o--o--o--o--o--| xs --o--o--o--o--o--o--| + // xs.Skip(2s) xxxxxxx-o--o--o--o--| xs.Skip(3s) xxxxxxxxxx-o--o--o--| + // xs.Skip(2s).Skip(3s) xxxxxxxxxx-o--o--o--| xs.Skip(3s).Skip(2s) xxxxxxx----o--o--o--| + // + if (duration <= _duration) + return this; + else + return new Time(_source, duration, _scheduler); } - public void OnError(Exception error) + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - base._observer.OnError(error); - base.Dispose(); + var sink = new _(observer, cancel); + setSink(sink); + return sink.Run(this); } - public void OnCompleted() + private sealed class _ : Sink, IObserver { - base._observer.OnCompleted(); - base.Dispose(); + private volatile bool _open; + + public _(IObserver observer, IDisposable cancel) + : base(observer, cancel) + { + } + + public IDisposable Run(Time parent) + { + var t = parent._scheduler.Schedule(parent._duration, Tick); + var d = parent._source.SubscribeSafe(this); + return StableCompositeDisposable.Create(t, d); + } + + private void Tick() + { + _open = true; + } + + public void OnNext(TSource value) + { + if (_open) + base._observer.OnNext(value); + } + + public void OnError(Exception error) + { + base._observer.OnError(error); + base.Dispose(); + } + + public void OnCompleted() + { + base._observer.OnCompleted(); + base.Dispose(); + } } } } diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/SkipLast.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/SkipLast.cs index 06cfa48896..2a8aa79b0c 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/SkipLast.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/SkipLast.cs @@ -7,117 +7,123 @@ namespace System.Reactive.Linq.ObservableImpl { - internal sealed class SkipLast : Producer + internal static class SkipLast { - private readonly IObservable _source; - private readonly int _count; - private readonly TimeSpan _duration; - private readonly IScheduler _scheduler; - - public SkipLast(IObservable source, int count) - { - _source = source; - _count = count; - } - - public SkipLast(IObservable source, TimeSpan duration, IScheduler scheduler) - { - _source = source; - _duration = duration; - _scheduler = scheduler; - } - - protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) - { - if (_scheduler == null) - { - var sink = new _(this, observer, cancel); - setSink(sink); - return _source.SubscribeSafe(sink); - } - else - { - var sink = new SkipLastImpl(this, observer, cancel); - setSink(sink); - return sink.Run(); - } - } - - class _ : Sink, IObserver + internal sealed class Count : Producer { - private readonly SkipLast _parent; - private Queue _queue; - - public _(SkipLast parent, IObserver observer, IDisposable cancel) - : base(observer, cancel) - { - _parent = parent; - _queue = new Queue(); - } + private readonly IObservable _source; + private readonly int _count; - public void OnNext(TSource value) + public Count(IObservable source, int count) { - _queue.Enqueue(value); - if (_queue.Count > _parent._count) - base._observer.OnNext(_queue.Dequeue()); + _source = source; + _count = count; } - public void OnError(Exception error) + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - base._observer.OnError(error); - base.Dispose(); + var sink = new _(_count, observer, cancel); + setSink(sink); + return _source.SubscribeSafe(sink); } - public void OnCompleted() + private sealed class _ : Sink, IObserver { - base._observer.OnCompleted(); - base.Dispose(); + private int _count; + private Queue _queue; + + public _(int count, IObserver observer, IDisposable cancel) + : base(observer, cancel) + { + _count = count; + _queue = new Queue(); + } + + public void OnNext(TSource value) + { + _queue.Enqueue(value); + if (_queue.Count > _count) + base._observer.OnNext(_queue.Dequeue()); + } + + public void OnError(Exception error) + { + base._observer.OnError(error); + base.Dispose(); + } + + public void OnCompleted() + { + base._observer.OnCompleted(); + base.Dispose(); + } } } - class SkipLastImpl : Sink, IObserver + internal sealed class Time : Producer { - private readonly SkipLast _parent; - private Queue> _queue; - - public SkipLastImpl(SkipLast parent, IObserver observer, IDisposable cancel) - : base(observer, cancel) - { - _parent = parent; - _queue = new Queue>(); - } - - private IStopwatch _watch; - - public IDisposable Run() - { - _watch = _parent._scheduler.StartStopwatch(); + private readonly IObservable _source; + private readonly TimeSpan _duration; + private readonly IScheduler _scheduler; - return _parent._source.SubscribeSafe(this); - } - - public void OnNext(TSource value) + public Time(IObservable source, TimeSpan duration, IScheduler scheduler) { - var now = _watch.Elapsed; - _queue.Enqueue(new System.Reactive.TimeInterval(value, now)); - while (_queue.Count > 0 && now - _queue.Peek().Interval >= _parent._duration) - base._observer.OnNext(_queue.Dequeue().Value); + _source = source; + _duration = duration; + _scheduler = scheduler; } - public void OnError(Exception error) + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - base._observer.OnError(error); - base.Dispose(); + var sink = new _(_duration, observer, cancel); + setSink(sink); + return sink.Run(this); } - public void OnCompleted() + private sealed class _ : Sink, IObserver { - var now = _watch.Elapsed; - while (_queue.Count > 0 && now - _queue.Peek().Interval >= _parent._duration) - base._observer.OnNext(_queue.Dequeue().Value); - - base._observer.OnCompleted(); - base.Dispose(); + private readonly TimeSpan _duration; + private Queue> _queue; + + public _(TimeSpan duration, IObserver observer, IDisposable cancel) + : base(observer, cancel) + { + _duration = duration; + _queue = new Queue>(); + } + + private IStopwatch _watch; + + public IDisposable Run(Time parent) + { + _watch = parent._scheduler.StartStopwatch(); + + return parent._source.SubscribeSafe(this); + } + + public void OnNext(TSource value) + { + var now = _watch.Elapsed; + _queue.Enqueue(new System.Reactive.TimeInterval(value, now)); + while (_queue.Count > 0 && now - _queue.Peek().Interval >= _duration) + base._observer.OnNext(_queue.Dequeue().Value); + } + + public void OnError(Exception error) + { + base._observer.OnError(error); + base.Dispose(); + } + + public void OnCompleted() + { + var now = _watch.Elapsed; + while (_queue.Count > 0 && now - _queue.Peek().Interval >= _duration) + base._observer.OnNext(_queue.Dequeue().Value); + + base._observer.OnCompleted(); + base.Dispose(); + } } } } diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/SkipUntil.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/SkipUntil.cs index 17b3ef9fae..f8063ce616 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/SkipUntil.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/SkipUntil.cs @@ -20,28 +20,25 @@ public SkipUntil(IObservable source, IObservable other) protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - var sink = new _(this, observer, cancel); + var sink = new _(observer, cancel); setSink(sink); - return sink.Run(); + return sink.Run(this); } - class _ : Sink + private sealed class _ : Sink { - private readonly SkipUntil _parent; - - public _(SkipUntil parent, IObserver observer, IDisposable cancel) + public _(IObserver observer, IDisposable cancel) : base(observer, cancel) { - _parent = parent; } - public IDisposable Run() + public IDisposable Run(SkipUntil parent) { - var sourceObserver = new T(this); - var otherObserver = new O(this, sourceObserver); + var sourceObserver = new SourceObserver(this); + var otherObserver = new OtherObserver(this, sourceObserver); - var sourceSubscription = _parent._source.SubscribeSafe(sourceObserver); - var otherSubscription = _parent._other.SubscribeSafe(otherObserver); + var sourceSubscription = parent._source.SubscribeSafe(sourceObserver); + var otherSubscription = parent._other.SubscribeSafe(otherObserver); sourceObserver.Disposable = sourceSubscription; otherObserver.Disposable = otherSubscription; @@ -52,13 +49,13 @@ public IDisposable Run() ); } - class T : IObserver + private sealed class SourceObserver : IObserver { private readonly _ _parent; public volatile IObserver _observer; private readonly SingleAssignmentDisposable _subscription; - public T(_ parent) + public SourceObserver(_ parent) { _parent = parent; _observer = NopObserver.Instance; @@ -88,13 +85,13 @@ public void OnCompleted() } } - class O : IObserver + private sealed class OtherObserver : IObserver { private readonly _ _parent; - private readonly T _sourceObserver; + private readonly SourceObserver _sourceObserver; private readonly SingleAssignmentDisposable _subscription; - public O(_ parent, T sourceObserver) + public OtherObserver(_ parent, SourceObserver sourceObserver) { _parent = parent; _sourceObserver = sourceObserver; @@ -158,26 +155,24 @@ public IObservable Combine(DateTimeOffset startTime) protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - var sink = new _(this, observer, cancel); + var sink = new _(observer, cancel); setSink(sink); - return sink.Run(); + return sink.Run(this); } - class _ : Sink, IObserver + private sealed class _ : Sink, IObserver { - private readonly SkipUntil _parent; private volatile bool _open; - public _(SkipUntil parent, IObserver observer, IDisposable cancel) + public _(IObserver observer, IDisposable cancel) : base(observer, cancel) { - _parent = parent; } - public IDisposable Run() + public IDisposable Run(SkipUntil parent) { - var t = _parent._scheduler.Schedule(_parent._startTime, Tick); - var d = _parent._source.SubscribeSafe(this); + var t = parent._scheduler.Schedule(parent._startTime, Tick); + var d = parent._source.SubscribeSafe(this); return StableCompositeDisposable.Create(t, d); } diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/SkipWhile.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/SkipWhile.cs index 59c2040927..7705c93754 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/SkipWhile.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/SkipWhile.cs @@ -4,133 +4,149 @@ namespace System.Reactive.Linq.ObservableImpl { - internal sealed class SkipWhile : Producer + internal static class SkipWhile { - private readonly IObservable _source; - private readonly Func _predicate; - private readonly Func _predicateI; - - public SkipWhile(IObservable source, Func predicate) + internal sealed class Predicate : Producer { - _source = source; - _predicate = predicate; - } - - public SkipWhile(IObservable source, Func predicate) - { - _source = source; - _predicateI = predicate; - } + private readonly IObservable _source; + private readonly Func _predicate; - protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) - { - if (_predicate != null) + public Predicate(IObservable source, Func predicate) { - var sink = new _(this, observer, cancel); - setSink(sink); - return _source.SubscribeSafe(sink); + _source = source; + _predicate = predicate; } - else + + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - var sink = new SkipWhileImpl(this, observer, cancel); + var sink = new _(_predicate, observer, cancel); setSink(sink); return _source.SubscribeSafe(sink); } - } - class _ : Sink, IObserver - { - private readonly SkipWhile _parent; - private bool _running; - - public _(SkipWhile parent, IObserver observer, IDisposable cancel) - : base(observer, cancel) + private sealed class _ : Sink, IObserver { - _parent = parent; - _running = false; - } + private Func _predicate; - public void OnNext(TSource value) - { - if (!_running) + public _(Func predicate, IObserver observer, IDisposable cancel) + : base(observer, cancel) + { + _predicate = predicate; + } + + public void OnNext(TSource value) { - try + if (_predicate != null) { - _running = !_parent._predicate(value); + var shouldStart = default(bool); + try + { + shouldStart = !_predicate(value); + } + catch (Exception exception) + { + base._observer.OnError(exception); + base.Dispose(); + return; + } + + if (shouldStart) + { + _predicate = null; + + base._observer.OnNext(value); + } } - catch (Exception exception) + else { - base._observer.OnError(exception); - base.Dispose(); - return; + base._observer.OnNext(value); } } - if (_running) + public void OnError(Exception error) { - base._observer.OnNext(value); + base._observer.OnError(error); + base.Dispose(); } - } - - public void OnError(Exception error) - { - base._observer.OnError(error); - base.Dispose(); - } - public void OnCompleted() - { - base._observer.OnCompleted(); - base.Dispose(); + public void OnCompleted() + { + base._observer.OnCompleted(); + base.Dispose(); + } } } - class SkipWhileImpl : Sink, IObserver + internal sealed class PredicateIndexed : Producer { - private readonly SkipWhile _parent; - private bool _running; - private int _index; + private readonly IObservable _source; + private readonly Func _predicate; + + public PredicateIndexed(IObservable source, Func predicate) + { + _source = source; + _predicate = predicate; + } - public SkipWhileImpl(SkipWhile parent, IObserver observer, IDisposable cancel) - : base(observer, cancel) + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - _parent = parent; - _running = false; - _index = 0; + var sink = new _(_predicate, observer, cancel); + setSink(sink); + return _source.SubscribeSafe(sink); } - public void OnNext(TSource value) + private sealed class _ : Sink, IObserver { - if (!_running) + private Func _predicate; + private int _index; + + public _(Func predicate, IObserver observer, IDisposable cancel) + : base(observer, cancel) { - try + _predicate = predicate; + _index = 0; + } + + public void OnNext(TSource value) + { + if (_predicate != null) { - _running = !_parent._predicateI(value, checked(_index++)); + var shouldStart = default(bool); + try + { + shouldStart = !_predicate(value, checked(_index++)); + } + catch (Exception exception) + { + base._observer.OnError(exception); + base.Dispose(); + return; + } + + if (shouldStart) + { + _predicate = null; + + base._observer.OnNext(value); + } } - catch (Exception exception) + else { - base._observer.OnError(exception); - base.Dispose(); - return; + base._observer.OnNext(value); } } - if (_running) + public void OnError(Exception error) { - base._observer.OnNext(value); + base._observer.OnError(error); + base.Dispose(); } - } - - public void OnError(Exception error) - { - base._observer.OnError(error); - base.Dispose(); - } - public void OnCompleted() - { - base._observer.OnCompleted(); - base.Dispose(); + public void OnCompleted() + { + base._observer.OnCompleted(); + base.Dispose(); + } } } } diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Sum.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Sum.cs index 8a32ab1b4f..c721987757 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Sum.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Sum.cs @@ -20,7 +20,7 @@ protected override IDisposable Run(IObserver observer, IDisposable cance return _source.SubscribeSafe(sink); } - class _ : Sink, IObserver + private sealed class _ : Sink, IObserver { private double _sum; @@ -66,7 +66,7 @@ protected override IDisposable Run(IObserver observer, IDisposable cancel return _source.SubscribeSafe(sink); } - class _ : Sink, IObserver + private sealed class _ : Sink, IObserver { private double _sum; // This is what LINQ to Objects does! @@ -112,7 +112,7 @@ protected override IDisposable Run(IObserver observer, IDisposable canc return _source.SubscribeSafe(sink); } - class _ : Sink, IObserver + private sealed class _ : Sink, IObserver { private decimal _sum; @@ -158,7 +158,7 @@ protected override IDisposable Run(IObserver observer, IDisposable cancel, return _source.SubscribeSafe(sink); } - class _ : Sink, IObserver + private sealed class _ : Sink, IObserver { private int _sum; @@ -215,7 +215,7 @@ protected override IDisposable Run(IObserver observer, IDisposable cancel, return _source.SubscribeSafe(sink); } - class _ : Sink, IObserver + private sealed class _ : Sink, IObserver { private long _sum; @@ -272,7 +272,7 @@ protected override IDisposable Run(IObserver observer, IDisposable canc return _source.SubscribeSafe(sink); } - class _ : Sink, IObserver + private sealed class _ : Sink, IObserver { private double _sum; @@ -319,7 +319,7 @@ protected override IDisposable Run(IObserver observer, IDisposable cance return _source.SubscribeSafe(sink); } - class _ : Sink, IObserver + private sealed class _ : Sink, IObserver { private double _sum; // This is what LINQ to Objects does! @@ -366,7 +366,7 @@ protected override IDisposable Run(IObserver observer, IDisposable can return _source.SubscribeSafe(sink); } - class _ : Sink, IObserver + private sealed class _ : Sink, IObserver { private decimal _sum; @@ -413,7 +413,7 @@ protected override IDisposable Run(IObserver observer, IDisposable cancel, return _source.SubscribeSafe(sink); } - class _ : Sink, IObserver + private sealed class _ : Sink, IObserver { private int _sum; @@ -471,7 +471,7 @@ protected override IDisposable Run(IObserver observer, IDisposable cancel return _source.SubscribeSafe(sink); } - class _ : Sink, IObserver + private sealed class _ : Sink, IObserver { private long _sum; diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Switch.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Switch.cs index 325792b194..55c7b647fb 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Switch.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Switch.cs @@ -17,31 +17,28 @@ public Switch(IObservable> sources) protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - var sink = new _(this, observer, cancel); + var sink = new _(observer, cancel); setSink(sink); - return sink.Run(); + return sink.Run(this); } - class _ : Sink, IObserver> + private sealed class _ : Sink, IObserver> { - private readonly Switch _parent; + private readonly object _gate = new object(); - public _(Switch parent, IObserver observer, IDisposable cancel) + public _(IObserver observer, IDisposable cancel) : base(observer, cancel) { - _parent = parent; } - private object _gate; private IDisposable _subscription; private SerialDisposable _innerSubscription; private bool _isStopped; private ulong _latest; private bool _hasLatest; - public IDisposable Run() + public IDisposable Run(Switch parent) { - _gate = new object(); _innerSubscription = new SerialDisposable(); _isStopped = false; _latest = 0UL; @@ -49,7 +46,7 @@ public IDisposable Run() var subscription = new SingleAssignmentDisposable(); _subscription = subscription; - subscription.Disposable = _parent._sources.SubscribeSafe(this); + subscription.Disposable = parent._sources.SubscribeSafe(this); return StableCompositeDisposable.Create(_subscription, _innerSubscription); } @@ -65,7 +62,7 @@ public void OnNext(IObservable value) var d = new SingleAssignmentDisposable(); _innerSubscription.Disposable = d; - d.Disposable = value.SubscribeSafe(new Iter(this, id, d)); + d.Disposable = value.SubscribeSafe(new InnerObserver(this, id, d)); } public void OnError(Exception error) @@ -91,13 +88,13 @@ public void OnCompleted() } } - class Iter : IObserver + private sealed class InnerObserver : IObserver { private readonly _ _parent; private readonly ulong _id; private readonly IDisposable _self; - public Iter(_ parent, ulong id, IDisposable self) + public InnerObserver(_ parent, ulong id, IDisposable self) { _parent = parent; _id = id; @@ -109,7 +106,9 @@ public void OnNext(TSource value) lock (_parent._gate) { if (_parent._latest == _id) + { _parent._observer.OnNext(value); + } } } diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Synchronize.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Synchronize.cs index 80304d42d9..51de5811aa 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Synchronize.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Synchronize.cs @@ -22,21 +22,19 @@ public Synchronize(IObservable source) protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - var sink = new _(this, observer, cancel); + var sink = new _(_gate, observer, cancel); setSink(sink); return _source.Subscribe(sink); } - class _ : Sink, IObserver + private sealed class _ : Sink, IObserver { - private readonly Synchronize _parent; - private object _gate; + private readonly object _gate; - public _(Synchronize parent, IObserver observer, IDisposable cancel) + public _(object gate, IObserver observer, IDisposable cancel) : base(observer, cancel) { - _parent = parent; - _gate = _parent._gate ?? new object(); + _gate = gate ?? new object(); } public void OnNext(TSource value) diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Take.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Take.cs index bb0c406110..4dead392c5 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Take.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Take.cs @@ -7,167 +7,168 @@ namespace System.Reactive.Linq.ObservableImpl { - internal sealed class Take : Producer + internal static class Take { - private readonly IObservable _source; - private readonly int _count; - private readonly TimeSpan _duration; - internal readonly IScheduler _scheduler; - - public Take(IObservable source, int count) - { - _source = source; - _count = count; - } - - public Take(IObservable source, TimeSpan duration, IScheduler scheduler) - { - _source = source; - _duration = duration; - _scheduler = scheduler; - } - - public IObservable Combine(int count) + internal sealed class Count : Producer { - // - // Minimum semantics: - // - // xs --o--o--o--o--o--o--| xs --o--o--o--o--o--o--| - // xs.Take(5) --o--o--o--o--o| xs.Take(3) --o--o--o| - // xs.Take(5).Take(3) --o--o--o| xs.Take(3).Take(5) --o--o--o| - // - if (_count <= count) - return this; - else - return new Take(_source, count); - } + private readonly IObservable _source; + private readonly int _count; - public IObservable Combine(TimeSpan duration) - { - // - // Minimum semantics: - // - // t 0--1--2--3--4--5--6--7-> t 0--1--2--3--4--5--6--7-> - // - // xs --o--o--o--o--o--o--| xs --o--o--o--o--o--o--| - // xs.Take(5s) --o--o--o--o--o| xs.Take(3s) --o--o--o| - // xs.Take(5s).Take(3s) --o--o--o| xs.Take(3s).Take(5s) --o--o--o| - // - if (_duration <= duration) - return this; - else - return new Take(_source, duration, _scheduler); - } - - protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) - { - if (_scheduler == null) + public Count(IObservable source, int count) { - var sink = new _(this, observer, cancel); - setSink(sink); - return _source.SubscribeSafe(sink); + _source = source; + _count = count; } - else + + public IObservable Combine(int count) { - var sink = new TakeImpl(this, observer, cancel); - setSink(sink); - return sink.Run(); + // + // Minimum semantics: + // + // xs --o--o--o--o--o--o--| xs --o--o--o--o--o--o--| + // xs.Take(5) --o--o--o--o--o| xs.Take(3) --o--o--o| + // xs.Take(5).Take(3) --o--o--o| xs.Take(3).Take(5) --o--o--o| + // + if (_count <= count) + return this; + else + return new Count(_source, count); } - } - - class _ : Sink, IObserver - { - private readonly Take _parent; - private int _remaining; - public _(Take parent, IObserver observer, IDisposable cancel) - : base(observer, cancel) + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - _parent = parent; - _remaining = _parent._count; + var sink = new _(_count, observer, cancel); + setSink(sink); + return _source.SubscribeSafe(sink); } - public void OnNext(TSource value) + private sealed class _ : Sink, IObserver { - if (_remaining > 0) + private int _remaining; + + public _(int count, IObserver observer, IDisposable cancel) + : base(observer, cancel) { - --_remaining; - base._observer.OnNext(value); + _remaining = count; + } - if (_remaining == 0) + public void OnNext(TSource value) + { + if (_remaining > 0) { - base._observer.OnCompleted(); - base.Dispose(); + --_remaining; + base._observer.OnNext(value); + + if (_remaining == 0) + { + base._observer.OnCompleted(); + base.Dispose(); + } } } - } - public void OnError(Exception error) - { - base._observer.OnError(error); - base.Dispose(); - } + public void OnError(Exception error) + { + base._observer.OnError(error); + base.Dispose(); + } - public void OnCompleted() - { - base._observer.OnCompleted(); - base.Dispose(); + public void OnCompleted() + { + base._observer.OnCompleted(); + base.Dispose(); + } } } - class TakeImpl : Sink, IObserver + internal sealed class Time : Producer { - private readonly Take _parent; + private readonly IObservable _source; + private readonly TimeSpan _duration; + internal readonly IScheduler _scheduler; - public TakeImpl(Take parent, IObserver observer, IDisposable cancel) - : base(observer, cancel) + public Time(IObservable source, TimeSpan duration, IScheduler scheduler) { - _parent = parent; + _source = source; + _duration = duration; + _scheduler = scheduler; } - private object _gate; - - public IDisposable Run() + public IObservable Combine(TimeSpan duration) { - _gate = new object(); + // + // Minimum semantics: + // + // t 0--1--2--3--4--5--6--7-> t 0--1--2--3--4--5--6--7-> + // + // xs --o--o--o--o--o--o--| xs --o--o--o--o--o--o--| + // xs.Take(5s) --o--o--o--o--o| xs.Take(3s) --o--o--o| + // xs.Take(5s).Take(3s) --o--o--o| xs.Take(3s).Take(5s) --o--o--o| + // + if (_duration <= duration) + return this; + else + return new Time(_source, duration, _scheduler); + } - var t = _parent._scheduler.Schedule(_parent._duration, Tick); - var d = _parent._source.SubscribeSafe(this); - return StableCompositeDisposable.Create(t, d); + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) + { + var sink = new _(observer, cancel); + setSink(sink); + return sink.Run(this); } - private void Tick() + private sealed class _ : Sink, IObserver { - lock (_gate) + public _(IObserver observer, IDisposable cancel) + : base(observer, cancel) { - base._observer.OnCompleted(); - base.Dispose(); } - } - public void OnNext(TSource value) - { - lock (_gate) + private object _gate; + + public IDisposable Run(Time parent) { - base._observer.OnNext(value); + _gate = new object(); + + var t = parent._scheduler.Schedule(parent._duration, Tick); + var d = parent._source.SubscribeSafe(this); + return StableCompositeDisposable.Create(t, d); } - } - public void OnError(Exception error) - { - lock (_gate) + private void Tick() { - base._observer.OnError(error); - base.Dispose(); + lock (_gate) + { + base._observer.OnCompleted(); + base.Dispose(); + } } - } - public void OnCompleted() - { - lock (_gate) + public void OnNext(TSource value) { - base._observer.OnCompleted(); - base.Dispose(); + lock (_gate) + { + base._observer.OnNext(value); + } + } + + public void OnError(Exception error) + { + lock (_gate) + { + base._observer.OnError(error); + base.Dispose(); + } + } + + public void OnCompleted() + { + lock (_gate) + { + base._observer.OnCompleted(); + base.Dispose(); + } } } } diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/TakeLast.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/TakeLast.cs index 9717ce5c10..d4effeafa8 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/TakeLast.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/TakeLast.cs @@ -8,221 +8,232 @@ namespace System.Reactive.Linq.ObservableImpl { - internal sealed class TakeLast : Producer + internal static class TakeLast { - private readonly IObservable _source; - private readonly int _count; - private readonly TimeSpan _duration; - private readonly IScheduler _scheduler; - private readonly IScheduler _loopScheduler; - - public TakeLast(IObservable source, int count, IScheduler loopScheduler) - { - _source = source; - _count = count; - _loopScheduler = loopScheduler; - } - - public TakeLast(IObservable source, TimeSpan duration, IScheduler scheduler, IScheduler loopScheduler) + internal sealed class Count : Producer { - _source = source; - _duration = duration; - _scheduler = scheduler; - _loopScheduler = loopScheduler; - } + private readonly IObservable _source; + private readonly int _count; + private readonly IScheduler _loopScheduler; - protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) - { - if (_scheduler == null) + public Count(IObservable source, int count, IScheduler loopScheduler) { - var sink = new _(this, observer, cancel); - setSink(sink); - return sink.Run(); + _source = source; + _count = count; + _loopScheduler = loopScheduler; } - else + + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - var sink = new TakeLastImpl(this, observer, cancel); + var sink = new _(this, observer, cancel); setSink(sink); return sink.Run(); } - } - class _ : Sink, IObserver - { - private readonly TakeLast _parent; - private Queue _queue; - - public _(TakeLast parent, IObserver observer, IDisposable cancel) - : base(observer, cancel) + private sealed class _ : Sink, IObserver { - _parent = parent; - _queue = new Queue(); - } + // CONSIDER: This sink has a parent reference that can be considered for removal. - private SingleAssignmentDisposable _subscription; - private SingleAssignmentDisposable _loop; + private readonly Count _parent; + private Queue _queue; - public IDisposable Run() - { - _subscription = new SingleAssignmentDisposable(); - _loop = new SingleAssignmentDisposable(); - - _subscription.Disposable = _parent._source.SubscribeSafe(this); - - return StableCompositeDisposable.Create(_subscription, _loop); - } + public _(Count parent, IObserver observer, IDisposable cancel) + : base(observer, cancel) + { + _parent = parent; + _queue = new Queue(); + } - public void OnNext(TSource value) - { - _queue.Enqueue(value); - if (_queue.Count > _parent._count) - _queue.Dequeue(); - } + private SingleAssignmentDisposable _subscription; + private SingleAssignmentDisposable _loop; - public void OnError(Exception error) - { - base._observer.OnError(error); - base.Dispose(); - } + public IDisposable Run() + { + _subscription = new SingleAssignmentDisposable(); + _loop = new SingleAssignmentDisposable(); - public void OnCompleted() - { - _subscription.Dispose(); + _subscription.Disposable = _parent._source.SubscribeSafe(this); - var longRunning = _parent._loopScheduler.AsLongRunning(); - if (longRunning != null) - _loop.Disposable = longRunning.ScheduleLongRunning(Loop); - else - _loop.Disposable = _parent._loopScheduler.Schedule(LoopRec); - } + return StableCompositeDisposable.Create(_subscription, _loop); + } - private void LoopRec(Action recurse) - { - if (_queue.Count > 0) + public void OnNext(TSource value) { - base._observer.OnNext(_queue.Dequeue()); - recurse(); + _queue.Enqueue(value); + if (_queue.Count > _parent._count) + _queue.Dequeue(); } - else + + public void OnError(Exception error) { - base._observer.OnCompleted(); + base._observer.OnError(error); base.Dispose(); } - } - private void Loop(ICancelable cancel) - { - var n = _queue.Count; + public void OnCompleted() + { + _subscription.Dispose(); + + var longRunning = _parent._loopScheduler.AsLongRunning(); + if (longRunning != null) + _loop.Disposable = longRunning.ScheduleLongRunning(Loop); + else + _loop.Disposable = _parent._loopScheduler.Schedule(LoopRec); + } - while (!cancel.IsDisposed) + private void LoopRec(Action recurse) { - if (n == 0) + if (_queue.Count > 0) { - base._observer.OnCompleted(); - break; + base._observer.OnNext(_queue.Dequeue()); + recurse(); } else - base._observer.OnNext(_queue.Dequeue()); - - n--; + { + base._observer.OnCompleted(); + base.Dispose(); + } } - base.Dispose(); + private void Loop(ICancelable cancel) + { + var n = _queue.Count; + + while (!cancel.IsDisposed) + { + if (n == 0) + { + base._observer.OnCompleted(); + break; + } + else + base._observer.OnNext(_queue.Dequeue()); + + n--; + } + + base.Dispose(); + } } } - class TakeLastImpl : Sink, IObserver + internal sealed class Time : Producer { - private readonly TakeLast _parent; - private Queue> _queue; + private readonly IObservable _source; + private readonly TimeSpan _duration; + private readonly IScheduler _scheduler; + private readonly IScheduler _loopScheduler; - public TakeLastImpl(TakeLast parent, IObserver observer, IDisposable cancel) - : base(observer, cancel) + public Time(IObservable source, TimeSpan duration, IScheduler scheduler, IScheduler loopScheduler) { - _parent = parent; - _queue = new Queue>(); + _source = source; + _duration = duration; + _scheduler = scheduler; + _loopScheduler = loopScheduler; } - private SingleAssignmentDisposable _subscription; - private SingleAssignmentDisposable _loop; - private IStopwatch _watch; - - public IDisposable Run() + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - _subscription = new SingleAssignmentDisposable(); - _loop = new SingleAssignmentDisposable(); - - _watch = _parent._scheduler.StartStopwatch(); - _subscription.Disposable = _parent._source.SubscribeSafe(this); - - return StableCompositeDisposable.Create(_subscription, _loop); + var sink = new _(this, observer, cancel); + setSink(sink); + return sink.Run(); } - public void OnNext(TSource value) + private sealed class _ : Sink, IObserver { - var now = _watch.Elapsed; - _queue.Enqueue(new System.Reactive.TimeInterval(value, now)); - Trim(now); - } + // CONSIDER: This sink has a parent reference that can be considered for removal. - public void OnError(Exception error) - { - base._observer.OnError(error); - base.Dispose(); - } + private readonly Time _parent; + private Queue> _queue; - public void OnCompleted() - { - _subscription.Dispose(); + public _(Time parent, IObserver observer, IDisposable cancel) + : base(observer, cancel) + { + _parent = parent; + _queue = new Queue>(); + } - var now = _watch.Elapsed; - Trim(now); + private SingleAssignmentDisposable _subscription; + private SingleAssignmentDisposable _loop; + private IStopwatch _watch; - var longRunning = _parent._loopScheduler.AsLongRunning(); - if (longRunning != null) - _loop.Disposable = longRunning.ScheduleLongRunning(Loop); - else - _loop.Disposable = _parent._loopScheduler.Schedule(LoopRec); - } + public IDisposable Run() + { + _subscription = new SingleAssignmentDisposable(); + _loop = new SingleAssignmentDisposable(); - private void LoopRec(Action recurse) - { - if (_queue.Count > 0) + _watch = _parent._scheduler.StartStopwatch(); + _subscription.Disposable = _parent._source.SubscribeSafe(this); + + return StableCompositeDisposable.Create(_subscription, _loop); + } + + public void OnNext(TSource value) { - base._observer.OnNext(_queue.Dequeue().Value); - recurse(); + var now = _watch.Elapsed; + _queue.Enqueue(new System.Reactive.TimeInterval(value, now)); + Trim(now); } - else + + public void OnError(Exception error) { - base._observer.OnCompleted(); + base._observer.OnError(error); base.Dispose(); } - } - private void Loop(ICancelable cancel) - { - var n = _queue.Count; + public void OnCompleted() + { + _subscription.Dispose(); + + var now = _watch.Elapsed; + Trim(now); + + var longRunning = _parent._loopScheduler.AsLongRunning(); + if (longRunning != null) + _loop.Disposable = longRunning.ScheduleLongRunning(Loop); + else + _loop.Disposable = _parent._loopScheduler.Schedule(LoopRec); + } - while (!cancel.IsDisposed) + private void LoopRec(Action recurse) { - if (n == 0) + if (_queue.Count > 0) { - base._observer.OnCompleted(); - break; + base._observer.OnNext(_queue.Dequeue().Value); + recurse(); } else - base._observer.OnNext(_queue.Dequeue().Value); - - n--; + { + base._observer.OnCompleted(); + base.Dispose(); + } } - base.Dispose(); - } + private void Loop(ICancelable cancel) + { + var n = _queue.Count; - private void Trim(TimeSpan now) - { - while (_queue.Count > 0 && now - _queue.Peek().Interval >= _parent._duration) - _queue.Dequeue(); + while (!cancel.IsDisposed) + { + if (n == 0) + { + base._observer.OnCompleted(); + break; + } + else + base._observer.OnNext(_queue.Dequeue().Value); + + n--; + } + + base.Dispose(); + } + + private void Trim(TimeSpan now) + { + while (_queue.Count > 0 && now - _queue.Peek().Interval >= _parent._duration) + _queue.Dequeue(); + } } } } diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/TakeLastBuffer.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/TakeLastBuffer.cs index 315b702012..5a9790418a 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/TakeLastBuffer.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/TakeLastBuffer.cs @@ -7,131 +7,137 @@ namespace System.Reactive.Linq.ObservableImpl { - internal sealed class TakeLastBuffer : Producer> + internal static class TakeLastBuffer { - private readonly IObservable _source; - private readonly int _count; - private readonly TimeSpan _duration; - private readonly IScheduler _scheduler; - - public TakeLastBuffer(IObservable source, int count) + internal sealed class Count : Producer> { - _source = source; - _count = count; - } - - public TakeLastBuffer(IObservable source, TimeSpan duration, IScheduler scheduler) - { - _source = source; - _duration = duration; - _scheduler = scheduler; - } + private readonly IObservable _source; + private readonly int _count; - protected override IDisposable Run(IObserver> observer, IDisposable cancel, Action setSink) - { - if (_scheduler == null) + public Count(IObservable source, int count) { - var sink = new _(this, observer, cancel); - setSink(sink); - return _source.SubscribeSafe(sink); + _source = source; + _count = count; } - else - { - var sink = new Impl(this, observer, cancel); - setSink(sink); - return sink.Run(); - } - } - class _ : Sink>, IObserver - { - private readonly TakeLastBuffer _parent; - private Queue _queue; - - public _(TakeLastBuffer parent, IObserver> observer, IDisposable cancel) - : base(observer, cancel) + protected override IDisposable Run(IObserver> observer, IDisposable cancel, Action setSink) { - _parent = parent; - _queue = new Queue(); - } - - public void OnNext(TSource value) - { - _queue.Enqueue(value); - if (_queue.Count > _parent._count) - _queue.Dequeue(); - } - - public void OnError(Exception error) - { - base._observer.OnError(error); - base.Dispose(); + var sink = new _(_count, observer, cancel); + setSink(sink); + return _source.SubscribeSafe(sink); } - public void OnCompleted() + private sealed class _ : Sink>, IObserver { - var res = new List(_queue.Count); - while (_queue.Count > 0) - res.Add(_queue.Dequeue()); - - base._observer.OnNext(res); - base._observer.OnCompleted(); - base.Dispose(); + private readonly int _count; + private Queue _queue; + + public _(int count, IObserver> observer, IDisposable cancel) + : base(observer, cancel) + { + _count = count; + _queue = new Queue(); + } + + public void OnNext(TSource value) + { + _queue.Enqueue(value); + if (_queue.Count > _count) + _queue.Dequeue(); + } + + public void OnError(Exception error) + { + base._observer.OnError(error); + base.Dispose(); + } + + public void OnCompleted() + { + var res = new List(_queue.Count); + while (_queue.Count > 0) + res.Add(_queue.Dequeue()); + + base._observer.OnNext(res); + base._observer.OnCompleted(); + base.Dispose(); + } } } - class Impl : Sink>, IObserver + internal sealed class Time : Producer> { - private readonly TakeLastBuffer _parent; - private Queue> _queue; - - public Impl(TakeLastBuffer parent, IObserver> observer, IDisposable cancel) - : base(observer, cancel) - { - _parent = parent; - _queue = new Queue>(); - } - - private IStopwatch _watch; - - public IDisposable Run() - { - _watch = _parent._scheduler.StartStopwatch(); - - return _parent._source.SubscribeSafe(this); - } + private readonly IObservable _source; + private readonly TimeSpan _duration; + private readonly IScheduler _scheduler; - public void OnNext(TSource value) + public Time(IObservable source, TimeSpan duration, IScheduler scheduler) { - var now = _watch.Elapsed; - _queue.Enqueue(new System.Reactive.TimeInterval(value, now)); - Trim(now); + _source = source; + _duration = duration; + _scheduler = scheduler; } - public void OnError(Exception error) + protected override IDisposable Run(IObserver> observer, IDisposable cancel, Action setSink) { - base._observer.OnError(error); - base.Dispose(); - } - - public void OnCompleted() - { - var now = _watch.Elapsed; - Trim(now); - - var res = new List(_queue.Count); - while (_queue.Count > 0) - res.Add(_queue.Dequeue().Value); - - base._observer.OnNext(res); - base._observer.OnCompleted(); - base.Dispose(); + var sink = new _(_duration, observer, cancel); + setSink(sink); + return sink.Run(this); } - private void Trim(TimeSpan now) + private sealed class _ : Sink>, IObserver { - while (_queue.Count > 0 && now - _queue.Peek().Interval >= _parent._duration) - _queue.Dequeue(); + private readonly TimeSpan _duration; + private Queue> _queue; + + public _(TimeSpan duration, IObserver> observer, IDisposable cancel) + : base(observer, cancel) + { + _duration = duration; + _queue = new Queue>(); + } + + private IStopwatch _watch; + + public IDisposable Run(Time parent) + { + _watch = parent._scheduler.StartStopwatch(); + + return parent._source.SubscribeSafe(this); + } + + public void OnNext(TSource value) + { + var now = _watch.Elapsed; + _queue.Enqueue(new System.Reactive.TimeInterval(value, now)); + Trim(now); + } + + public void OnError(Exception error) + { + base._observer.OnError(error); + base.Dispose(); + } + + public void OnCompleted() + { + var now = _watch.Elapsed; + Trim(now); + + var res = new List(_queue.Count); + while (_queue.Count > 0) + res.Add(_queue.Dequeue().Value); + + base._observer.OnNext(res); + base._observer.OnCompleted(); + base.Dispose(); + } + + private void Trim(TimeSpan now) + { + while (_queue.Count > 0 && now - _queue.Peek().Interval >= _duration) + _queue.Dequeue(); + } } } } diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/TakeUntil.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/TakeUntil.cs index a19ca7acbe..c46b7243ee 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/TakeUntil.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/TakeUntil.cs @@ -20,31 +20,28 @@ public TakeUntil(IObservable source, IObservable other) protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - var sink = new _(this, observer, cancel); + var sink = new _(observer, cancel); setSink(sink); - return sink.Run(); + return sink.Run(this); } - class _ : Sink + private sealed class _ : Sink { - private readonly TakeUntil _parent; - - public _(TakeUntil parent, IObserver observer, IDisposable cancel) + public _(IObserver observer, IDisposable cancel) : base(observer, cancel) { - _parent = parent; } - public IDisposable Run() + public IDisposable Run(TakeUntil parent) { - var sourceObserver = new T(this); - var otherObserver = new O(this, sourceObserver); + var sourceObserver = new SourceObserver(this); + var otherObserver = new OtherObserver(this, sourceObserver); // COMPAT - Order of Subscribe calls per v1.0.10621 - var otherSubscription = _parent._other.SubscribeSafe(otherObserver); + var otherSubscription = parent._other.SubscribeSafe(otherObserver); otherObserver.Disposable = otherSubscription; - var sourceSubscription = _parent._source.SubscribeSafe(sourceObserver); + var sourceSubscription = parent._source.SubscribeSafe(sourceObserver); return StableCompositeDisposable.Create( otherSubscription, @@ -58,7 +55,7 @@ public IDisposable Run() * * Notice an approach where the "other" channel performs an Interlocked.Exchange operation on * the _parent._observer field to substitute it with a NopObserver doesn't work, - * because the "other" channel still need to send an OnCompleted message, which could happen + * because the "other" channel still needs to send an OnCompleted message, which could happen * concurrently with another message when the "source" channel has already read from the * _parent._observer field between making the On* call. * @@ -66,12 +63,12 @@ public IDisposable Run() * access to the outgoing observer while dispatching a message. Doing this more fine-grained * than using locks turns out to be tricky and doesn't reduce cost. */ - class T : IObserver + private sealed class SourceObserver : IObserver { private readonly _ _parent; public volatile bool _open; - public T(_ parent) + public SourceObserver(_ parent) { _parent = parent; _open = false; @@ -111,13 +108,13 @@ public void OnCompleted() } } - class O : IObserver + private sealed class OtherObserver : IObserver { private readonly _ _parent; - private readonly T _sourceObserver; + private readonly SourceObserver _sourceObserver; private readonly SingleAssignmentDisposable _subscription; - public O(_ parent, T sourceObserver) + public OtherObserver(_ parent, SourceObserver sourceObserver) { _parent = parent; _sourceObserver = sourceObserver; @@ -191,29 +188,24 @@ public IObservable Combine(DateTimeOffset endTime) protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - var sink = new _(this, observer, cancel); + var sink = new _(observer, cancel); setSink(sink); - return sink.Run(); + return sink.Run(this); } - class _ : Sink, IObserver + private sealed class _ : Sink, IObserver { - private readonly TakeUntil _parent; + private readonly object _gate = new object(); - public _(TakeUntil parent, IObserver observer, IDisposable cancel) + public _(IObserver observer, IDisposable cancel) : base(observer, cancel) { - _parent = parent; } - private object _gate; - - public IDisposable Run() + public IDisposable Run(TakeUntil parent) { - _gate = new object(); - - var t = _parent._scheduler.Schedule(_parent._endTime, Tick); - var d = _parent._source.SubscribeSafe(this); + var t = parent._scheduler.Schedule(parent._endTime, Tick); + var d = parent._source.SubscribeSafe(this); return StableCompositeDisposable.Create(t, d); } diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/TakeWhile.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/TakeWhile.cs index 7f91fc1ce0..4b10ab28ad 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/TakeWhile.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/TakeWhile.cs @@ -4,143 +4,149 @@ namespace System.Reactive.Linq.ObservableImpl { - internal sealed class TakeWhile : Producer + internal static class TakeWhile { - private readonly IObservable _source; - private readonly Func _predicate; - private readonly Func _predicateI; - - public TakeWhile(IObservable source, Func predicate) + internal sealed class Predicate : Producer { - _source = source; - _predicate = predicate; - } + private readonly IObservable _source; + private readonly Func _predicate; - public TakeWhile(IObservable source, Func predicate) - { - _source = source; - _predicateI = predicate; - } - - protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) - { - if (_predicate != null) + public Predicate(IObservable source, Func predicate) { - var sink = new _(this, observer, cancel); - setSink(sink); - return _source.SubscribeSafe(sink); + _source = source; + _predicate = predicate; } - else + + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - var sink = new TakeWhileImpl(this, observer, cancel); + var sink = new _(_predicate, observer, cancel); setSink(sink); return _source.SubscribeSafe(sink); } - } - class _ : Sink, IObserver - { - private readonly TakeWhile _parent; - private bool _running; - - public _(TakeWhile parent, IObserver observer, IDisposable cancel) - : base(observer, cancel) + private sealed class _ : Sink, IObserver { - _parent = parent; - _running = true; - } + private readonly Func _predicate; + private bool _running; - public void OnNext(TSource value) - { - if (_running) + public _(Func predicate, IObserver observer, IDisposable cancel) + : base(observer, cancel) { - try - { - _running = _parent._predicate(value); - } - catch (Exception exception) - { - base._observer.OnError(exception); - base.Dispose(); - return; - } + _predicate = predicate; + _running = true; + } + public void OnNext(TSource value) + { if (_running) { - base._observer.OnNext(value); - } - else - { - base._observer.OnCompleted(); - base.Dispose(); + try + { + _running = _predicate(value); + } + catch (Exception exception) + { + base._observer.OnError(exception); + base.Dispose(); + return; + } + + if (_running) + { + base._observer.OnNext(value); + } + else + { + base._observer.OnCompleted(); + base.Dispose(); + } } } - } - public void OnError(Exception error) - { - base._observer.OnError(error); - base.Dispose(); - } + public void OnError(Exception error) + { + base._observer.OnError(error); + base.Dispose(); + } - public void OnCompleted() - { - base._observer.OnCompleted(); - base.Dispose(); + public void OnCompleted() + { + base._observer.OnCompleted(); + base.Dispose(); + } } } - class TakeWhileImpl : Sink, IObserver + internal sealed class PredicateIndexed : Producer { - private readonly TakeWhile _parent; - private bool _running; - private int _index; + private readonly IObservable _source; + private readonly Func _predicate; - public TakeWhileImpl(TakeWhile parent, IObserver observer, IDisposable cancel) - : base(observer, cancel) + public PredicateIndexed(IObservable source, Func predicate) { - _parent = parent; - _running = true; - _index = 0; + _source = source; + _predicate = predicate; } - public void OnNext(TSource value) + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - if (_running) + var sink = new _(_predicate, observer, cancel); + setSink(sink); + return _source.SubscribeSafe(sink); + } + + private sealed class _ : Sink, IObserver + { + private readonly Func _predicate; + private bool _running; + private int _index; + + public _(Func predicate, IObserver observer, IDisposable cancel) + : base(observer, cancel) { - try - { - _running = _parent._predicateI(value, checked(_index++)); - } - catch (Exception exception) - { - base._observer.OnError(exception); - base.Dispose(); - return; - } + _predicate = predicate; + _running = true; + _index = 0; + } + public void OnNext(TSource value) + { if (_running) { - base._observer.OnNext(value); - } - else - { - base._observer.OnCompleted(); - base.Dispose(); + try + { + _running = _predicate(value, checked(_index++)); + } + catch (Exception exception) + { + base._observer.OnError(exception); + base.Dispose(); + return; + } + + if (_running) + { + base._observer.OnNext(value); + } + else + { + base._observer.OnCompleted(); + base.Dispose(); + } } } - } - public void OnError(Exception error) - { - base._observer.OnError(error); - base.Dispose(); - } + public void OnError(Exception error) + { + base._observer.OnError(error); + base.Dispose(); + } - public void OnCompleted() - { - base._observer.OnCompleted(); - base.Dispose(); + public void OnCompleted() + { + base._observer.OnCompleted(); + base.Dispose(); + } } } } diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Throttle.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Throttle.cs index be94efcb70..5ae66fa42c 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Throttle.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Throttle.cs @@ -24,17 +24,19 @@ protected override IDisposable Run(IObserver observer, IDisposable canc { var sink = new _(this, observer, cancel); setSink(sink); - return sink.Run(); + return sink.Run(_source); } - class _ : Sink, IObserver + private sealed class _ : Sink, IObserver { - private readonly Throttle _parent; + private readonly TimeSpan _dueTime; + private readonly IScheduler _scheduler; public _(Throttle parent, IObserver observer, IDisposable cancel) : base(observer, cancel) { - _parent = parent; + _dueTime = parent._dueTime; + _scheduler = parent._scheduler; } private object _gate; @@ -43,7 +45,7 @@ public _(Throttle parent, IObserver observer, IDisposable canc private SerialDisposable _cancelable; private ulong _id; - public IDisposable Run() + public IDisposable Run(IObservable source) { _gate = new object(); _value = default(TSource); @@ -51,7 +53,7 @@ public IDisposable Run() _cancelable = new SerialDisposable(); _id = 0UL; - var subscription = _parent._source.SubscribeSafe(this); + var subscription = source.SubscribeSafe(this); return StableCompositeDisposable.Create(subscription, _cancelable); } @@ -68,7 +70,7 @@ public void OnNext(TSource value) } var d = new SingleAssignmentDisposable(); _cancelable.Disposable = d; - d.Disposable = _parent._scheduler.Schedule(currentid, _parent._dueTime, Propagate); + d.Disposable = _scheduler.Schedule(currentid, _dueTime, Propagate); } private IDisposable Propagate(IScheduler self, ulong currentid) @@ -94,7 +96,7 @@ public void OnError(Exception error) _hasValue = false; _id = unchecked(_id + 1); - } + } } public void OnCompleted() @@ -105,7 +107,7 @@ public void OnCompleted() { if (_hasValue) base._observer.OnNext(_value); - + base._observer.OnCompleted(); base.Dispose(); @@ -131,17 +133,17 @@ protected override IDisposable Run(IObserver observer, IDisposable canc { var sink = new _(this, observer, cancel); setSink(sink); - return sink.Run(); + return sink.Run(this); } - class _ : Sink, IObserver + private sealed class _ : Sink, IObserver { - private readonly Throttle _parent; + private readonly Func> _throttleSelector; public _(Throttle parent, IObserver observer, IDisposable cancel) : base(observer, cancel) { - _parent = parent; + _throttleSelector = parent._throttleSelector; } private object _gate; @@ -150,7 +152,7 @@ public _(Throttle parent, IObserver observer, IDisp private SerialDisposable _cancelable; private ulong _id; - public IDisposable Run() + public IDisposable Run(Throttle parent) { _gate = new object(); _value = default(TSource); @@ -158,7 +160,7 @@ public IDisposable Run() _cancelable = new SerialDisposable(); _id = 0UL; - var subscription = _parent._source.SubscribeSafe(this); + var subscription = parent._source.SubscribeSafe(this); return StableCompositeDisposable.Create(subscription, _cancelable); } @@ -168,7 +170,7 @@ public void OnNext(TSource value) var throttle = default(IObservable); try { - throttle = _parent._throttleSelector(value); + throttle = _throttleSelector(value); } catch (Exception error) { @@ -192,7 +194,7 @@ public void OnNext(TSource value) var d = new SingleAssignmentDisposable(); _cancelable.Disposable = d; - d.Disposable = throttle.SubscribeSafe(new Delta(this, value, currentid, d)); + d.Disposable = throttle.SubscribeSafe(new ThrottleObserver(this, value, currentid, d)); } public void OnError(Exception error) @@ -226,14 +228,14 @@ public void OnCompleted() } } - class Delta : IObserver + private sealed class ThrottleObserver : IObserver { private readonly _ _parent; private readonly TSource _value; private readonly ulong _currentid; private readonly IDisposable _self; - public Delta(_ parent, TSource value, ulong currentid, IDisposable self) + public ThrottleObserver(_ parent, TSource value, ulong currentid, IDisposable self) { _parent = parent; _value = value; diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Throw.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Throw.cs index dcbb791d04..f85e7f688a 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Throw.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Throw.cs @@ -19,29 +19,29 @@ public Throw(Exception exception, IScheduler scheduler) protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - var sink = new _(this, observer, cancel); + var sink = new _(_exception, observer, cancel); setSink(sink); - return sink.Run(); + return sink.Run(_scheduler); } - class _ : Sink + private sealed class _ : Sink { - private readonly Throw _parent; + private readonly Exception _exception; - public _(Throw parent, IObserver observer, IDisposable cancel) + public _(Exception exception, IObserver observer, IDisposable cancel) : base(observer, cancel) { - _parent = parent; + _exception = exception; } - public IDisposable Run() + public IDisposable Run(IScheduler scheduler) { - return _parent._scheduler.Schedule(Invoke); + return scheduler.Schedule(Invoke); } private void Invoke() { - base._observer.OnError(_parent._exception); + base._observer.OnError(_exception); base.Dispose(); } } diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/TimeInterval.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/TimeInterval.cs index 0a1ccc3900..bdf488f2d1 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/TimeInterval.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/TimeInterval.cs @@ -19,30 +19,27 @@ public TimeInterval(IObservable source, IScheduler scheduler) protected override IDisposable Run(IObserver> observer, IDisposable cancel, Action setSink) { - var sink = new _(this, observer, cancel); + var sink = new _(observer, cancel); setSink(sink); - return sink.Run(); + return sink.Run(this); } - class _ : Sink>, IObserver + private sealed class _ : Sink>, IObserver { - private readonly TimeInterval _parent; - - public _(TimeInterval parent, IObserver> observer, IDisposable cancel) + public _(IObserver> observer, IDisposable cancel) : base(observer, cancel) { - _parent = parent; } private IStopwatch _watch; private TimeSpan _last; - public IDisposable Run() + public IDisposable Run(TimeInterval parent) { - _watch = _parent._scheduler.StartStopwatch(); + _watch = parent._scheduler.StartStopwatch(); _last = TimeSpan.Zero; - return _parent._source.Subscribe(this); + return parent._source.Subscribe(this); } public void OnNext(TSource value) diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Timeout.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Timeout.cs index 044aa58fc2..bce0d44626 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Timeout.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Timeout.cs @@ -7,250 +7,258 @@ namespace System.Reactive.Linq.ObservableImpl { - internal sealed class Timeout : Producer + internal static class Timeout { - private readonly IObservable _source; - private readonly TimeSpan? _dueTimeR; - private readonly DateTimeOffset? _dueTimeA; - private readonly IObservable _other; - private readonly IScheduler _scheduler; - - public Timeout(IObservable source, TimeSpan dueTime, IObservable other, IScheduler scheduler) + internal sealed class Relative : Producer { - _source = source; - _dueTimeR = dueTime; - _other = other; - _scheduler = scheduler; - } + private readonly IObservable _source; + private readonly TimeSpan _dueTime; + private readonly IObservable _other; + private readonly IScheduler _scheduler; - public Timeout(IObservable source, DateTimeOffset dueTime, IObservable other, IScheduler scheduler) - { - _source = source; - _dueTimeA = dueTime; - _other = other; - _scheduler = scheduler; - } - - protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) - { - if (_dueTimeA.HasValue) + public Relative(IObservable source, TimeSpan dueTime, IObservable other, IScheduler scheduler) { - var sink = new TimeA(this, observer, cancel); - setSink(sink); - return sink.Run(); + _source = source; + _dueTime = dueTime; + _other = other; + _scheduler = scheduler; } - else + + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - var sink = new TimeR(this, observer, cancel); + var sink = new _(this, observer, cancel); setSink(sink); - return sink.Run(); + return sink.Run(_source); } - } - - class TimeA : Sink, IObserver - { - private readonly Timeout _parent; - public TimeA(Timeout parent, IObserver observer, IDisposable cancel) - : base(observer, cancel) + private sealed class _ : Sink, IObserver { - _parent = parent; - } + private readonly TimeSpan _dueTime; + private readonly IObservable _other; + private readonly IScheduler _scheduler; - private SerialDisposable _subscription; - private object _gate; - private bool _switched; + private readonly object _gate = new object(); + private SerialDisposable _subscription = new SerialDisposable(); + private SerialDisposable _timer = new SerialDisposable(); - public IDisposable Run() - { - _subscription = new SerialDisposable(); - var original = new SingleAssignmentDisposable(); + public _(Relative parent, IObserver observer, IDisposable cancel) + : base(observer, cancel) + { + _dueTime = parent._dueTime; + _other = parent._other; + _scheduler = parent._scheduler; + } - _subscription.Disposable = original; + private ulong _id; + private bool _switched; - _gate = new object(); - _switched = false; + public IDisposable Run(IObservable source) + { + var original = new SingleAssignmentDisposable(); - var timer = _parent._scheduler.Schedule(_parent._dueTimeA.Value, Timeout); + _subscription.Disposable = original; - original.Disposable = _parent._source.SubscribeSafe(this); + _id = 0UL; + _switched = false; - return StableCompositeDisposable.Create(_subscription, timer); - } + CreateTimer(); - private void Timeout() - { - var timerWins = false; + original.Disposable = source.SubscribeSafe(this); - lock (_gate) - { - timerWins = !_switched; - _switched = true; + return StableCompositeDisposable.Create(_subscription, _timer); } - if (timerWins) - _subscription.Disposable = _parent._other.SubscribeSafe(this.GetForwarder()); - } - - public void OnNext(TSource value) - { - lock (_gate) + private void CreateTimer() { - if (!_switched) - base._observer.OnNext(value); + _timer.Disposable = _scheduler.Schedule(_id, _dueTime, Timeout); } - } - - public void OnError(Exception error) - { - var onErrorWins = false; - lock (_gate) + private IDisposable Timeout(IScheduler _, ulong myid) { - onErrorWins = !_switched; - _switched = true; + var timerWins = false; + + lock (_gate) + { + _switched = (_id == myid); + timerWins = _switched; + } + + if (timerWins) + _subscription.Disposable = _other.SubscribeSafe(this.GetForwarder()); + + return Disposable.Empty; } - if (onErrorWins) + public void OnNext(TSource value) { - base._observer.OnError(error); - base.Dispose(); - } - } + var onNextWins = false; - public void OnCompleted() - { - var onCompletedWins = false; + lock (_gate) + { + onNextWins = !_switched; + if (onNextWins) + { + _id = unchecked(_id + 1); + } + } - lock (_gate) + if (onNextWins) + { + base._observer.OnNext(value); + CreateTimer(); + } + } + + public void OnError(Exception error) { - onCompletedWins = !_switched; - _switched = true; + var onErrorWins = false; + + lock (_gate) + { + onErrorWins = !_switched; + if (onErrorWins) + { + _id = unchecked(_id + 1); + } + } + + if (onErrorWins) + { + base._observer.OnError(error); + base.Dispose(); + } } - if (onCompletedWins) + public void OnCompleted() { - base._observer.OnCompleted(); - base.Dispose(); + var onCompletedWins = false; + + lock (_gate) + { + onCompletedWins = !_switched; + if (onCompletedWins) + { + _id = unchecked(_id + 1); + } + } + + if (onCompletedWins) + { + base._observer.OnCompleted(); + base.Dispose(); + } } } } - class TimeR : Sink, IObserver + internal sealed class Absolute : Producer { - private readonly Timeout _parent; + private readonly IObservable _source; + private readonly DateTimeOffset _dueTime; + private readonly IObservable _other; + private readonly IScheduler _scheduler; - public TimeR(Timeout parent, IObserver observer, IDisposable cancel) - : base(observer, cancel) + public Absolute(IObservable source, DateTimeOffset dueTime, IObservable other, IScheduler scheduler) { - _parent = parent; + _source = source; + _dueTime = dueTime; + _other = other; + _scheduler = scheduler; } - private SerialDisposable _subscription; - private SerialDisposable _timer; - - private object _gate; - private ulong _id; - private bool _switched; + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) + { + var sink = new _(_other, observer, cancel); + setSink(sink); + return sink.Run(this); + } - public IDisposable Run() + private sealed class _ : Sink, IObserver { - _subscription = new SerialDisposable(); - _timer = new SerialDisposable(); - var original = new SingleAssignmentDisposable(); + private readonly IObservable _other; - _subscription.Disposable = original; + private readonly object _gate = new object(); + private readonly SerialDisposable _subscription = new SerialDisposable(); - _gate = new object(); - _id = 0UL; - _switched = false; + public _(IObservable other, IObserver observer, IDisposable cancel) + : base(observer, cancel) + { + _other = other; + } - CreateTimer(); + private bool _switched; - original.Disposable = _parent._source.SubscribeSafe(this); + public IDisposable Run(Absolute parent) + { + var original = new SingleAssignmentDisposable(); - return StableCompositeDisposable.Create(_subscription, _timer); - } + _subscription.Disposable = original; - private void CreateTimer() - { - _timer.Disposable = _parent._scheduler.Schedule(_id, _parent._dueTimeR.Value, Timeout); - } + _switched = false; - private IDisposable Timeout(IScheduler _, ulong myid) - { - var timerWins = false; + var timer = parent._scheduler.Schedule(parent._dueTime, Timeout); - lock (_gate) - { - _switched = (_id == myid); - timerWins = _switched; + original.Disposable = parent._source.SubscribeSafe(this); + + return StableCompositeDisposable.Create(_subscription, timer); } - if (timerWins) - _subscription.Disposable = _parent._other.SubscribeSafe(this.GetForwarder()); + private void Timeout() + { + var timerWins = false; - return Disposable.Empty; - } + lock (_gate) + { + timerWins = !_switched; + _switched = true; + } - public void OnNext(TSource value) - { - var onNextWins = false; + if (timerWins) + _subscription.Disposable = _other.SubscribeSafe(this.GetForwarder()); + } - lock (_gate) + public void OnNext(TSource value) { - onNextWins = !_switched; - if (onNextWins) + lock (_gate) { - _id = unchecked(_id + 1); + if (!_switched) + base._observer.OnNext(value); } } - if (onNextWins) + public void OnError(Exception error) { - base._observer.OnNext(value); - CreateTimer(); - } - } + var onErrorWins = false; - public void OnError(Exception error) - { - var onErrorWins = false; + lock (_gate) + { + onErrorWins = !_switched; + _switched = true; + } - lock (_gate) - { - onErrorWins = !_switched; if (onErrorWins) { - _id = unchecked(_id + 1); + base._observer.OnError(error); + base.Dispose(); } } - if (onErrorWins) + public void OnCompleted() { - base._observer.OnError(error); - base.Dispose(); - } - } + var onCompletedWins = false; - public void OnCompleted() - { - var onCompletedWins = false; + lock (_gate) + { + onCompletedWins = !_switched; + _switched = true; + } - lock (_gate) - { - onCompletedWins = !_switched; if (onCompletedWins) { - _id = unchecked(_id + 1); + base._observer.OnCompleted(); + base.Dispose(); } } - - if (onCompletedWins) - { - base._observer.OnCompleted(); - base.Dispose(); - } } } } @@ -274,40 +282,40 @@ protected override IDisposable Run(IObserver observer, IDisposable canc { var sink = new _(this, observer, cancel); setSink(sink); - return sink.Run(); + return sink.Run(this); } - class _ : Sink, IObserver + private sealed class _ : Sink, IObserver { - private readonly Timeout _parent; + private readonly Func> _timeoutSelector; + private readonly IObservable _other; + + private readonly object _gate = new object(); + private readonly SerialDisposable _subscription = new SerialDisposable(); + private readonly SerialDisposable _timer = new SerialDisposable(); public _(Timeout parent, IObserver observer, IDisposable cancel) : base(observer, cancel) { - _parent = parent; + _timeoutSelector = parent._timeoutSelector; + _other = parent._other; } - private SerialDisposable _subscription; - private SerialDisposable _timer; - private object _gate; private ulong _id; private bool _switched; - public IDisposable Run() + public IDisposable Run(Timeout parent) { - _subscription = new SerialDisposable(); - _timer = new SerialDisposable(); var original = new SingleAssignmentDisposable(); _subscription.Disposable = original; - _gate = new object(); _id = 0UL; _switched = false; - SetTimer(_parent._firstTimeout); + SetTimer(parent._firstTimeout); - original.Disposable = _parent._source.SubscribeSafe(this); + original.Disposable = parent._source.SubscribeSafe(this); return StableCompositeDisposable.Create(_subscription, _timer); } @@ -321,7 +329,7 @@ public void OnNext(TSource value) var timeout = default(IObservable); try { - timeout = _parent._timeoutSelector(value); + timeout = _timeoutSelector(value); } catch (Exception error) { @@ -358,16 +366,16 @@ private void SetTimer(IObservable timeout) var d = new SingleAssignmentDisposable(); _timer.Disposable = d; - d.Disposable = timeout.SubscribeSafe(new TimeoutImpl(this, myid, d)); + d.Disposable = timeout.SubscribeSafe(new TimeoutObserver(this, myid, d)); } - class TimeoutImpl : IObserver + private sealed class TimeoutObserver : IObserver { private readonly _ _parent; private readonly ulong _id; private readonly IDisposable _self; - public TimeoutImpl(_ parent, ulong id, IDisposable self) + public TimeoutObserver(_ parent, ulong id, IDisposable self) { _parent = parent; _id = id; @@ -377,7 +385,7 @@ public TimeoutImpl(_ parent, ulong id, IDisposable self) public void OnNext(TTimeout value) { if (TimerWins()) - _parent._subscription.Disposable = _parent._parent._other.SubscribeSafe(_parent.GetForwarder()); + _parent._subscription.Disposable = _parent._other.SubscribeSafe(_parent.GetForwarder()); _self.Dispose(); } @@ -394,7 +402,7 @@ public void OnError(Exception error) public void OnCompleted() { if (TimerWins()) - _parent._subscription.Disposable = _parent._parent._other.SubscribeSafe(_parent.GetForwarder()); + _parent._subscription.Disposable = _parent._other.SubscribeSafe(_parent.GetForwarder()); } private bool TimerWins() diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Timer.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Timer.cs index 290c4f4feb..224a85f287 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Timer.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Timer.cs @@ -8,253 +8,300 @@ namespace System.Reactive.Linq.ObservableImpl { - internal sealed class Timer : Producer + internal static class Timer { - private readonly DateTimeOffset? _dueTimeA; - private readonly TimeSpan? _dueTimeR; - private readonly TimeSpan? _period; - private readonly IScheduler _scheduler; - - public Timer(DateTimeOffset dueTime, TimeSpan? period, IScheduler scheduler) - { - _dueTimeA = dueTime; - _period = period; - _scheduler = scheduler; - } - - public Timer(TimeSpan dueTime, TimeSpan? period, IScheduler scheduler) + internal abstract class Single : Producer { - _dueTimeR = dueTime; - _period = period; - _scheduler = scheduler; - } + private readonly IScheduler _scheduler; - protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) - { - if (_period.HasValue) + public Single(IScheduler scheduler) { - var sink = new TimerImpl(this, observer, cancel); - setSink(sink); - return sink.Run(); + _scheduler = scheduler; } - else + + internal sealed class Relative : Single { - var sink = new _(this, observer, cancel); - setSink(sink); - return sink.Run(); - } - } + private readonly TimeSpan _dueTime; - class _ : Sink - { - private readonly Timer _parent; + public Relative(TimeSpan dueTime, IScheduler scheduler) + : base(scheduler) + { + _dueTime = dueTime; + } - public _(Timer parent, IObserver observer, IDisposable cancel) - : base(observer, cancel) - { - _parent = parent; + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) + { + var sink = new _(observer, cancel); + setSink(sink); + return sink.Run(this, _dueTime); + } } - public IDisposable Run() + internal sealed class Absolute : Single { - if (_parent._dueTimeA.HasValue) + private readonly DateTimeOffset _dueTime; + + public Absolute(DateTimeOffset dueTime, IScheduler scheduler) + : base(scheduler) { - return _parent._scheduler.Schedule(_parent._dueTimeA.Value, Invoke); + _dueTime = dueTime; } - else + + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - return _parent._scheduler.Schedule(_parent._dueTimeR.Value, Invoke); + var sink = new _(observer, cancel); + setSink(sink); + return sink.Run(this, _dueTime); } } - private void Invoke() + private sealed class _ : Sink { - base._observer.OnNext(0); - base._observer.OnCompleted(); - base.Dispose(); + public _(IObserver observer, IDisposable cancel) + : base(observer, cancel) + { + } + + public IDisposable Run(Single parent, DateTimeOffset dueTime) + { + return parent._scheduler.Schedule(dueTime, Invoke); + } + + public IDisposable Run(Single parent, TimeSpan dueTime) + { + return parent._scheduler.Schedule(dueTime, Invoke); + } + + private void Invoke() + { + base._observer.OnNext(0); + base._observer.OnCompleted(); + base.Dispose(); + } } } - class TimerImpl : Sink + internal abstract class Periodic : Producer { - private readonly Timer _parent; private readonly TimeSpan _period; + private readonly IScheduler _scheduler; - public TimerImpl(Timer parent, IObserver observer, IDisposable cancel) - : base(observer, cancel) + public Periodic(TimeSpan period, IScheduler scheduler) { - _parent = parent; - _period = _parent._period.Value; + _period = period; + _scheduler = scheduler; } - public IDisposable Run() + internal sealed class Relative : Periodic { - if (_parent._dueTimeA.HasValue) + private readonly TimeSpan _dueTime; + + public Relative(TimeSpan dueTime, TimeSpan period, IScheduler scheduler) + : base(period, scheduler) { - var dueTime = _parent._dueTimeA.Value; - return _parent._scheduler.Schedule(default(object), dueTime, InvokeStart); + _dueTime = dueTime; } - else - { - var dueTime = _parent._dueTimeR.Value; - // - // Optimize for the case of Observable.Interval. - // - if (dueTime == _period) - { - return _parent._scheduler.SchedulePeriodic(0L, _period, (Func)Tick); - } - - return _parent._scheduler.Schedule(default(object), dueTime, InvokeStart); + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) + { + var sink = new _(_period, observer, cancel); + setSink(sink); + return sink.Run(this, _dueTime); } } - // - // BREAKING CHANGE v2 > v1.x - No more correction for time drift based on absolute time. This - // didn't work for large period values anyway; the fractional - // error exceeded corrections. Also complicated dealing with system - // clock change conditions and caused numerous bugs. - // - // - For more precise scheduling, use a custom scheduler that measures TimeSpan values in a - // better way, e.g. spinning to make up for the last part of the period. Whether or not the - // values of the TimeSpan period match NT time or wall clock time is up to the scheduler. - // - // - For more accurate scheduling wrt the system clock, use Generate with DateTimeOffset time - // selectors. When the system clock changes, intervals will not be the same as diffs between - // consecutive absolute time values. The precision will be low (1s range by default). - // - private long Tick(long count) + internal sealed class Absolute : Periodic { - base._observer.OnNext(count); - return unchecked(count + 1); - } - - private int _pendingTickCount; - private IDisposable _periodic; + private readonly DateTimeOffset _dueTime; - private IDisposable InvokeStart(IScheduler self, object state) - { - // - // Notice the first call to OnNext will introduce skew if it takes significantly long when - // using the following naive implementation: - // - // Code: base._observer.OnNext(0L); - // return self.SchedulePeriodicEmulated(1L, _period, (Func)Tick); - // - // What we're saying here is that Observable.Timer(dueTime, period) is pretty much the same - // as writing Observable.Timer(dueTime).Concat(Observable.Interval(period)). - // - // Expected: dueTime - // | - // 0--period--1--period--2--period--3--period--4--... - // | - // +-OnNext(0L)-| - // - // Actual: dueTime - // | - // 0------------#--period--1--period--2--period--3--period--4--... - // | - // +-OnNext(0L)-| - // - // Different solutions for this behavior have different problems: - // - // 1. Scheduling the periodic job first and using an AsyncLock to serialize the OnNext calls - // has the drawback that InvokeStart may never return. This happens when every callback - // doesn't meet the period's deadline, hence the periodic job keeps queueing stuff up. In - // this case, InvokeStart stays the owner of the AsyncLock and the call to Wait will never - // return, thus not allowing any interleaving of work on this scheduler's logical thread. - // - // 2. Scheduling the periodic job first and using a (blocking) synchronization primitive to - // signal completion of the OnNext(0L) call to the Tick call requires quite a bit of state - // and careful handling of the case when OnNext(0L) throws. What's worse is the blocking - // behavior inside Tick. - // - // In order to avoid blocking behavior, we need a scheme much like SchedulePeriodic emulation - // where work to dispatch OnNext(n + 1) is delegated to a catch up loop in case OnNext(n) was - // still running. Because SchedulePeriodic emulation exhibits such behavior in all cases, we - // only need to deal with the overlap of OnNext(0L) with future periodic OnNext(n) dispatch - // jobs. In the worst case where every callback takes longer than the deadline implied by the - // period, the periodic job will just queue up work that's dispatched by the tail-recursive - // catch up loop. In the best case, all work will be dispatched on the periodic scheduler. - // + public Absolute(DateTimeOffset dueTime, TimeSpan period, IScheduler scheduler) + : base(period, scheduler) + { + _dueTime = dueTime; + } - // - // We start with one tick pending because we're about to start doing OnNext(0L). - // - _pendingTickCount = 1; + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) + { + var sink = new _(_period, observer, cancel); + setSink(sink); + return sink.Run(this, _dueTime); + } + } - var d = new SingleAssignmentDisposable(); - _periodic = d; - d.Disposable = self.SchedulePeriodic(1L, _period, (Func)Tock); + private sealed class _ : Sink + { + private readonly TimeSpan _period; - try + public _(TimeSpan period, IObserver observer, IDisposable cancel) + : base(observer, cancel) { - base._observer.OnNext(0L); + _period = period; } - catch (Exception e) + + public IDisposable Run(Periodic parent, DateTimeOffset dueTime) { - d.Dispose(); - e.Throw(); + return parent._scheduler.Schedule(default(object), dueTime, InvokeStart); } - // - // If the periodic scheduling job already ran before we finished dispatching the OnNext(0L) - // call, we'll find pendingTickCount to be > 1. In this case, we need to catch up by dispatching - // subsequent calls to OnNext as fast as possible, but without running a loop in order to ensure - // fair play with the scheduler. So, we run a tail-recursive loop in CatchUp instead. - // - if (Interlocked.Decrement(ref _pendingTickCount) > 0) + public IDisposable Run(Periodic parent, TimeSpan dueTime) { - var c = new SingleAssignmentDisposable(); - c.Disposable = self.Schedule(1L, CatchUp); + // + // Optimize for the case of Observable.Interval. + // + if (dueTime == _period) + { + return parent._scheduler.SchedulePeriodic(0L, _period, (Func)Tick); + } - return StableCompositeDisposable.Create(d, c); + return parent._scheduler.Schedule(default(object), dueTime, InvokeStart); } - return d; - } - - private long Tock(long count) - { // - // Notice the handler for (emulated) periodic scheduling is non-reentrant. + // BREAKING CHANGE v2 > v1.x - No more correction for time drift based on absolute time. This + // didn't work for large period values anyway; the fractional + // error exceeded corrections. Also complicated dealing with system + // clock change conditions and caused numerous bugs. // - // When there's no overlap with the OnNext(0L) call, the following code will cycle through - // pendingTickCount 0 -> 1 -> 0 for the remainder of the timer's execution. + // - For more precise scheduling, use a custom scheduler that measures TimeSpan values in a + // better way, e.g. spinning to make up for the last part of the period. Whether or not the + // values of the TimeSpan period match NT time or wall clock time is up to the scheduler. // - // If there's overlap with the OnNext(0L) call, pendingTickCount will increase to record - // the number of catch up OnNext calls required, which will be dispatched by the recursive - // scheduling loop in CatchUp (which quits when it reaches 0 pending ticks). + // - For more accurate scheduling wrt the system clock, use Generate with DateTimeOffset time + // selectors. When the system clock changes, intervals will not be the same as diffs between + // consecutive absolute time values. The precision will be low (1s range by default). // - if (Interlocked.Increment(ref _pendingTickCount) == 1) + private long Tick(long count) { base._observer.OnNext(count); - Interlocked.Decrement(ref _pendingTickCount); + return unchecked(count + 1); } - return unchecked(count + 1); - } + private int _pendingTickCount; + private IDisposable _periodic; - private void CatchUp(long count, Action recurse) - { - try + private IDisposable InvokeStart(IScheduler self, object state) { - base._observer.OnNext(count); + // + // Notice the first call to OnNext will introduce skew if it takes significantly long when + // using the following naive implementation: + // + // Code: base._observer.OnNext(0L); + // return self.SchedulePeriodicEmulated(1L, _period, (Func)Tick); + // + // What we're saying here is that Observable.Timer(dueTime, period) is pretty much the same + // as writing Observable.Timer(dueTime).Concat(Observable.Interval(period)). + // + // Expected: dueTime + // | + // 0--period--1--period--2--period--3--period--4--... + // | + // +-OnNext(0L)-| + // + // Actual: dueTime + // | + // 0------------#--period--1--period--2--period--3--period--4--... + // | + // +-OnNext(0L)-| + // + // Different solutions for this behavior have different problems: + // + // 1. Scheduling the periodic job first and using an AsyncLock to serialize the OnNext calls + // has the drawback that InvokeStart may never return. This happens when every callback + // doesn't meet the period's deadline, hence the periodic job keeps queueing stuff up. In + // this case, InvokeStart stays the owner of the AsyncLock and the call to Wait will never + // return, thus not allowing any interleaving of work on this scheduler's logical thread. + // + // 2. Scheduling the periodic job first and using a (blocking) synchronization primitive to + // signal completion of the OnNext(0L) call to the Tick call requires quite a bit of state + // and careful handling of the case when OnNext(0L) throws. What's worse is the blocking + // behavior inside Tick. + // + // In order to avoid blocking behavior, we need a scheme much like SchedulePeriodic emulation + // where work to dispatch OnNext(n + 1) is delegated to a catch up loop in case OnNext(n) was + // still running. Because SchedulePeriodic emulation exhibits such behavior in all cases, we + // only need to deal with the overlap of OnNext(0L) with future periodic OnNext(n) dispatch + // jobs. In the worst case where every callback takes longer than the deadline implied by the + // period, the periodic job will just queue up work that's dispatched by the tail-recursive + // catch up loop. In the best case, all work will be dispatched on the periodic scheduler. + // + + // + // We start with one tick pending because we're about to start doing OnNext(0L). + // + _pendingTickCount = 1; + + var d = new SingleAssignmentDisposable(); + _periodic = d; + d.Disposable = self.SchedulePeriodic(1L, _period, (Func)Tock); + + try + { + base._observer.OnNext(0L); + } + catch (Exception e) + { + d.Dispose(); + e.Throw(); + } + + // + // If the periodic scheduling job already ran before we finished dispatching the OnNext(0L) + // call, we'll find pendingTickCount to be > 1. In this case, we need to catch up by dispatching + // subsequent calls to OnNext as fast as possible, but without running a loop in order to ensure + // fair play with the scheduler. So, we run a tail-recursive loop in CatchUp instead. + // + if (Interlocked.Decrement(ref _pendingTickCount) > 0) + { + var c = new SingleAssignmentDisposable(); + c.Disposable = self.Schedule(1L, CatchUp); + + return StableCompositeDisposable.Create(d, c); + } + + return d; } - catch (Exception e) + + private long Tock(long count) { - _periodic.Dispose(); - e.Throw(); + // + // Notice the handler for (emulated) periodic scheduling is non-reentrant. + // + // When there's no overlap with the OnNext(0L) call, the following code will cycle through + // pendingTickCount 0 -> 1 -> 0 for the remainder of the timer's execution. + // + // If there's overlap with the OnNext(0L) call, pendingTickCount will increase to record + // the number of catch up OnNext calls required, which will be dispatched by the recursive + // scheduling loop in CatchUp (which quits when it reaches 0 pending ticks). + // + if (Interlocked.Increment(ref _pendingTickCount) == 1) + { + base._observer.OnNext(count); + Interlocked.Decrement(ref _pendingTickCount); + } + + return unchecked(count + 1); } - // - // We can simply bail out if we decreased the tick count to 0. In that case, the Tock - // method will take over when it sees the 0 -> 1 transition. - // - if (Interlocked.Decrement(ref _pendingTickCount) > 0) + private void CatchUp(long count, Action recurse) { - recurse(unchecked(count + 1)); + try + { + base._observer.OnNext(count); + } + catch (Exception e) + { + _periodic.Dispose(); + e.Throw(); + } + + // + // We can simply bail out if we decreased the tick count to 0. In that case, the Tock + // method will take over when it sees the 0 -> 1 transition. + // + if (Interlocked.Decrement(ref _pendingTickCount) > 0) + { + recurse(unchecked(count + 1)); + } } } } diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Timestamp.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Timestamp.cs index 02e079ff7d..090251b774 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Timestamp.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Timestamp.cs @@ -19,24 +19,24 @@ public Timestamp(IObservable source, IScheduler scheduler) protected override IDisposable Run(IObserver> observer, IDisposable cancel, Action setSink) { - var sink = new _(this, observer, cancel); + var sink = new _(_scheduler, observer, cancel); setSink(sink); return _source.SubscribeSafe(sink); } - class _ : Sink>, IObserver + private sealed class _ : Sink>, IObserver { - private readonly Timestamp _parent; + private readonly IScheduler _scheduler; - public _(Timestamp parent, IObserver> observer, IDisposable cancel) + public _(IScheduler scheduler, IObserver> observer, IDisposable cancel) : base(observer, cancel) { - _parent = parent; + _scheduler = scheduler; } public void OnNext(TSource value) { - base._observer.OnNext(new Timestamped(value, _parent._scheduler.Now)); + base._observer.OnNext(new Timestamped(value, _scheduler.Now)); } public void OnError(Exception error) diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/ToArray.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/ToArray.cs index c5b1a3f6dd..074de207df 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/ToArray.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/ToArray.cs @@ -22,9 +22,9 @@ protected override IDisposable Run(IObserver observer, IDisposable ca return _source.SubscribeSafe(sink); } - class _ : Sink, IObserver + private sealed class _ : Sink, IObserver { - private List _list; + private readonly List _list; public _(IObserver observer, IDisposable cancel) : base(observer, cancel) diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/ToDictionary.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/ToDictionary.cs index 58c7ed8066..0c4982c312 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/ToDictionary.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/ToDictionary.cs @@ -28,23 +28,25 @@ protected override IDisposable Run(IObserver> observ return _source.SubscribeSafe(sink); } - class _ : Sink>, IObserver + private sealed class _ : Sink>, IObserver { - private readonly ToDictionary _parent; - private Dictionary _dictionary; + private readonly Func _keySelector; + private readonly Func _elementSelector; + private readonly Dictionary _dictionary; public _(ToDictionary parent, IObserver> observer, IDisposable cancel) : base(observer, cancel) { - _parent = parent; - _dictionary = new Dictionary(_parent._comparer); + _keySelector = parent._keySelector; + _elementSelector = parent._elementSelector; + _dictionary = new Dictionary(parent._comparer); } public void OnNext(TSource value) { try { - _dictionary.Add(_parent._keySelector(value), _parent._elementSelector(value)); + _dictionary.Add(_keySelector(value), _elementSelector(value)); } catch (Exception ex) { diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/ToList.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/ToList.cs index 48142a3778..d2ddf08935 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/ToList.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/ToList.cs @@ -22,9 +22,9 @@ protected override IDisposable Run(IObserver> observer, IDisposab return _source.SubscribeSafe(sink); } - class _ : Sink>, IObserver + private sealed class _ : Sink>, IObserver { - private List _list; + private readonly List _list; public _(IObserver> observer, IDisposable cancel) : base(observer, cancel) diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/ToLookup.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/ToLookup.cs index 36c327a4ff..baa87b3eac 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/ToLookup.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/ToLookup.cs @@ -29,23 +29,25 @@ protected override IDisposable Run(IObserver> observer, return _source.SubscribeSafe(sink); } - class _ : Sink>, IObserver + private sealed class _ : Sink>, IObserver { - private readonly ToLookup _parent; - private Lookup _lookup; + private readonly Func _keySelector; + private readonly Func _elementSelector; + private readonly Lookup _lookup; public _(ToLookup parent, IObserver> observer, IDisposable cancel) : base(observer, cancel) { - _parent = parent; - _lookup = new Lookup(_parent._comparer); + _keySelector = parent._keySelector; + _elementSelector = parent._elementSelector; + _lookup = new Lookup(parent._comparer); } public void OnNext(TSource value) { try { - _lookup.Add(_parent._keySelector(value), _parent._elementSelector(value)); + _lookup.Add(_keySelector(value), _elementSelector(value)); } catch (Exception ex) { diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/ToObservable.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/ToObservable.cs index 7c197c9c72..21c04703fc 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/ToObservable.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/ToObservable.cs @@ -21,27 +21,24 @@ public ToObservable(IEnumerable source, IScheduler scheduler) protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - var sink = new _(this, observer, cancel); + var sink = new _(observer, cancel); setSink(sink); - return sink.Run(); + return sink.Run(this); } - class _ : Sink + private sealed class _ : Sink { - private readonly ToObservable _parent; - - public _(ToObservable parent, IObserver observer, IDisposable cancel) + public _(IObserver observer, IDisposable cancel) : base(observer, cancel) { - _parent = parent; } - public IDisposable Run() + public IDisposable Run(ToObservable parent) { var e = default(IEnumerator); try { - e = _parent._source.GetEnumerator(); + e = parent._source.GetEnumerator(); } catch (Exception exception) { @@ -50,7 +47,7 @@ public IDisposable Run() return Disposable.Empty; } - var longRunning = _parent._scheduler.AsLongRunning(); + var longRunning = parent._scheduler.AsLongRunning(); if (longRunning != null) { // @@ -69,12 +66,12 @@ public IDisposable Run() // enumerator. // var flag = new BooleanDisposable(); - _parent._scheduler.Schedule(new State(flag, e), LoopRec); + parent._scheduler.Schedule(new State(flag, e), LoopRec); return flag; } } - class State + private sealed class State { public readonly ICancelable flag; public readonly IEnumerator enumerator; diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Using.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Using.cs index eca80d5f16..519e8c4160 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Using.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Using.cs @@ -20,31 +20,28 @@ public Using(Func resourceFactory, Func observer, IDisposable cancel, Action setSink) { - var sink = new _(this, observer, cancel); + var sink = new _(observer, cancel); setSink(sink); - return sink.Run(); + return sink.Run(this); } - class _ : Sink, IObserver + private sealed class _ : Sink, IObserver { - private readonly Using _parent; - - public _(Using parent, IObserver observer, IDisposable cancel) + public _(IObserver observer, IDisposable cancel) : base(observer, cancel) { - _parent = parent; } - public IDisposable Run() + public IDisposable Run(Using parent) { var source = default(IObservable); var disposable = Disposable.Empty; try { - var resource = _parent._resourceFactory(); + var resource = parent._resourceFactory(); if (resource != null) disposable = resource; - source = _parent._observableFactory(resource); + source = parent._observableFactory(resource); } catch (Exception exception) { diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Where.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Where.cs index 95bd47985a..95373be9a0 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Where.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Where.cs @@ -4,129 +4,136 @@ namespace System.Reactive.Linq.ObservableImpl { - internal sealed class Where : Producer + internal static class Where { - private readonly IObservable _source; - private readonly Func _predicate; - private readonly Func _predicateI; - - public Where(IObservable source, Func predicate) - { - _source = source; - _predicate = predicate; - } - - public Where(IObservable source, Func predicate) + internal sealed class Predicate : Producer { - _source = source; - _predicateI = predicate; - } + private readonly IObservable _source; + private readonly Func _predicate; - public IObservable Combine(Func predicate) - { - if (_predicate != null) - return new Where(_source, x => _predicate(x) && predicate(x)); - else - return new Where(this, predicate); - } + public Predicate(IObservable source, Func predicate) + { + _source = source; + _predicate = predicate; + } - protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) - { - if (_predicate != null) + public IObservable Combine(Func predicate) { - var sink = new _(this, observer, cancel); - setSink(sink); - return _source.SubscribeSafe(sink); + return new Predicate(_source, x => _predicate(x) && predicate(x)); } - else + + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - var sink = new WhereImpl(this, observer, cancel); + var sink = new _(_predicate, observer, cancel); setSink(sink); return _source.SubscribeSafe(sink); } - } - - class _ : Sink, IObserver - { - private readonly Where _parent; - public _(Where parent, IObserver observer, IDisposable cancel) - : base(observer, cancel) + private sealed class _ : Sink, IObserver { - _parent = parent; - } + private readonly Func _predicate; - public void OnNext(TSource value) - { - var shouldRun = default(bool); - try + public _(Func predicate, IObserver observer, IDisposable cancel) + : base(observer, cancel) { - shouldRun = _parent._predicate(value); + _predicate = predicate; } - catch (Exception exception) + + public void OnNext(TSource value) + { + var shouldRun = default(bool); + try + { + shouldRun = _predicate(value); + } + catch (Exception exception) + { + base._observer.OnError(exception); + base.Dispose(); + return; + } + + if (shouldRun) + { + base._observer.OnNext(value); + } + } + + public void OnError(Exception error) { - base._observer.OnError(exception); + base._observer.OnError(error); base.Dispose(); - return; } - if (shouldRun) - base._observer.OnNext(value); + public void OnCompleted() + { + base._observer.OnCompleted(); + base.Dispose(); + } } + } - public void OnError(Exception error) - { - base._observer.OnError(error); - base.Dispose(); - } + internal sealed class PredicateIndexed : Producer + { + private readonly IObservable _source; + private readonly Func _predicate; - public void OnCompleted() + public PredicateIndexed(IObservable source, Func predicate) { - base._observer.OnCompleted(); - base.Dispose(); + _source = source; + _predicate = predicate; } - } - class WhereImpl : Sink, IObserver - { - private readonly Where _parent; - private int _index; - - public WhereImpl(Where parent, IObserver observer, IDisposable cancel) - : base(observer, cancel) + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - _parent = parent; - _index = 0; + var sink = new _(_predicate, observer, cancel); + setSink(sink); + return _source.SubscribeSafe(sink); } - public void OnNext(TSource value) + private sealed class _ : Sink, IObserver { - var shouldRun = default(bool); - try + private readonly Func _predicate; + private int _index; + + public _(Func predicate, IObserver observer, IDisposable cancel) + : base(observer, cancel) + { + _predicate = predicate; + _index = 0; + } + + public void OnNext(TSource value) { - shouldRun = _parent._predicateI(value, checked(_index++)); + var shouldRun = default(bool); + try + { + shouldRun = _predicate(value, checked(_index++)); + } + catch (Exception exception) + { + base._observer.OnError(exception); + base.Dispose(); + return; + } + + if (shouldRun) + { + base._observer.OnNext(value); + } } - catch (Exception exception) + + public void OnError(Exception error) { - base._observer.OnError(exception); + base._observer.OnError(error); base.Dispose(); - return; } - if (shouldRun) - base._observer.OnNext(value); - } - - public void OnError(Exception error) - { - base._observer.OnError(error); - base.Dispose(); - } - - public void OnCompleted() - { - base._observer.OnCompleted(); - base.Dispose(); + public void OnCompleted() + { + base._observer.OnCompleted(); + base.Dispose(); + } } } } diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/While.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/While.cs index 1775f72943..6bab75aeaa 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/While.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/While.cs @@ -30,7 +30,7 @@ public IEnumerable> GetSources() yield return _source; } - class _ : ConcatSink + private sealed class _ : ConcatSink { public _(IObserver observer, IDisposable cancel) : base(observer, cancel) diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Window.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Window.cs index eea76f9747..f54119c7cb 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Window.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Window.cs @@ -9,737 +9,757 @@ namespace System.Reactive.Linq.ObservableImpl { - internal sealed class Window : Producer> + internal static class Window { - private readonly IObservable _source; - private readonly int _count; - private readonly int _skip; - - private readonly TimeSpan _timeSpan; - private readonly TimeSpan _timeShift; - private readonly IScheduler _scheduler; - - public Window(IObservable source, int count, int skip) - { - _source = source; - _count = count; - _skip = skip; - } - - public Window(IObservable source, TimeSpan timeSpan, TimeSpan timeShift, IScheduler scheduler) + internal sealed class Count : Producer> { - _source = source; - _timeSpan = timeSpan; - _timeShift = timeShift; - _scheduler = scheduler; - } + private readonly IObservable _source; + private readonly int _count; + private readonly int _skip; - public Window(IObservable source, TimeSpan timeSpan, int count, IScheduler scheduler) - { - _source = source; - _timeSpan = timeSpan; - _count = count; - _scheduler = scheduler; - } - - protected override IDisposable Run(IObserver> observer, IDisposable cancel, Action setSink) - { - if (_scheduler == null) + public Count(IObservable source, int count, int skip) { - var sink = new _(this, observer, cancel); - setSink(sink); - return sink.Run(); + _source = source; + _count = count; + _skip = skip; } - else if (_count > 0) + + protected override IDisposable Run(IObserver> observer, IDisposable cancel, Action setSink) { - var sink = new BoundedWindowImpl(this, observer, cancel); + var sink = new _(this, observer, cancel); setSink(sink); - return sink.Run(); + return sink.Run(_source); } - else - { - if (_timeSpan == _timeShift) - { - var sink = new TimeShiftImpl(this, observer, cancel); - setSink(sink); - return sink.Run(); - } - else - { - var sink = new WindowImpl(this, observer, cancel); - setSink(sink); - return sink.Run(); - } - } - } - - class _ : Sink>, IObserver - { - private readonly Window _parent; - public _(Window parent, IObserver> observer, IDisposable cancel) - : base(observer, cancel) + private sealed class _ : Sink>, IObserver { - _parent = parent; - } + private readonly Queue> _queue = new Queue>(); + private readonly SingleAssignmentDisposable _m = new SingleAssignmentDisposable(); + private readonly RefCountDisposable _refCountDisposable; - private Queue> _queue; - private int _n; - private SingleAssignmentDisposable _m; - private RefCountDisposable _refCountDisposable; + private readonly int _count; + private readonly int _skip; - public IDisposable Run() - { - _queue = new Queue>(); - _n = 0; - _m = new SingleAssignmentDisposable(); - _refCountDisposable = new RefCountDisposable(_m); + public _(Count parent, IObserver> observer, IDisposable cancel) + : base(observer, cancel) + { + _refCountDisposable = new RefCountDisposable(_m); - var firstWindow = CreateWindow(); - base._observer.OnNext(firstWindow); + _count = parent._count; + _skip = parent._skip; + } - _m.Disposable = _parent._source.SubscribeSafe(this); + private int _n; - return _refCountDisposable; - } + public IDisposable Run(IObservable source) + { + _n = 0; - private IObservable CreateWindow() - { - var s = new Subject(); - _queue.Enqueue(s); - return new WindowObservable(s, _refCountDisposable); - } + var firstWindow = CreateWindow(); + base._observer.OnNext(firstWindow); - public void OnNext(TSource value) - { - foreach (var s in _queue) - s.OnNext(value); + _m.Disposable = source.SubscribeSafe(this); - var c = _n - _parent._count + 1; - if (c >= 0 && c % _parent._skip == 0) + return _refCountDisposable; + } + + private IObservable CreateWindow() { - var s = _queue.Dequeue(); - s.OnCompleted(); + var s = new Subject(); + _queue.Enqueue(s); + return new WindowObservable(s, _refCountDisposable); } - _n++; - if (_n % _parent._skip == 0) + public void OnNext(TSource value) { - var newWindow = CreateWindow(); - base._observer.OnNext(newWindow); + foreach (var s in _queue) + s.OnNext(value); + + var c = _n - _count + 1; + if (c >= 0 && c % _skip == 0) + { + var s = _queue.Dequeue(); + s.OnCompleted(); + } + + _n++; + if (_n % _skip == 0) + { + var newWindow = CreateWindow(); + base._observer.OnNext(newWindow); + } } - } - public void OnError(Exception error) - { - while (_queue.Count > 0) - _queue.Dequeue().OnError(error); + public void OnError(Exception error) + { + while (_queue.Count > 0) + _queue.Dequeue().OnError(error); - base._observer.OnError(error); - base.Dispose(); - } + base._observer.OnError(error); + base.Dispose(); + } - public void OnCompleted() - { - while (_queue.Count > 0) - _queue.Dequeue().OnCompleted(); + public void OnCompleted() + { + while (_queue.Count > 0) + _queue.Dequeue().OnCompleted(); - base._observer.OnCompleted(); - base.Dispose(); + base._observer.OnCompleted(); + base.Dispose(); + } } } - class WindowImpl : Sink>, IObserver + internal sealed class TimeSliding : Producer> { - private readonly Window _parent; + private readonly IObservable _source; + private readonly TimeSpan _timeSpan; + private readonly TimeSpan _timeShift; + private readonly IScheduler _scheduler; - public WindowImpl(Window parent, IObserver> observer, IDisposable cancel) - : base(observer, cancel) + public TimeSliding(IObservable source, TimeSpan timeSpan, TimeSpan timeShift, IScheduler scheduler) { - _parent = parent; + _source = source; + _timeSpan = timeSpan; + _timeShift = timeShift; + _scheduler = scheduler; } - private TimeSpan _totalTime; - private TimeSpan _nextShift; - private TimeSpan _nextSpan; - - private object _gate; - private Queue> _q; - - private SerialDisposable _timerD; - private RefCountDisposable _refCountDisposable; + protected override IDisposable Run(IObserver> observer, IDisposable cancel, Action setSink) + { + var sink = new _(this, observer, cancel); + setSink(sink); + return sink.Run(this); + } - public IDisposable Run() + private sealed class _ : Sink>, IObserver { - _totalTime = TimeSpan.Zero; - _nextShift = _parent._timeShift; - _nextSpan = _parent._timeSpan; + private readonly object _gate = new object(); + private readonly Queue> _q = new Queue>(); + private readonly SerialDisposable _timerD = new SerialDisposable(); - _gate = new object(); - _q = new Queue>(); + private readonly IScheduler _scheduler; + private readonly TimeSpan _timeShift; - _timerD = new SerialDisposable(); + public _(TimeSliding parent, IObserver> observer, IDisposable cancel) + : base(observer, cancel) + { + _scheduler = parent._scheduler; + _timeShift = parent._timeShift; + } - var groupDisposable = new CompositeDisposable(2) { _timerD }; - _refCountDisposable = new RefCountDisposable(groupDisposable); + private RefCountDisposable _refCountDisposable; + private TimeSpan _totalTime; + private TimeSpan _nextShift; + private TimeSpan _nextSpan; - CreateWindow(); - CreateTimer(); + public IDisposable Run(TimeSliding parent) + { + _totalTime = TimeSpan.Zero; + _nextShift = parent._timeShift; + _nextSpan = parent._timeSpan; - groupDisposable.Add(_parent._source.SubscribeSafe(this)); + var groupDisposable = new CompositeDisposable(2) { _timerD }; + _refCountDisposable = new RefCountDisposable(groupDisposable); - return _refCountDisposable; - } + CreateWindow(); + CreateTimer(); - private void CreateWindow() - { - var s = new Subject(); - _q.Enqueue(s); - base._observer.OnNext(new WindowObservable(s, _refCountDisposable)); - } + groupDisposable.Add(parent._source.SubscribeSafe(this)); - private void CreateTimer() - { - var m = new SingleAssignmentDisposable(); - _timerD.Disposable = m; + return _refCountDisposable; + } - var isSpan = false; - var isShift = false; - if (_nextSpan == _nextShift) + private void CreateWindow() { - isSpan = true; - isShift = true; + var s = new Subject(); + _q.Enqueue(s); + base._observer.OnNext(new WindowObservable(s, _refCountDisposable)); } - else if (_nextSpan < _nextShift) - isSpan = true; - else - isShift = true; - var newTotalTime = isSpan ? _nextSpan : _nextShift; - var ts = newTotalTime - _totalTime; - _totalTime = newTotalTime; + private void CreateTimer() + { + var m = new SingleAssignmentDisposable(); + _timerD.Disposable = m; - if (isSpan) - _nextSpan += _parent._timeShift; - if (isShift) - _nextShift += _parent._timeShift; + var isSpan = false; + var isShift = false; + if (_nextSpan == _nextShift) + { + isSpan = true; + isShift = true; + } + else if (_nextSpan < _nextShift) + isSpan = true; + else + isShift = true; - m.Disposable = _parent._scheduler.Schedule(new State { isSpan = isSpan, isShift = isShift }, ts, Tick); - } + var newTotalTime = isSpan ? _nextSpan : _nextShift; + var ts = newTotalTime - _totalTime; + _totalTime = newTotalTime; - struct State - { - public bool isSpan; - public bool isShift; - } + if (isSpan) + _nextSpan += _timeShift; + if (isShift) + _nextShift += _timeShift; - private IDisposable Tick(IScheduler self, State state) - { - lock (_gate) + m.Disposable = _scheduler.Schedule(new State { isSpan = isSpan, isShift = isShift }, ts, Tick); + } + + struct State { - // - // BREAKING CHANGE v2 > v1.x - Making behavior of sending OnCompleted to the window - // before sending out a new window consistent across all - // overloads of Window and Buffer. Before v2, the two - // operations below were reversed. - // - if (state.isSpan) - { - var s = _q.Dequeue(); - s.OnCompleted(); - } + public bool isSpan; + public bool isShift; + } - if (state.isShift) + private IDisposable Tick(IScheduler self, State state) + { + lock (_gate) { - CreateWindow(); + // + // BREAKING CHANGE v2 > v1.x - Making behavior of sending OnCompleted to the window + // before sending out a new window consistent across all + // overloads of Window and Buffer. Before v2, the two + // operations below were reversed. + // + if (state.isSpan) + { + var s = _q.Dequeue(); + s.OnCompleted(); + } + + if (state.isShift) + { + CreateWindow(); + } } - } - CreateTimer(); + CreateTimer(); - return Disposable.Empty; - } + return Disposable.Empty; + } - public void OnNext(TSource value) - { - lock (_gate) + public void OnNext(TSource value) { - foreach (var s in _q) - s.OnNext(value); + lock (_gate) + { + foreach (var s in _q) + s.OnNext(value); + } } - } - public void OnError(Exception error) - { - lock (_gate) + public void OnError(Exception error) { - foreach (var s in _q) - s.OnError(error); + lock (_gate) + { + foreach (var s in _q) + s.OnError(error); - base._observer.OnError(error); - base.Dispose(); + base._observer.OnError(error); + base.Dispose(); + } } - } - public void OnCompleted() - { - lock (_gate) + public void OnCompleted() { - foreach (var s in _q) - s.OnCompleted(); + lock (_gate) + { + foreach (var s in _q) + s.OnCompleted(); - base._observer.OnCompleted(); - base.Dispose(); + base._observer.OnCompleted(); + base.Dispose(); + } } } } - class TimeShiftImpl : Sink>, IObserver + internal sealed class TimeHopping : Producer> { - private readonly Window _parent; + private readonly IObservable _source; + private readonly TimeSpan _timeSpan; + private readonly IScheduler _scheduler; - public TimeShiftImpl(Window parent, IObserver> observer, IDisposable cancel) - : base(observer, cancel) + public TimeHopping(IObservable source, TimeSpan timeSpan, IScheduler scheduler) { - _parent = parent; + _source = source; + _timeSpan = timeSpan; + _scheduler = scheduler; } - private object _gate; - private Subject _subject; - private RefCountDisposable _refCountDisposable; + protected override IDisposable Run(IObserver> observer, IDisposable cancel, Action setSink) + { + var sink = new _(observer, cancel); + setSink(sink); + return sink.Run(this); + } - public IDisposable Run() + private sealed class _ : Sink>, IObserver { - _gate = new object(); + private readonly object _gate = new object(); - var groupDisposable = new CompositeDisposable(2); - _refCountDisposable = new RefCountDisposable(groupDisposable); + public _(IObserver> observer, IDisposable cancel) + : base(observer, cancel) + { + } - CreateWindow(); + private Subject _subject; + private RefCountDisposable _refCountDisposable; - groupDisposable.Add(_parent._scheduler.SchedulePeriodic(_parent._timeSpan, Tick)); - groupDisposable.Add(_parent._source.SubscribeSafe(this)); + public IDisposable Run(TimeHopping parent) + { + var groupDisposable = new CompositeDisposable(2); + _refCountDisposable = new RefCountDisposable(groupDisposable); - return _refCountDisposable; - } + CreateWindow(); - private void Tick() - { - lock (_gate) + groupDisposable.Add(parent._scheduler.SchedulePeriodic(parent._timeSpan, Tick)); + groupDisposable.Add(parent._source.SubscribeSafe(this)); + + return _refCountDisposable; + } + + private void Tick() { - _subject.OnCompleted(); - CreateWindow(); + lock (_gate) + { + _subject.OnCompleted(); + CreateWindow(); + } } - } - private void CreateWindow() - { - _subject = new Subject(); - base._observer.OnNext(new WindowObservable(_subject, _refCountDisposable)); - } + private void CreateWindow() + { + _subject = new Subject(); + base._observer.OnNext(new WindowObservable(_subject, _refCountDisposable)); + } - public void OnNext(TSource value) - { - lock (_gate) + public void OnNext(TSource value) { - _subject.OnNext(value); + lock (_gate) + { + _subject.OnNext(value); + } } - } - public void OnError(Exception error) - { - lock (_gate) + public void OnError(Exception error) { - _subject.OnError(error); + lock (_gate) + { + _subject.OnError(error); - base._observer.OnError(error); - base.Dispose(); + base._observer.OnError(error); + base.Dispose(); + } } - } - public void OnCompleted() - { - lock (_gate) + public void OnCompleted() { - _subject.OnCompleted(); + lock (_gate) + { + _subject.OnCompleted(); - base._observer.OnCompleted(); - base.Dispose(); + base._observer.OnCompleted(); + base.Dispose(); + } } } } - class BoundedWindowImpl : Sink>, IObserver + internal sealed class Ferry : Producer> { - private readonly Window _parent; + private readonly IObservable _source; + private readonly int _count; + private readonly TimeSpan _timeSpan; + private readonly IScheduler _scheduler; - public BoundedWindowImpl(Window parent, IObserver> observer, IDisposable cancel) - : base(observer, cancel) + public Ferry(IObservable source, TimeSpan timeSpan, int count, IScheduler scheduler) { - _parent = parent; + _source = source; + _timeSpan = timeSpan; + _count = count; + _scheduler = scheduler; } - private object _gate; - private ISubject _s; - private int _n; - private int _windowId; - - private SerialDisposable _timerD; - private RefCountDisposable _refCountDisposable; - - public IDisposable Run() + protected override IDisposable Run(IObserver> observer, IDisposable cancel, Action setSink) { - _gate = new object(); - _s = default(ISubject); - _n = 0; - _windowId = 0; - - _timerD = new SerialDisposable(); - var groupDisposable = new CompositeDisposable(2) { _timerD }; - _refCountDisposable = new RefCountDisposable(groupDisposable); - - _s = new Subject(); - base._observer.OnNext(new WindowObservable(_s, _refCountDisposable)); - CreateTimer(0); - - groupDisposable.Add(_parent._source.SubscribeSafe(this)); - - return _refCountDisposable; + var sink = new _(this, observer, cancel); + setSink(sink); + return sink.Run(_source); } - private void CreateTimer(int id) + private sealed class _ : Sink>, IObserver { - var m = new SingleAssignmentDisposable(); - _timerD.Disposable = m; + private readonly object _gate = new object(); + private readonly SerialDisposable _timerD = new SerialDisposable(); - m.Disposable = _parent._scheduler.Schedule(id, _parent._timeSpan, Tick); - } - - private IDisposable Tick(IScheduler self, int id) - { - var d = Disposable.Empty; + private readonly int _count; + private readonly TimeSpan _timeSpan; + private readonly IScheduler _scheduler; - var newId = 0; - lock (_gate) + public _(Ferry parent, IObserver> observer, IDisposable cancel) + : base(observer, cancel) { - if (id != _windowId) - return d; + _count = parent._count; + _timeSpan = parent._timeSpan; + _scheduler = parent._scheduler; + } + + private Subject _s; + private int _n; + private RefCountDisposable _refCountDisposable; + + public IDisposable Run(IObservable source) + { _n = 0; - newId = ++_windowId; - _s.OnCompleted(); + var groupDisposable = new CompositeDisposable(2) { _timerD }; + _refCountDisposable = new RefCountDisposable(groupDisposable); + _s = new Subject(); base._observer.OnNext(new WindowObservable(_s, _refCountDisposable)); - } + CreateTimer(_s); - CreateTimer(newId); + groupDisposable.Add(source.SubscribeSafe(this)); - return d; - } + return _refCountDisposable; + } - public void OnNext(TSource value) - { - var newWindow = false; - var newId = 0; + private void CreateTimer(Subject window) + { + var m = new SingleAssignmentDisposable(); + _timerD.Disposable = m; - lock (_gate) + m.Disposable = _scheduler.Schedule(window, _timeSpan, Tick); + } + + private IDisposable Tick(IScheduler self, Subject window) { - _s.OnNext(value); + var d = Disposable.Empty; - _n++; - if (_n == _parent._count) + var newWindow = default(Subject); + lock (_gate) { - newWindow = true; + if (window != _s) + return d; + _n = 0; - newId = ++_windowId; + newWindow = new Subject(); _s.OnCompleted(); - _s = new Subject(); + _s = newWindow; base._observer.OnNext(new WindowObservable(_s, _refCountDisposable)); } + + CreateTimer(newWindow); + + return d; } - if (newWindow) - CreateTimer(newId); - } + public void OnNext(TSource value) + { + var newWindow = default(Subject); - public void OnError(Exception error) - { - lock (_gate) + lock (_gate) + { + _s.OnNext(value); + + _n++; + if (_n == _count) + { + _n = 0; + newWindow = new Subject(); + + _s.OnCompleted(); + _s = newWindow; + base._observer.OnNext(new WindowObservable(_s, _refCountDisposable)); + } + } + + if (newWindow != null) + CreateTimer(newWindow); + } + + public void OnError(Exception error) { - _s.OnError(error); - base._observer.OnError(error); - base.Dispose(); + lock (_gate) + { + _s.OnError(error); + base._observer.OnError(error); + base.Dispose(); + } } - } - public void OnCompleted() - { - lock (_gate) + public void OnCompleted() { - _s.OnCompleted(); - base._observer.OnCompleted(); - base.Dispose(); + lock (_gate) + { + _s.OnCompleted(); + base._observer.OnCompleted(); + base.Dispose(); + } } } } } - internal sealed class Window : Producer> + internal static class Window { - private readonly IObservable _source; - private readonly Func> _windowClosingSelector; - private readonly IObservable _windowBoundaries; - - public Window(IObservable source, Func> windowClosingSelector) + internal sealed class Selector : Producer> { - _source = source; - _windowClosingSelector = windowClosingSelector; - } + private readonly IObservable _source; + private readonly Func> _windowClosingSelector; - public Window(IObservable source, IObservable windowBoundaries) - { - _source = source; - _windowBoundaries = windowBoundaries; - } - - protected override IDisposable Run(IObserver> observer, IDisposable cancel, Action setSink) - { - if (_windowClosingSelector != null) + public Selector(IObservable source, Func> windowClosingSelector) { - var sink = new _(this, observer, cancel); - setSink(sink); - return sink.Run(); + _source = source; + _windowClosingSelector = windowClosingSelector; } - else + + protected override IDisposable Run(IObserver> observer, IDisposable cancel, Action setSink) { - var sink = new Beta(this, observer, cancel); + var sink = new _(this, observer, cancel); setSink(sink); - return sink.Run(); + return sink.Run(_source); } - } - class _ : Sink>, IObserver - { - private readonly Window _parent; - - public _(Window parent, IObserver> observer, IDisposable cancel) - : base(observer, cancel) + private sealed class _ : Sink>, IObserver { - _parent = parent; - } + private readonly object _gate = new object(); + private readonly AsyncLock _windowGate = new AsyncLock(); + private readonly SerialDisposable _m = new SerialDisposable(); - private ISubject _window; - private object _gate; - private AsyncLock _windowGate; + private readonly Func> _windowClosingSelector; - private SerialDisposable _m; - private RefCountDisposable _refCountDisposable; + public _(Selector parent, IObserver> observer, IDisposable cancel) + : base(observer, cancel) + { + _windowClosingSelector = parent._windowClosingSelector; + } - public IDisposable Run() - { - _window = new Subject(); - _gate = new object(); - _windowGate = new AsyncLock(); + private ISubject _window; + private RefCountDisposable _refCountDisposable; - _m = new SerialDisposable(); - var groupDisposable = new CompositeDisposable(2) { _m }; - _refCountDisposable = new RefCountDisposable(groupDisposable); + public IDisposable Run(IObservable source) + { + _window = new Subject(); - var window = new WindowObservable(_window, _refCountDisposable); - base._observer.OnNext(window); + var groupDisposable = new CompositeDisposable(2) { _m }; + _refCountDisposable = new RefCountDisposable(groupDisposable); - groupDisposable.Add(_parent._source.SubscribeSafe(this)); + var window = new WindowObservable(_window, _refCountDisposable); + base._observer.OnNext(window); - _windowGate.Wait(CreateWindowClose); + groupDisposable.Add(source.SubscribeSafe(this)); - return _refCountDisposable; - } + _windowGate.Wait(CreateWindowClose); - private void CreateWindowClose() - { - var windowClose = default(IObservable); - try - { - windowClose = _parent._windowClosingSelector(); + return _refCountDisposable; } - catch (Exception exception) + + private void CreateWindowClose() { - lock (_gate) + var windowClose = default(IObservable); + try { - base._observer.OnError(exception); - base.Dispose(); + windowClose = _windowClosingSelector(); + } + catch (Exception exception) + { + lock (_gate) + { + base._observer.OnError(exception); + base.Dispose(); + } + return; } - return; + + var closingSubscription = new SingleAssignmentDisposable(); + _m.Disposable = closingSubscription; + closingSubscription.Disposable = windowClose.SubscribeSafe(new WindowClosingObserver(this, closingSubscription)); } - var closingSubscription = new SingleAssignmentDisposable(); - _m.Disposable = closingSubscription; - closingSubscription.Disposable = windowClose.SubscribeSafe(new Omega(this, closingSubscription)); - } + private void CloseWindow(IDisposable closingSubscription) + { + closingSubscription.Dispose(); - private void CloseWindow(IDisposable closingSubscription) - { - closingSubscription.Dispose(); + lock (_gate) + { + _window.OnCompleted(); + _window = new Subject(); - lock (_gate) - { - _window.OnCompleted(); - _window = new Subject(); + var window = new WindowObservable(_window, _refCountDisposable); + base._observer.OnNext(window); + } - var window = new WindowObservable(_window, _refCountDisposable); - base._observer.OnNext(window); + _windowGate.Wait(CreateWindowClose); } - _windowGate.Wait(CreateWindowClose); - } + private sealed class WindowClosingObserver : IObserver + { + private readonly _ _parent; + private readonly IDisposable _self; - class Omega : IObserver - { - private readonly _ _parent; - private readonly IDisposable _self; + public WindowClosingObserver(_ parent, IDisposable self) + { + _parent = parent; + _self = self; + } - public Omega(_ parent, IDisposable self) - { - _parent = parent; - _self = self; + public void OnNext(TWindowClosing value) + { + _parent.CloseWindow(_self); + } + + public void OnError(Exception error) + { + _parent.OnError(error); + } + + public void OnCompleted() + { + _parent.CloseWindow(_self); + } } - public void OnNext(TWindowClosing value) + public void OnNext(TSource value) { - _parent.CloseWindow(_self); + lock (_gate) + { + _window.OnNext(value); + } } public void OnError(Exception error) { - _parent.OnError(error); + lock (_gate) + { + _window.OnError(error); + base._observer.OnError(error); + base.Dispose(); + } } public void OnCompleted() { - _parent.CloseWindow(_self); + lock (_gate) + { + _window.OnCompleted(); + base._observer.OnCompleted(); + base.Dispose(); + } } } + } - public void OnNext(TSource value) - { - lock (_gate) - { - _window.OnNext(value); - } - } + internal sealed class Boundaries : Producer> + { + private readonly IObservable _source; + private readonly IObservable _windowBoundaries; - public void OnError(Exception error) + public Boundaries(IObservable source, IObservable windowBoundaries) { - lock (_gate) - { - _window.OnError(error); - base._observer.OnError(error); - base.Dispose(); - } + _source = source; + _windowBoundaries = windowBoundaries; } - public void OnCompleted() + protected override IDisposable Run(IObserver> observer, IDisposable cancel, Action setSink) { - lock (_gate) - { - _window.OnCompleted(); - base._observer.OnCompleted(); - base.Dispose(); - } + var sink = new _(this, observer, cancel); + setSink(sink); + return sink.Run(this); } - } - - class Beta : Sink>, IObserver - { - private readonly Window _parent; - public Beta(Window parent, IObserver> observer, IDisposable cancel) - : base(observer, cancel) + private sealed class _ : Sink>, IObserver { - _parent = parent; - } - - private ISubject _window; - private object _gate; + private readonly object _gate = new object(); - private RefCountDisposable _refCountDisposable; + private readonly IObservable _windowBoundaries; - public IDisposable Run() - { - _window = new Subject(); - _gate = new object(); + public _(Boundaries parent, IObserver> observer, IDisposable cancel) + : base(observer, cancel) + { + _windowBoundaries = parent._windowBoundaries; + } - var d = new CompositeDisposable(2); - _refCountDisposable = new RefCountDisposable(d); + private ISubject _window; + private RefCountDisposable _refCountDisposable; - var window = new WindowObservable(_window, _refCountDisposable); - base._observer.OnNext(window); + public IDisposable Run(Boundaries parent) + { + _window = new Subject(); - d.Add(_parent._source.SubscribeSafe(this)); - d.Add(_parent._windowBoundaries.SubscribeSafe(new Omega(this))); + var d = new CompositeDisposable(2); + _refCountDisposable = new RefCountDisposable(d); - return _refCountDisposable; - } + var window = new WindowObservable(_window, _refCountDisposable); + base._observer.OnNext(window); - class Omega : IObserver - { - private readonly Beta _parent; + d.Add(parent._source.SubscribeSafe(this)); + d.Add(parent._windowBoundaries.SubscribeSafe(new WindowClosingObserver(this))); - public Omega(Beta parent) - { - _parent = parent; + return _refCountDisposable; } - public void OnNext(TWindowClosing value) + private sealed class WindowClosingObserver : IObserver { - lock (_parent._gate) + private readonly _ _parent; + + public WindowClosingObserver(_ parent) { - _parent._window.OnCompleted(); - _parent._window = new Subject(); + _parent = parent; + } - var window = new WindowObservable(_parent._window, _parent._refCountDisposable); - _parent._observer.OnNext(window); + public void OnNext(TWindowClosing value) + { + lock (_parent._gate) + { + _parent._window.OnCompleted(); + _parent._window = new Subject(); + + var window = new WindowObservable(_parent._window, _parent._refCountDisposable); + _parent._observer.OnNext(window); + } } - } - public void OnError(Exception error) - { - _parent.OnError(error); - } + public void OnError(Exception error) + { + _parent.OnError(error); + } - public void OnCompleted() - { - _parent.OnCompleted(); + public void OnCompleted() + { + _parent.OnCompleted(); + } } - } - public void OnNext(TSource value) - { - lock (_gate) + public void OnNext(TSource value) { - _window.OnNext(value); + lock (_gate) + { + _window.OnNext(value); + } } - } - public void OnError(Exception error) - { - lock (_gate) + public void OnError(Exception error) { - _window.OnError(error); - base._observer.OnError(error); - base.Dispose(); + lock (_gate) + { + _window.OnError(error); + base._observer.OnError(error); + base.Dispose(); + } } - } - public void OnCompleted() - { - lock (_gate) + public void OnCompleted() { - _window.OnCompleted(); - base._observer.OnCompleted(); - base.Dispose(); + lock (_gate) + { + _window.OnCompleted(); + base._observer.OnCompleted(); + base.Dispose(); + } } } } diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/WithLatestFrom.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/WithLatestFrom.cs index 8e67771581..d78e325f4c 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/WithLatestFrom.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/WithLatestFrom.cs @@ -21,19 +21,19 @@ public WithLatestFrom(IObservable first, IObservable second, Fu protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - var sink = new _(this, observer, cancel); + var sink = new _(_resultSelector, observer, cancel); setSink(sink); - return sink.Run(); + return sink.Run(_first, _second); } - class _ : Sink + private sealed class _ : Sink { - private readonly WithLatestFrom _parent; + private readonly Func _resultSelector; - public _(WithLatestFrom parent, IObserver observer, IDisposable cancel) + public _(Func resultSelector, IObserver observer, IDisposable cancel) : base(observer, cancel) { - _parent = parent; + _resultSelector = resultSelector; } private object _gate; @@ -42,27 +42,27 @@ public _(WithLatestFrom parent, IObserver obs private object _latestGate; - public IDisposable Run() + public IDisposable Run(IObservable first, IObservable second) { _gate = new object(); _latestGate = new object(); var sndSubscription = new SingleAssignmentDisposable(); - var fstO = new F(this); - var sndO = new S(this, sndSubscription); + var fstO = new FirstObserver(this); + var sndO = new SecondObserver(this, sndSubscription); - var fstSubscription = _parent._first.SubscribeSafe(fstO); - sndSubscription.Disposable = _parent._second.SubscribeSafe(sndO); + var fstSubscription = first.SubscribeSafe(fstO); + sndSubscription.Disposable = second.SubscribeSafe(sndO); return StableCompositeDisposable.Create(fstSubscription, sndSubscription); } - class F : IObserver + private sealed class FirstObserver : IObserver { private readonly _ _parent; - public F(_ parent) + public FirstObserver(_ parent) { _parent = parent; } @@ -101,7 +101,7 @@ public void OnNext(TFirst value) try { - res = _parent._parent._resultSelector(value, latest); + res = _parent._resultSelector(value, latest); } catch (Exception ex) { @@ -122,12 +122,12 @@ public void OnNext(TFirst value) } } - class S : IObserver + private sealed class SecondObserver : IObserver { private readonly _ _parent; private readonly IDisposable _self; - public S(_ parent, IDisposable self) + public SecondObserver(_ parent, IDisposable self) { _parent = parent; _self = self; diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Zip.Generated.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Zip.Generated.cs index 810cd4db37..1c8cb0aef0 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Zip.Generated.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Zip.Generated.cs @@ -10,7 +10,7 @@ namespace System.Reactive.Linq.ObservableImpl /* The following code is generated by a T4 template. */ - #region Zip auto-generated code (4/14/2017 12:34:48 PM) + #region Zip auto-generated code (4/17/2017 4:46:17 PM) internal sealed class Zip : Producer { @@ -29,26 +29,26 @@ public Zip(IObservable source1, IObservable source2, IObservable sou protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - var sink = new _(this, observer, cancel); + var sink = new _(_resultSelector, observer, cancel); setSink(sink); - return sink.Run(); + return sink.Run(_source1, _source2, _source3); } - class _ : ZipSink + private sealed class _ : ZipSink { - private readonly Zip _parent; + private readonly Func _resultSelector; - public _(Zip parent, IObserver observer, IDisposable cancel) + public _(Func resultSelector, IObserver observer, IDisposable cancel) : base(3, observer, cancel) { - _parent = parent; + _resultSelector = resultSelector; } private ZipObserver _observer1; private ZipObserver _observer2; private ZipObserver _observer3; - public IDisposable Run() + public IDisposable Run(IObservable source1, IObservable source2, IObservable source3) { var disposables = new IDisposable[4]; @@ -67,9 +67,9 @@ public IDisposable Run() _observer3 = new ZipObserver(_gate, this, 2, d3); base.Queues[2] = _observer3.Values; - d1.Disposable = _parent._source1.SubscribeSafe(_observer1); - d2.Disposable = _parent._source2.SubscribeSafe(_observer2); - d3.Disposable = _parent._source3.SubscribeSafe(_observer3); + d1.Disposable = source1.SubscribeSafe(_observer1); + d2.Disposable = source2.SubscribeSafe(_observer2); + d3.Disposable = source3.SubscribeSafe(_observer3); disposables[3] = Disposable.Create(() => { @@ -81,10 +81,7 @@ public IDisposable Run() return StableCompositeDisposable.Create(disposables); } - protected override TResult GetResult() - { - return _parent._resultSelector(_observer1.Values.Dequeue(), _observer2.Values.Dequeue(), _observer3.Values.Dequeue()); - } + protected override TResult GetResult() => _resultSelector(_observer1.Values.Dequeue(), _observer2.Values.Dequeue(), _observer3.Values.Dequeue()); } } @@ -107,19 +104,19 @@ public Zip(IObservable source1, IObservable source2, IObservable sou protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - var sink = new _(this, observer, cancel); + var sink = new _(_resultSelector, observer, cancel); setSink(sink); - return sink.Run(); + return sink.Run(_source1, _source2, _source3, _source4); } - class _ : ZipSink + private sealed class _ : ZipSink { - private readonly Zip _parent; + private readonly Func _resultSelector; - public _(Zip parent, IObserver observer, IDisposable cancel) + public _(Func resultSelector, IObserver observer, IDisposable cancel) : base(4, observer, cancel) { - _parent = parent; + _resultSelector = resultSelector; } private ZipObserver _observer1; @@ -127,7 +124,7 @@ public _(Zip parent, IObserver observer, IDisp private ZipObserver _observer3; private ZipObserver _observer4; - public IDisposable Run() + public IDisposable Run(IObservable source1, IObservable source2, IObservable source3, IObservable source4) { var disposables = new IDisposable[5]; @@ -151,10 +148,10 @@ public IDisposable Run() _observer4 = new ZipObserver(_gate, this, 3, d4); base.Queues[3] = _observer4.Values; - d1.Disposable = _parent._source1.SubscribeSafe(_observer1); - d2.Disposable = _parent._source2.SubscribeSafe(_observer2); - d3.Disposable = _parent._source3.SubscribeSafe(_observer3); - d4.Disposable = _parent._source4.SubscribeSafe(_observer4); + d1.Disposable = source1.SubscribeSafe(_observer1); + d2.Disposable = source2.SubscribeSafe(_observer2); + d3.Disposable = source3.SubscribeSafe(_observer3); + d4.Disposable = source4.SubscribeSafe(_observer4); disposables[4] = Disposable.Create(() => { @@ -167,10 +164,7 @@ public IDisposable Run() return StableCompositeDisposable.Create(disposables); } - protected override TResult GetResult() - { - return _parent._resultSelector(_observer1.Values.Dequeue(), _observer2.Values.Dequeue(), _observer3.Values.Dequeue(), _observer4.Values.Dequeue()); - } + protected override TResult GetResult() => _resultSelector(_observer1.Values.Dequeue(), _observer2.Values.Dequeue(), _observer3.Values.Dequeue(), _observer4.Values.Dequeue()); } } @@ -195,19 +189,19 @@ public Zip(IObservable source1, IObservable source2, IObservable sou protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - var sink = new _(this, observer, cancel); + var sink = new _(_resultSelector, observer, cancel); setSink(sink); - return sink.Run(); + return sink.Run(_source1, _source2, _source3, _source4, _source5); } - class _ : ZipSink + private sealed class _ : ZipSink { - private readonly Zip _parent; + private readonly Func _resultSelector; - public _(Zip parent, IObserver observer, IDisposable cancel) + public _(Func resultSelector, IObserver observer, IDisposable cancel) : base(5, observer, cancel) { - _parent = parent; + _resultSelector = resultSelector; } private ZipObserver _observer1; @@ -216,7 +210,7 @@ public _(Zip parent, IObserver observer, I private ZipObserver _observer4; private ZipObserver _observer5; - public IDisposable Run() + public IDisposable Run(IObservable source1, IObservable source2, IObservable source3, IObservable source4, IObservable source5) { var disposables = new IDisposable[6]; @@ -245,11 +239,11 @@ public IDisposable Run() _observer5 = new ZipObserver(_gate, this, 4, d5); base.Queues[4] = _observer5.Values; - d1.Disposable = _parent._source1.SubscribeSafe(_observer1); - d2.Disposable = _parent._source2.SubscribeSafe(_observer2); - d3.Disposable = _parent._source3.SubscribeSafe(_observer3); - d4.Disposable = _parent._source4.SubscribeSafe(_observer4); - d5.Disposable = _parent._source5.SubscribeSafe(_observer5); + d1.Disposable = source1.SubscribeSafe(_observer1); + d2.Disposable = source2.SubscribeSafe(_observer2); + d3.Disposable = source3.SubscribeSafe(_observer3); + d4.Disposable = source4.SubscribeSafe(_observer4); + d5.Disposable = source5.SubscribeSafe(_observer5); disposables[5] = Disposable.Create(() => { @@ -263,10 +257,7 @@ public IDisposable Run() return StableCompositeDisposable.Create(disposables); } - protected override TResult GetResult() - { - return _parent._resultSelector(_observer1.Values.Dequeue(), _observer2.Values.Dequeue(), _observer3.Values.Dequeue(), _observer4.Values.Dequeue(), _observer5.Values.Dequeue()); - } + protected override TResult GetResult() => _resultSelector(_observer1.Values.Dequeue(), _observer2.Values.Dequeue(), _observer3.Values.Dequeue(), _observer4.Values.Dequeue(), _observer5.Values.Dequeue()); } } @@ -293,19 +284,19 @@ public Zip(IObservable source1, IObservable source2, IObservable sou protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - var sink = new _(this, observer, cancel); + var sink = new _(_resultSelector, observer, cancel); setSink(sink); - return sink.Run(); + return sink.Run(_source1, _source2, _source3, _source4, _source5, _source6); } - class _ : ZipSink + private sealed class _ : ZipSink { - private readonly Zip _parent; + private readonly Func _resultSelector; - public _(Zip parent, IObserver observer, IDisposable cancel) + public _(Func resultSelector, IObserver observer, IDisposable cancel) : base(6, observer, cancel) { - _parent = parent; + _resultSelector = resultSelector; } private ZipObserver _observer1; @@ -315,7 +306,7 @@ public _(Zip parent, IObserver observe private ZipObserver _observer5; private ZipObserver _observer6; - public IDisposable Run() + public IDisposable Run(IObservable source1, IObservable source2, IObservable source3, IObservable source4, IObservable source5, IObservable source6) { var disposables = new IDisposable[7]; @@ -349,12 +340,12 @@ public IDisposable Run() _observer6 = new ZipObserver(_gate, this, 5, d6); base.Queues[5] = _observer6.Values; - d1.Disposable = _parent._source1.SubscribeSafe(_observer1); - d2.Disposable = _parent._source2.SubscribeSafe(_observer2); - d3.Disposable = _parent._source3.SubscribeSafe(_observer3); - d4.Disposable = _parent._source4.SubscribeSafe(_observer4); - d5.Disposable = _parent._source5.SubscribeSafe(_observer5); - d6.Disposable = _parent._source6.SubscribeSafe(_observer6); + d1.Disposable = source1.SubscribeSafe(_observer1); + d2.Disposable = source2.SubscribeSafe(_observer2); + d3.Disposable = source3.SubscribeSafe(_observer3); + d4.Disposable = source4.SubscribeSafe(_observer4); + d5.Disposable = source5.SubscribeSafe(_observer5); + d6.Disposable = source6.SubscribeSafe(_observer6); disposables[6] = Disposable.Create(() => { @@ -369,10 +360,7 @@ public IDisposable Run() return StableCompositeDisposable.Create(disposables); } - protected override TResult GetResult() - { - return _parent._resultSelector(_observer1.Values.Dequeue(), _observer2.Values.Dequeue(), _observer3.Values.Dequeue(), _observer4.Values.Dequeue(), _observer5.Values.Dequeue(), _observer6.Values.Dequeue()); - } + protected override TResult GetResult() => _resultSelector(_observer1.Values.Dequeue(), _observer2.Values.Dequeue(), _observer3.Values.Dequeue(), _observer4.Values.Dequeue(), _observer5.Values.Dequeue(), _observer6.Values.Dequeue()); } } @@ -401,19 +389,19 @@ public Zip(IObservable source1, IObservable source2, IObservable sou protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - var sink = new _(this, observer, cancel); + var sink = new _(_resultSelector, observer, cancel); setSink(sink); - return sink.Run(); + return sink.Run(_source1, _source2, _source3, _source4, _source5, _source6, _source7); } - class _ : ZipSink + private sealed class _ : ZipSink { - private readonly Zip _parent; + private readonly Func _resultSelector; - public _(Zip parent, IObserver observer, IDisposable cancel) + public _(Func resultSelector, IObserver observer, IDisposable cancel) : base(7, observer, cancel) { - _parent = parent; + _resultSelector = resultSelector; } private ZipObserver _observer1; @@ -424,7 +412,7 @@ public _(Zip parent, IObserver obs private ZipObserver _observer6; private ZipObserver _observer7; - public IDisposable Run() + public IDisposable Run(IObservable source1, IObservable source2, IObservable source3, IObservable source4, IObservable source5, IObservable source6, IObservable source7) { var disposables = new IDisposable[8]; @@ -463,13 +451,13 @@ public IDisposable Run() _observer7 = new ZipObserver(_gate, this, 6, d7); base.Queues[6] = _observer7.Values; - d1.Disposable = _parent._source1.SubscribeSafe(_observer1); - d2.Disposable = _parent._source2.SubscribeSafe(_observer2); - d3.Disposable = _parent._source3.SubscribeSafe(_observer3); - d4.Disposable = _parent._source4.SubscribeSafe(_observer4); - d5.Disposable = _parent._source5.SubscribeSafe(_observer5); - d6.Disposable = _parent._source6.SubscribeSafe(_observer6); - d7.Disposable = _parent._source7.SubscribeSafe(_observer7); + d1.Disposable = source1.SubscribeSafe(_observer1); + d2.Disposable = source2.SubscribeSafe(_observer2); + d3.Disposable = source3.SubscribeSafe(_observer3); + d4.Disposable = source4.SubscribeSafe(_observer4); + d5.Disposable = source5.SubscribeSafe(_observer5); + d6.Disposable = source6.SubscribeSafe(_observer6); + d7.Disposable = source7.SubscribeSafe(_observer7); disposables[7] = Disposable.Create(() => { @@ -485,10 +473,7 @@ public IDisposable Run() return StableCompositeDisposable.Create(disposables); } - protected override TResult GetResult() - { - return _parent._resultSelector(_observer1.Values.Dequeue(), _observer2.Values.Dequeue(), _observer3.Values.Dequeue(), _observer4.Values.Dequeue(), _observer5.Values.Dequeue(), _observer6.Values.Dequeue(), _observer7.Values.Dequeue()); - } + protected override TResult GetResult() => _resultSelector(_observer1.Values.Dequeue(), _observer2.Values.Dequeue(), _observer3.Values.Dequeue(), _observer4.Values.Dequeue(), _observer5.Values.Dequeue(), _observer6.Values.Dequeue(), _observer7.Values.Dequeue()); } } @@ -519,19 +504,19 @@ public Zip(IObservable source1, IObservable source2, IObservable sou protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - var sink = new _(this, observer, cancel); + var sink = new _(_resultSelector, observer, cancel); setSink(sink); - return sink.Run(); + return sink.Run(_source1, _source2, _source3, _source4, _source5, _source6, _source7, _source8); } - class _ : ZipSink + private sealed class _ : ZipSink { - private readonly Zip _parent; + private readonly Func _resultSelector; - public _(Zip parent, IObserver observer, IDisposable cancel) + public _(Func resultSelector, IObserver observer, IDisposable cancel) : base(8, observer, cancel) { - _parent = parent; + _resultSelector = resultSelector; } private ZipObserver _observer1; @@ -543,7 +528,7 @@ public _(Zip parent, IObserver private ZipObserver _observer7; private ZipObserver _observer8; - public IDisposable Run() + public IDisposable Run(IObservable source1, IObservable source2, IObservable source3, IObservable source4, IObservable source5, IObservable source6, IObservable source7, IObservable source8) { var disposables = new IDisposable[9]; @@ -587,14 +572,14 @@ public IDisposable Run() _observer8 = new ZipObserver(_gate, this, 7, d8); base.Queues[7] = _observer8.Values; - d1.Disposable = _parent._source1.SubscribeSafe(_observer1); - d2.Disposable = _parent._source2.SubscribeSafe(_observer2); - d3.Disposable = _parent._source3.SubscribeSafe(_observer3); - d4.Disposable = _parent._source4.SubscribeSafe(_observer4); - d5.Disposable = _parent._source5.SubscribeSafe(_observer5); - d6.Disposable = _parent._source6.SubscribeSafe(_observer6); - d7.Disposable = _parent._source7.SubscribeSafe(_observer7); - d8.Disposable = _parent._source8.SubscribeSafe(_observer8); + d1.Disposable = source1.SubscribeSafe(_observer1); + d2.Disposable = source2.SubscribeSafe(_observer2); + d3.Disposable = source3.SubscribeSafe(_observer3); + d4.Disposable = source4.SubscribeSafe(_observer4); + d5.Disposable = source5.SubscribeSafe(_observer5); + d6.Disposable = source6.SubscribeSafe(_observer6); + d7.Disposable = source7.SubscribeSafe(_observer7); + d8.Disposable = source8.SubscribeSafe(_observer8); disposables[8] = Disposable.Create(() => { @@ -611,10 +596,7 @@ public IDisposable Run() return StableCompositeDisposable.Create(disposables); } - protected override TResult GetResult() - { - return _parent._resultSelector(_observer1.Values.Dequeue(), _observer2.Values.Dequeue(), _observer3.Values.Dequeue(), _observer4.Values.Dequeue(), _observer5.Values.Dequeue(), _observer6.Values.Dequeue(), _observer7.Values.Dequeue(), _observer8.Values.Dequeue()); - } + protected override TResult GetResult() => _resultSelector(_observer1.Values.Dequeue(), _observer2.Values.Dequeue(), _observer3.Values.Dequeue(), _observer4.Values.Dequeue(), _observer5.Values.Dequeue(), _observer6.Values.Dequeue(), _observer7.Values.Dequeue(), _observer8.Values.Dequeue()); } } @@ -647,19 +629,19 @@ public Zip(IObservable source1, IObservable source2, IObservable sou protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - var sink = new _(this, observer, cancel); + var sink = new _(_resultSelector, observer, cancel); setSink(sink); - return sink.Run(); + return sink.Run(_source1, _source2, _source3, _source4, _source5, _source6, _source7, _source8, _source9); } - class _ : ZipSink + private sealed class _ : ZipSink { - private readonly Zip _parent; + private readonly Func _resultSelector; - public _(Zip parent, IObserver observer, IDisposable cancel) + public _(Func resultSelector, IObserver observer, IDisposable cancel) : base(9, observer, cancel) { - _parent = parent; + _resultSelector = resultSelector; } private ZipObserver _observer1; @@ -672,7 +654,7 @@ public _(Zip parent, IObserver _observer8; private ZipObserver _observer9; - public IDisposable Run() + public IDisposable Run(IObservable source1, IObservable source2, IObservable source3, IObservable source4, IObservable source5, IObservable source6, IObservable source7, IObservable source8, IObservable source9) { var disposables = new IDisposable[10]; @@ -721,15 +703,15 @@ public IDisposable Run() _observer9 = new ZipObserver(_gate, this, 8, d9); base.Queues[8] = _observer9.Values; - d1.Disposable = _parent._source1.SubscribeSafe(_observer1); - d2.Disposable = _parent._source2.SubscribeSafe(_observer2); - d3.Disposable = _parent._source3.SubscribeSafe(_observer3); - d4.Disposable = _parent._source4.SubscribeSafe(_observer4); - d5.Disposable = _parent._source5.SubscribeSafe(_observer5); - d6.Disposable = _parent._source6.SubscribeSafe(_observer6); - d7.Disposable = _parent._source7.SubscribeSafe(_observer7); - d8.Disposable = _parent._source8.SubscribeSafe(_observer8); - d9.Disposable = _parent._source9.SubscribeSafe(_observer9); + d1.Disposable = source1.SubscribeSafe(_observer1); + d2.Disposable = source2.SubscribeSafe(_observer2); + d3.Disposable = source3.SubscribeSafe(_observer3); + d4.Disposable = source4.SubscribeSafe(_observer4); + d5.Disposable = source5.SubscribeSafe(_observer5); + d6.Disposable = source6.SubscribeSafe(_observer6); + d7.Disposable = source7.SubscribeSafe(_observer7); + d8.Disposable = source8.SubscribeSafe(_observer8); + d9.Disposable = source9.SubscribeSafe(_observer9); disposables[9] = Disposable.Create(() => { @@ -747,10 +729,7 @@ public IDisposable Run() return StableCompositeDisposable.Create(disposables); } - protected override TResult GetResult() - { - return _parent._resultSelector(_observer1.Values.Dequeue(), _observer2.Values.Dequeue(), _observer3.Values.Dequeue(), _observer4.Values.Dequeue(), _observer5.Values.Dequeue(), _observer6.Values.Dequeue(), _observer7.Values.Dequeue(), _observer8.Values.Dequeue(), _observer9.Values.Dequeue()); - } + protected override TResult GetResult() => _resultSelector(_observer1.Values.Dequeue(), _observer2.Values.Dequeue(), _observer3.Values.Dequeue(), _observer4.Values.Dequeue(), _observer5.Values.Dequeue(), _observer6.Values.Dequeue(), _observer7.Values.Dequeue(), _observer8.Values.Dequeue(), _observer9.Values.Dequeue()); } } @@ -785,19 +764,19 @@ public Zip(IObservable source1, IObservable source2, IObservable sou protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - var sink = new _(this, observer, cancel); + var sink = new _(_resultSelector, observer, cancel); setSink(sink); - return sink.Run(); + return sink.Run(_source1, _source2, _source3, _source4, _source5, _source6, _source7, _source8, _source9, _source10); } - class _ : ZipSink + private sealed class _ : ZipSink { - private readonly Zip _parent; + private readonly Func _resultSelector; - public _(Zip parent, IObserver observer, IDisposable cancel) + public _(Func resultSelector, IObserver observer, IDisposable cancel) : base(10, observer, cancel) { - _parent = parent; + _resultSelector = resultSelector; } private ZipObserver _observer1; @@ -811,7 +790,7 @@ public _(Zip parent, IObserver private ZipObserver _observer9; private ZipObserver _observer10; - public IDisposable Run() + public IDisposable Run(IObservable source1, IObservable source2, IObservable source3, IObservable source4, IObservable source5, IObservable source6, IObservable source7, IObservable source8, IObservable source9, IObservable source10) { var disposables = new IDisposable[11]; @@ -865,16 +844,16 @@ public IDisposable Run() _observer10 = new ZipObserver(_gate, this, 9, d10); base.Queues[9] = _observer10.Values; - d1.Disposable = _parent._source1.SubscribeSafe(_observer1); - d2.Disposable = _parent._source2.SubscribeSafe(_observer2); - d3.Disposable = _parent._source3.SubscribeSafe(_observer3); - d4.Disposable = _parent._source4.SubscribeSafe(_observer4); - d5.Disposable = _parent._source5.SubscribeSafe(_observer5); - d6.Disposable = _parent._source6.SubscribeSafe(_observer6); - d7.Disposable = _parent._source7.SubscribeSafe(_observer7); - d8.Disposable = _parent._source8.SubscribeSafe(_observer8); - d9.Disposable = _parent._source9.SubscribeSafe(_observer9); - d10.Disposable = _parent._source10.SubscribeSafe(_observer10); + d1.Disposable = source1.SubscribeSafe(_observer1); + d2.Disposable = source2.SubscribeSafe(_observer2); + d3.Disposable = source3.SubscribeSafe(_observer3); + d4.Disposable = source4.SubscribeSafe(_observer4); + d5.Disposable = source5.SubscribeSafe(_observer5); + d6.Disposable = source6.SubscribeSafe(_observer6); + d7.Disposable = source7.SubscribeSafe(_observer7); + d8.Disposable = source8.SubscribeSafe(_observer8); + d9.Disposable = source9.SubscribeSafe(_observer9); + d10.Disposable = source10.SubscribeSafe(_observer10); disposables[10] = Disposable.Create(() => { @@ -893,10 +872,7 @@ public IDisposable Run() return StableCompositeDisposable.Create(disposables); } - protected override TResult GetResult() - { - return _parent._resultSelector(_observer1.Values.Dequeue(), _observer2.Values.Dequeue(), _observer3.Values.Dequeue(), _observer4.Values.Dequeue(), _observer5.Values.Dequeue(), _observer6.Values.Dequeue(), _observer7.Values.Dequeue(), _observer8.Values.Dequeue(), _observer9.Values.Dequeue(), _observer10.Values.Dequeue()); - } + protected override TResult GetResult() => _resultSelector(_observer1.Values.Dequeue(), _observer2.Values.Dequeue(), _observer3.Values.Dequeue(), _observer4.Values.Dequeue(), _observer5.Values.Dequeue(), _observer6.Values.Dequeue(), _observer7.Values.Dequeue(), _observer8.Values.Dequeue(), _observer9.Values.Dequeue(), _observer10.Values.Dequeue()); } } @@ -933,19 +909,19 @@ public Zip(IObservable source1, IObservable source2, IObservable sou protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - var sink = new _(this, observer, cancel); + var sink = new _(_resultSelector, observer, cancel); setSink(sink); - return sink.Run(); + return sink.Run(_source1, _source2, _source3, _source4, _source5, _source6, _source7, _source8, _source9, _source10, _source11); } - class _ : ZipSink + private sealed class _ : ZipSink { - private readonly Zip _parent; + private readonly Func _resultSelector; - public _(Zip parent, IObserver observer, IDisposable cancel) + public _(Func resultSelector, IObserver observer, IDisposable cancel) : base(11, observer, cancel) { - _parent = parent; + _resultSelector = resultSelector; } private ZipObserver _observer1; @@ -960,7 +936,7 @@ public _(Zip parent, IObs private ZipObserver _observer10; private ZipObserver _observer11; - public IDisposable Run() + public IDisposable Run(IObservable source1, IObservable source2, IObservable source3, IObservable source4, IObservable source5, IObservable source6, IObservable source7, IObservable source8, IObservable source9, IObservable source10, IObservable source11) { var disposables = new IDisposable[12]; @@ -1019,17 +995,17 @@ public IDisposable Run() _observer11 = new ZipObserver(_gate, this, 10, d11); base.Queues[10] = _observer11.Values; - d1.Disposable = _parent._source1.SubscribeSafe(_observer1); - d2.Disposable = _parent._source2.SubscribeSafe(_observer2); - d3.Disposable = _parent._source3.SubscribeSafe(_observer3); - d4.Disposable = _parent._source4.SubscribeSafe(_observer4); - d5.Disposable = _parent._source5.SubscribeSafe(_observer5); - d6.Disposable = _parent._source6.SubscribeSafe(_observer6); - d7.Disposable = _parent._source7.SubscribeSafe(_observer7); - d8.Disposable = _parent._source8.SubscribeSafe(_observer8); - d9.Disposable = _parent._source9.SubscribeSafe(_observer9); - d10.Disposable = _parent._source10.SubscribeSafe(_observer10); - d11.Disposable = _parent._source11.SubscribeSafe(_observer11); + d1.Disposable = source1.SubscribeSafe(_observer1); + d2.Disposable = source2.SubscribeSafe(_observer2); + d3.Disposable = source3.SubscribeSafe(_observer3); + d4.Disposable = source4.SubscribeSafe(_observer4); + d5.Disposable = source5.SubscribeSafe(_observer5); + d6.Disposable = source6.SubscribeSafe(_observer6); + d7.Disposable = source7.SubscribeSafe(_observer7); + d8.Disposable = source8.SubscribeSafe(_observer8); + d9.Disposable = source9.SubscribeSafe(_observer9); + d10.Disposable = source10.SubscribeSafe(_observer10); + d11.Disposable = source11.SubscribeSafe(_observer11); disposables[11] = Disposable.Create(() => { @@ -1049,10 +1025,7 @@ public IDisposable Run() return StableCompositeDisposable.Create(disposables); } - protected override TResult GetResult() - { - return _parent._resultSelector(_observer1.Values.Dequeue(), _observer2.Values.Dequeue(), _observer3.Values.Dequeue(), _observer4.Values.Dequeue(), _observer5.Values.Dequeue(), _observer6.Values.Dequeue(), _observer7.Values.Dequeue(), _observer8.Values.Dequeue(), _observer9.Values.Dequeue(), _observer10.Values.Dequeue(), _observer11.Values.Dequeue()); - } + protected override TResult GetResult() => _resultSelector(_observer1.Values.Dequeue(), _observer2.Values.Dequeue(), _observer3.Values.Dequeue(), _observer4.Values.Dequeue(), _observer5.Values.Dequeue(), _observer6.Values.Dequeue(), _observer7.Values.Dequeue(), _observer8.Values.Dequeue(), _observer9.Values.Dequeue(), _observer10.Values.Dequeue(), _observer11.Values.Dequeue()); } } @@ -1091,19 +1064,19 @@ public Zip(IObservable source1, IObservable source2, IObservable sou protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - var sink = new _(this, observer, cancel); + var sink = new _(_resultSelector, observer, cancel); setSink(sink); - return sink.Run(); + return sink.Run(_source1, _source2, _source3, _source4, _source5, _source6, _source7, _source8, _source9, _source10, _source11, _source12); } - class _ : ZipSink + private sealed class _ : ZipSink { - private readonly Zip _parent; + private readonly Func _resultSelector; - public _(Zip parent, IObserver observer, IDisposable cancel) + public _(Func resultSelector, IObserver observer, IDisposable cancel) : base(12, observer, cancel) { - _parent = parent; + _resultSelector = resultSelector; } private ZipObserver _observer1; @@ -1119,7 +1092,7 @@ public _(Zip parent, private ZipObserver _observer11; private ZipObserver _observer12; - public IDisposable Run() + public IDisposable Run(IObservable source1, IObservable source2, IObservable source3, IObservable source4, IObservable source5, IObservable source6, IObservable source7, IObservable source8, IObservable source9, IObservable source10, IObservable source11, IObservable source12) { var disposables = new IDisposable[13]; @@ -1183,18 +1156,18 @@ public IDisposable Run() _observer12 = new ZipObserver(_gate, this, 11, d12); base.Queues[11] = _observer12.Values; - d1.Disposable = _parent._source1.SubscribeSafe(_observer1); - d2.Disposable = _parent._source2.SubscribeSafe(_observer2); - d3.Disposable = _parent._source3.SubscribeSafe(_observer3); - d4.Disposable = _parent._source4.SubscribeSafe(_observer4); - d5.Disposable = _parent._source5.SubscribeSafe(_observer5); - d6.Disposable = _parent._source6.SubscribeSafe(_observer6); - d7.Disposable = _parent._source7.SubscribeSafe(_observer7); - d8.Disposable = _parent._source8.SubscribeSafe(_observer8); - d9.Disposable = _parent._source9.SubscribeSafe(_observer9); - d10.Disposable = _parent._source10.SubscribeSafe(_observer10); - d11.Disposable = _parent._source11.SubscribeSafe(_observer11); - d12.Disposable = _parent._source12.SubscribeSafe(_observer12); + d1.Disposable = source1.SubscribeSafe(_observer1); + d2.Disposable = source2.SubscribeSafe(_observer2); + d3.Disposable = source3.SubscribeSafe(_observer3); + d4.Disposable = source4.SubscribeSafe(_observer4); + d5.Disposable = source5.SubscribeSafe(_observer5); + d6.Disposable = source6.SubscribeSafe(_observer6); + d7.Disposable = source7.SubscribeSafe(_observer7); + d8.Disposable = source8.SubscribeSafe(_observer8); + d9.Disposable = source9.SubscribeSafe(_observer9); + d10.Disposable = source10.SubscribeSafe(_observer10); + d11.Disposable = source11.SubscribeSafe(_observer11); + d12.Disposable = source12.SubscribeSafe(_observer12); disposables[12] = Disposable.Create(() => { @@ -1215,10 +1188,7 @@ public IDisposable Run() return StableCompositeDisposable.Create(disposables); } - protected override TResult GetResult() - { - return _parent._resultSelector(_observer1.Values.Dequeue(), _observer2.Values.Dequeue(), _observer3.Values.Dequeue(), _observer4.Values.Dequeue(), _observer5.Values.Dequeue(), _observer6.Values.Dequeue(), _observer7.Values.Dequeue(), _observer8.Values.Dequeue(), _observer9.Values.Dequeue(), _observer10.Values.Dequeue(), _observer11.Values.Dequeue(), _observer12.Values.Dequeue()); - } + protected override TResult GetResult() => _resultSelector(_observer1.Values.Dequeue(), _observer2.Values.Dequeue(), _observer3.Values.Dequeue(), _observer4.Values.Dequeue(), _observer5.Values.Dequeue(), _observer6.Values.Dequeue(), _observer7.Values.Dequeue(), _observer8.Values.Dequeue(), _observer9.Values.Dequeue(), _observer10.Values.Dequeue(), _observer11.Values.Dequeue(), _observer12.Values.Dequeue()); } } @@ -1259,19 +1229,19 @@ public Zip(IObservable source1, IObservable source2, IObservable sou protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - var sink = new _(this, observer, cancel); + var sink = new _(_resultSelector, observer, cancel); setSink(sink); - return sink.Run(); + return sink.Run(_source1, _source2, _source3, _source4, _source5, _source6, _source7, _source8, _source9, _source10, _source11, _source12, _source13); } - class _ : ZipSink + private sealed class _ : ZipSink { - private readonly Zip _parent; + private readonly Func _resultSelector; - public _(Zip parent, IObserver observer, IDisposable cancel) + public _(Func resultSelector, IObserver observer, IDisposable cancel) : base(13, observer, cancel) { - _parent = parent; + _resultSelector = resultSelector; } private ZipObserver _observer1; @@ -1288,7 +1258,7 @@ public _(Zip pa private ZipObserver _observer12; private ZipObserver _observer13; - public IDisposable Run() + public IDisposable Run(IObservable source1, IObservable source2, IObservable source3, IObservable source4, IObservable source5, IObservable source6, IObservable source7, IObservable source8, IObservable source9, IObservable source10, IObservable source11, IObservable source12, IObservable source13) { var disposables = new IDisposable[14]; @@ -1357,19 +1327,19 @@ public IDisposable Run() _observer13 = new ZipObserver(_gate, this, 12, d13); base.Queues[12] = _observer13.Values; - d1.Disposable = _parent._source1.SubscribeSafe(_observer1); - d2.Disposable = _parent._source2.SubscribeSafe(_observer2); - d3.Disposable = _parent._source3.SubscribeSafe(_observer3); - d4.Disposable = _parent._source4.SubscribeSafe(_observer4); - d5.Disposable = _parent._source5.SubscribeSafe(_observer5); - d6.Disposable = _parent._source6.SubscribeSafe(_observer6); - d7.Disposable = _parent._source7.SubscribeSafe(_observer7); - d8.Disposable = _parent._source8.SubscribeSafe(_observer8); - d9.Disposable = _parent._source9.SubscribeSafe(_observer9); - d10.Disposable = _parent._source10.SubscribeSafe(_observer10); - d11.Disposable = _parent._source11.SubscribeSafe(_observer11); - d12.Disposable = _parent._source12.SubscribeSafe(_observer12); - d13.Disposable = _parent._source13.SubscribeSafe(_observer13); + d1.Disposable = source1.SubscribeSafe(_observer1); + d2.Disposable = source2.SubscribeSafe(_observer2); + d3.Disposable = source3.SubscribeSafe(_observer3); + d4.Disposable = source4.SubscribeSafe(_observer4); + d5.Disposable = source5.SubscribeSafe(_observer5); + d6.Disposable = source6.SubscribeSafe(_observer6); + d7.Disposable = source7.SubscribeSafe(_observer7); + d8.Disposable = source8.SubscribeSafe(_observer8); + d9.Disposable = source9.SubscribeSafe(_observer9); + d10.Disposable = source10.SubscribeSafe(_observer10); + d11.Disposable = source11.SubscribeSafe(_observer11); + d12.Disposable = source12.SubscribeSafe(_observer12); + d13.Disposable = source13.SubscribeSafe(_observer13); disposables[13] = Disposable.Create(() => { @@ -1391,10 +1361,7 @@ public IDisposable Run() return StableCompositeDisposable.Create(disposables); } - protected override TResult GetResult() - { - return _parent._resultSelector(_observer1.Values.Dequeue(), _observer2.Values.Dequeue(), _observer3.Values.Dequeue(), _observer4.Values.Dequeue(), _observer5.Values.Dequeue(), _observer6.Values.Dequeue(), _observer7.Values.Dequeue(), _observer8.Values.Dequeue(), _observer9.Values.Dequeue(), _observer10.Values.Dequeue(), _observer11.Values.Dequeue(), _observer12.Values.Dequeue(), _observer13.Values.Dequeue()); - } + protected override TResult GetResult() => _resultSelector(_observer1.Values.Dequeue(), _observer2.Values.Dequeue(), _observer3.Values.Dequeue(), _observer4.Values.Dequeue(), _observer5.Values.Dequeue(), _observer6.Values.Dequeue(), _observer7.Values.Dequeue(), _observer8.Values.Dequeue(), _observer9.Values.Dequeue(), _observer10.Values.Dequeue(), _observer11.Values.Dequeue(), _observer12.Values.Dequeue(), _observer13.Values.Dequeue()); } } @@ -1437,19 +1404,19 @@ public Zip(IObservable source1, IObservable source2, IObservable sou protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - var sink = new _(this, observer, cancel); + var sink = new _(_resultSelector, observer, cancel); setSink(sink); - return sink.Run(); + return sink.Run(_source1, _source2, _source3, _source4, _source5, _source6, _source7, _source8, _source9, _source10, _source11, _source12, _source13, _source14); } - class _ : ZipSink + private sealed class _ : ZipSink { - private readonly Zip _parent; + private readonly Func _resultSelector; - public _(Zip parent, IObserver observer, IDisposable cancel) + public _(Func resultSelector, IObserver observer, IDisposable cancel) : base(14, observer, cancel) { - _parent = parent; + _resultSelector = resultSelector; } private ZipObserver _observer1; @@ -1467,7 +1434,7 @@ public _(Zip _observer13; private ZipObserver _observer14; - public IDisposable Run() + public IDisposable Run(IObservable source1, IObservable source2, IObservable source3, IObservable source4, IObservable source5, IObservable source6, IObservable source7, IObservable source8, IObservable source9, IObservable source10, IObservable source11, IObservable source12, IObservable source13, IObservable source14) { var disposables = new IDisposable[15]; @@ -1541,20 +1508,20 @@ public IDisposable Run() _observer14 = new ZipObserver(_gate, this, 13, d14); base.Queues[13] = _observer14.Values; - d1.Disposable = _parent._source1.SubscribeSafe(_observer1); - d2.Disposable = _parent._source2.SubscribeSafe(_observer2); - d3.Disposable = _parent._source3.SubscribeSafe(_observer3); - d4.Disposable = _parent._source4.SubscribeSafe(_observer4); - d5.Disposable = _parent._source5.SubscribeSafe(_observer5); - d6.Disposable = _parent._source6.SubscribeSafe(_observer6); - d7.Disposable = _parent._source7.SubscribeSafe(_observer7); - d8.Disposable = _parent._source8.SubscribeSafe(_observer8); - d9.Disposable = _parent._source9.SubscribeSafe(_observer9); - d10.Disposable = _parent._source10.SubscribeSafe(_observer10); - d11.Disposable = _parent._source11.SubscribeSafe(_observer11); - d12.Disposable = _parent._source12.SubscribeSafe(_observer12); - d13.Disposable = _parent._source13.SubscribeSafe(_observer13); - d14.Disposable = _parent._source14.SubscribeSafe(_observer14); + d1.Disposable = source1.SubscribeSafe(_observer1); + d2.Disposable = source2.SubscribeSafe(_observer2); + d3.Disposable = source3.SubscribeSafe(_observer3); + d4.Disposable = source4.SubscribeSafe(_observer4); + d5.Disposable = source5.SubscribeSafe(_observer5); + d6.Disposable = source6.SubscribeSafe(_observer6); + d7.Disposable = source7.SubscribeSafe(_observer7); + d8.Disposable = source8.SubscribeSafe(_observer8); + d9.Disposable = source9.SubscribeSafe(_observer9); + d10.Disposable = source10.SubscribeSafe(_observer10); + d11.Disposable = source11.SubscribeSafe(_observer11); + d12.Disposable = source12.SubscribeSafe(_observer12); + d13.Disposable = source13.SubscribeSafe(_observer13); + d14.Disposable = source14.SubscribeSafe(_observer14); disposables[14] = Disposable.Create(() => { @@ -1577,10 +1544,7 @@ public IDisposable Run() return StableCompositeDisposable.Create(disposables); } - protected override TResult GetResult() - { - return _parent._resultSelector(_observer1.Values.Dequeue(), _observer2.Values.Dequeue(), _observer3.Values.Dequeue(), _observer4.Values.Dequeue(), _observer5.Values.Dequeue(), _observer6.Values.Dequeue(), _observer7.Values.Dequeue(), _observer8.Values.Dequeue(), _observer9.Values.Dequeue(), _observer10.Values.Dequeue(), _observer11.Values.Dequeue(), _observer12.Values.Dequeue(), _observer13.Values.Dequeue(), _observer14.Values.Dequeue()); - } + protected override TResult GetResult() => _resultSelector(_observer1.Values.Dequeue(), _observer2.Values.Dequeue(), _observer3.Values.Dequeue(), _observer4.Values.Dequeue(), _observer5.Values.Dequeue(), _observer6.Values.Dequeue(), _observer7.Values.Dequeue(), _observer8.Values.Dequeue(), _observer9.Values.Dequeue(), _observer10.Values.Dequeue(), _observer11.Values.Dequeue(), _observer12.Values.Dequeue(), _observer13.Values.Dequeue(), _observer14.Values.Dequeue()); } } @@ -1625,19 +1589,19 @@ public Zip(IObservable source1, IObservable source2, IObservable sou protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - var sink = new _(this, observer, cancel); + var sink = new _(_resultSelector, observer, cancel); setSink(sink); - return sink.Run(); + return sink.Run(_source1, _source2, _source3, _source4, _source5, _source6, _source7, _source8, _source9, _source10, _source11, _source12, _source13, _source14, _source15); } - class _ : ZipSink + private sealed class _ : ZipSink { - private readonly Zip _parent; + private readonly Func _resultSelector; - public _(Zip parent, IObserver observer, IDisposable cancel) + public _(Func resultSelector, IObserver observer, IDisposable cancel) : base(15, observer, cancel) { - _parent = parent; + _resultSelector = resultSelector; } private ZipObserver _observer1; @@ -1656,7 +1620,7 @@ public _(Zip _observer14; private ZipObserver _observer15; - public IDisposable Run() + public IDisposable Run(IObservable source1, IObservable source2, IObservable source3, IObservable source4, IObservable source5, IObservable source6, IObservable source7, IObservable source8, IObservable source9, IObservable source10, IObservable source11, IObservable source12, IObservable source13, IObservable source14, IObservable source15) { var disposables = new IDisposable[16]; @@ -1735,21 +1699,21 @@ public IDisposable Run() _observer15 = new ZipObserver(_gate, this, 14, d15); base.Queues[14] = _observer15.Values; - d1.Disposable = _parent._source1.SubscribeSafe(_observer1); - d2.Disposable = _parent._source2.SubscribeSafe(_observer2); - d3.Disposable = _parent._source3.SubscribeSafe(_observer3); - d4.Disposable = _parent._source4.SubscribeSafe(_observer4); - d5.Disposable = _parent._source5.SubscribeSafe(_observer5); - d6.Disposable = _parent._source6.SubscribeSafe(_observer6); - d7.Disposable = _parent._source7.SubscribeSafe(_observer7); - d8.Disposable = _parent._source8.SubscribeSafe(_observer8); - d9.Disposable = _parent._source9.SubscribeSafe(_observer9); - d10.Disposable = _parent._source10.SubscribeSafe(_observer10); - d11.Disposable = _parent._source11.SubscribeSafe(_observer11); - d12.Disposable = _parent._source12.SubscribeSafe(_observer12); - d13.Disposable = _parent._source13.SubscribeSafe(_observer13); - d14.Disposable = _parent._source14.SubscribeSafe(_observer14); - d15.Disposable = _parent._source15.SubscribeSafe(_observer15); + d1.Disposable = source1.SubscribeSafe(_observer1); + d2.Disposable = source2.SubscribeSafe(_observer2); + d3.Disposable = source3.SubscribeSafe(_observer3); + d4.Disposable = source4.SubscribeSafe(_observer4); + d5.Disposable = source5.SubscribeSafe(_observer5); + d6.Disposable = source6.SubscribeSafe(_observer6); + d7.Disposable = source7.SubscribeSafe(_observer7); + d8.Disposable = source8.SubscribeSafe(_observer8); + d9.Disposable = source9.SubscribeSafe(_observer9); + d10.Disposable = source10.SubscribeSafe(_observer10); + d11.Disposable = source11.SubscribeSafe(_observer11); + d12.Disposable = source12.SubscribeSafe(_observer12); + d13.Disposable = source13.SubscribeSafe(_observer13); + d14.Disposable = source14.SubscribeSafe(_observer14); + d15.Disposable = source15.SubscribeSafe(_observer15); disposables[15] = Disposable.Create(() => { @@ -1773,10 +1737,7 @@ public IDisposable Run() return StableCompositeDisposable.Create(disposables); } - protected override TResult GetResult() - { - return _parent._resultSelector(_observer1.Values.Dequeue(), _observer2.Values.Dequeue(), _observer3.Values.Dequeue(), _observer4.Values.Dequeue(), _observer5.Values.Dequeue(), _observer6.Values.Dequeue(), _observer7.Values.Dequeue(), _observer8.Values.Dequeue(), _observer9.Values.Dequeue(), _observer10.Values.Dequeue(), _observer11.Values.Dequeue(), _observer12.Values.Dequeue(), _observer13.Values.Dequeue(), _observer14.Values.Dequeue(), _observer15.Values.Dequeue()); - } + protected override TResult GetResult() => _resultSelector(_observer1.Values.Dequeue(), _observer2.Values.Dequeue(), _observer3.Values.Dequeue(), _observer4.Values.Dequeue(), _observer5.Values.Dequeue(), _observer6.Values.Dequeue(), _observer7.Values.Dequeue(), _observer8.Values.Dequeue(), _observer9.Values.Dequeue(), _observer10.Values.Dequeue(), _observer11.Values.Dequeue(), _observer12.Values.Dequeue(), _observer13.Values.Dequeue(), _observer14.Values.Dequeue(), _observer15.Values.Dequeue()); } } @@ -1823,19 +1784,19 @@ public Zip(IObservable source1, IObservable source2, IObservable sou protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - var sink = new _(this, observer, cancel); + var sink = new _(_resultSelector, observer, cancel); setSink(sink); - return sink.Run(); + return sink.Run(_source1, _source2, _source3, _source4, _source5, _source6, _source7, _source8, _source9, _source10, _source11, _source12, _source13, _source14, _source15, _source16); } - class _ : ZipSink + private sealed class _ : ZipSink { - private readonly Zip _parent; + private readonly Func _resultSelector; - public _(Zip parent, IObserver observer, IDisposable cancel) + public _(Func resultSelector, IObserver observer, IDisposable cancel) : base(16, observer, cancel) { - _parent = parent; + _resultSelector = resultSelector; } private ZipObserver _observer1; @@ -1855,7 +1816,7 @@ public _(Zip _observer15; private ZipObserver _observer16; - public IDisposable Run() + public IDisposable Run(IObservable source1, IObservable source2, IObservable source3, IObservable source4, IObservable source5, IObservable source6, IObservable source7, IObservable source8, IObservable source9, IObservable source10, IObservable source11, IObservable source12, IObservable source13, IObservable source14, IObservable source15, IObservable source16) { var disposables = new IDisposable[17]; @@ -1939,22 +1900,22 @@ public IDisposable Run() _observer16 = new ZipObserver(_gate, this, 15, d16); base.Queues[15] = _observer16.Values; - d1.Disposable = _parent._source1.SubscribeSafe(_observer1); - d2.Disposable = _parent._source2.SubscribeSafe(_observer2); - d3.Disposable = _parent._source3.SubscribeSafe(_observer3); - d4.Disposable = _parent._source4.SubscribeSafe(_observer4); - d5.Disposable = _parent._source5.SubscribeSafe(_observer5); - d6.Disposable = _parent._source6.SubscribeSafe(_observer6); - d7.Disposable = _parent._source7.SubscribeSafe(_observer7); - d8.Disposable = _parent._source8.SubscribeSafe(_observer8); - d9.Disposable = _parent._source9.SubscribeSafe(_observer9); - d10.Disposable = _parent._source10.SubscribeSafe(_observer10); - d11.Disposable = _parent._source11.SubscribeSafe(_observer11); - d12.Disposable = _parent._source12.SubscribeSafe(_observer12); - d13.Disposable = _parent._source13.SubscribeSafe(_observer13); - d14.Disposable = _parent._source14.SubscribeSafe(_observer14); - d15.Disposable = _parent._source15.SubscribeSafe(_observer15); - d16.Disposable = _parent._source16.SubscribeSafe(_observer16); + d1.Disposable = source1.SubscribeSafe(_observer1); + d2.Disposable = source2.SubscribeSafe(_observer2); + d3.Disposable = source3.SubscribeSafe(_observer3); + d4.Disposable = source4.SubscribeSafe(_observer4); + d5.Disposable = source5.SubscribeSafe(_observer5); + d6.Disposable = source6.SubscribeSafe(_observer6); + d7.Disposable = source7.SubscribeSafe(_observer7); + d8.Disposable = source8.SubscribeSafe(_observer8); + d9.Disposable = source9.SubscribeSafe(_observer9); + d10.Disposable = source10.SubscribeSafe(_observer10); + d11.Disposable = source11.SubscribeSafe(_observer11); + d12.Disposable = source12.SubscribeSafe(_observer12); + d13.Disposable = source13.SubscribeSafe(_observer13); + d14.Disposable = source14.SubscribeSafe(_observer14); + d15.Disposable = source15.SubscribeSafe(_observer15); + d16.Disposable = source16.SubscribeSafe(_observer16); disposables[16] = Disposable.Create(() => { @@ -1979,10 +1940,7 @@ public IDisposable Run() return StableCompositeDisposable.Create(disposables); } - protected override TResult GetResult() - { - return _parent._resultSelector(_observer1.Values.Dequeue(), _observer2.Values.Dequeue(), _observer3.Values.Dequeue(), _observer4.Values.Dequeue(), _observer5.Values.Dequeue(), _observer6.Values.Dequeue(), _observer7.Values.Dequeue(), _observer8.Values.Dequeue(), _observer9.Values.Dequeue(), _observer10.Values.Dequeue(), _observer11.Values.Dequeue(), _observer12.Values.Dequeue(), _observer13.Values.Dequeue(), _observer14.Values.Dequeue(), _observer15.Values.Dequeue(), _observer16.Values.Dequeue()); - } + protected override TResult GetResult() => _resultSelector(_observer1.Values.Dequeue(), _observer2.Values.Dequeue(), _observer3.Values.Dequeue(), _observer4.Values.Dequeue(), _observer5.Values.Dequeue(), _observer6.Values.Dequeue(), _observer7.Values.Dequeue(), _observer8.Values.Dequeue(), _observer9.Values.Dequeue(), _observer10.Values.Dequeue(), _observer11.Values.Dequeue(), _observer12.Values.Dequeue(), _observer13.Values.Dequeue(), _observer14.Values.Dequeue(), _observer15.Values.Dequeue(), _observer16.Values.Dequeue()); } } diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Zip.Generated.tt b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Zip.Generated.tt index c8dea7ac1d..20b396325d 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Zip.Generated.tt +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Zip.Generated.tt @@ -24,6 +24,7 @@ for (var i = 3; i <= 16; i++) var ts = string.Join(", ", Enumerable.Range(1, i).Select(j => "T" + j)); var os = string.Join(", ", Enumerable.Range(1, i).Select(j => "IObservable source" + j)); var vs = string.Join(", ", Enumerable.Range(1, i).Select(j => "_observer" + j + ".Values.Dequeue()")); + var ss = string.Join(", ", Enumerable.Range(1, i).Select(j => "_source" + j)); #> internal sealed class Zip<<#=ts#>, TResult> : Producer { @@ -52,19 +53,19 @@ for (var j = 1; j <= i; j++) protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - var sink = new _(this, observer, cancel); + var sink = new _(_resultSelector, observer, cancel); setSink(sink); - return sink.Run(); + return sink.Run(<#=ss#>); } - class _ : ZipSink + private sealed class _ : ZipSink { - private readonly Zip<<#=ts#>, TResult> _parent; + private readonly Func<<#=ts#>, TResult> _resultSelector; - public _(Zip<<#=ts#>, TResult> parent, IObserver observer, IDisposable cancel) + public _(Func<<#=ts#>, TResult> resultSelector, IObserver observer, IDisposable cancel) : base(<#=i#>, observer, cancel) { - _parent = parent; + _resultSelector = resultSelector; } <# @@ -76,7 +77,7 @@ for (var j = 1; j <= i; j++) } #> - public IDisposable Run() + public IDisposable Run(<#=os#>) { var disposables = new IDisposable[<#=i + 1#>]; @@ -95,7 +96,7 @@ for (var j = 1; j <= i; j++) for (var j = 1; j <= i; j++) { #> - d<#=j#>.Disposable = _parent._source<#=j#>.SubscribeSafe(_observer<#=j#>); + d<#=j#>.Disposable = source<#=j#>.SubscribeSafe(_observer<#=j#>); <# } #> @@ -115,10 +116,7 @@ for (var j = 1; j <= i; j++) return StableCompositeDisposable.Create(disposables); } - protected override TResult GetResult() - { - return _parent._resultSelector(<#=vs#>); - } + protected override TResult GetResult() => _resultSelector(<#=vs#>); } } diff --git a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Zip.cs b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Zip.cs index 6996d35f23..b2452426b8 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/Observable/Zip.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/Observable/Zip.cs @@ -11,310 +11,302 @@ namespace System.Reactive.Linq.ObservableImpl { #region Binary - internal sealed class Zip : Producer + internal static class Zip { - private readonly IObservable _first; - private readonly IObservable _second; - private readonly IEnumerable _secondE; - private readonly Func _resultSelector; - - public Zip(IObservable first, IObservable second, Func resultSelector) - { - _first = first; - _second = second; - _resultSelector = resultSelector; - } - - public Zip(IObservable first, IEnumerable second, Func resultSelector) + internal sealed class Observable : Producer { - _first = first; - _secondE = second; - _resultSelector = resultSelector; - } + private readonly IObservable _first; + private readonly IObservable _second; + private readonly Func _resultSelector; - protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) - { - if (_second != null) + public Observable(IObservable first, IObservable second, Func resultSelector) { - var sink = new _(this, observer, cancel); - setSink(sink); - return sink.Run(); + _first = first; + _second = second; + _resultSelector = resultSelector; } - else + + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - var sink = new ZipImpl(this, observer, cancel); + var sink = new _(_resultSelector, observer, cancel); setSink(sink); - return sink.Run(); + return sink.Run(_first, _second); } - } - - class _ : Sink - { - private readonly Zip _parent; - public _(Zip parent, IObserver observer, IDisposable cancel) - : base(observer, cancel) + private sealed class _ : Sink { - _parent = parent; - } + private readonly Func _resultSelector; - private object _gate; + public _(Func resultSelector, IObserver observer, IDisposable cancel) + : base(observer, cancel) + { + _resultSelector = resultSelector; + } - public IDisposable Run() - { - _gate = new object(); + private object _gate; - var fstSubscription = new SingleAssignmentDisposable(); - var sndSubscription = new SingleAssignmentDisposable(); + public IDisposable Run(IObservable first, IObservable second) + { + _gate = new object(); - var fstO = new F(this, fstSubscription); - var sndO = new S(this, sndSubscription); + var fstSubscription = new SingleAssignmentDisposable(); + var sndSubscription = new SingleAssignmentDisposable(); - fstO.Other = sndO; - sndO.Other = fstO; + var fstO = new FirstObserver(this, fstSubscription); + var sndO = new SecondObserver(this, sndSubscription); - fstSubscription.Disposable = _parent._first.SubscribeSafe(fstO); - sndSubscription.Disposable = _parent._second.SubscribeSafe(sndO); + fstO.Other = sndO; + sndO.Other = fstO; - return StableCompositeDisposable.Create(fstSubscription, sndSubscription, fstO, sndO); - } + fstSubscription.Disposable = first.SubscribeSafe(fstO); + sndSubscription.Disposable = second.SubscribeSafe(sndO); - class F : IObserver, IDisposable - { - private readonly _ _parent; - private readonly IDisposable _self; - private S _other; - private Queue _queue; + return StableCompositeDisposable.Create(fstSubscription, sndSubscription, fstO, sndO); + } - public F(_ parent, IDisposable self) + private sealed class FirstObserver : IObserver, IDisposable { - _parent = parent; - _self = self; - _queue = new Queue(); - } + private readonly _ _parent; + private readonly IDisposable _self; + private SecondObserver _other; + private Queue _queue; - public S Other { set { _other = value; } } + public FirstObserver(_ parent, IDisposable self) + { + _parent = parent; + _self = self; + _queue = new Queue(); + } - public Queue Queue { get { return _queue; } } - public bool Done { get; private set; } + public SecondObserver Other { set { _other = value; } } - public void OnNext(TFirst value) - { - lock (_parent._gate) + public Queue Queue => _queue; + public bool Done { get; private set; } + + public void OnNext(TFirst value) { - if (_other.Queue.Count > 0) + lock (_parent._gate) { - var r = _other.Queue.Dequeue(); - - var res = default(TResult); - try + if (_other.Queue.Count > 0) { - res = _parent._parent._resultSelector(value, r); + var r = _other.Queue.Dequeue(); + + var res = default(TResult); + try + { + res = _parent._resultSelector(value, r); + } + catch (Exception ex) + { + _parent._observer.OnError(ex); + _parent.Dispose(); + return; + } + + _parent._observer.OnNext(res); } - catch (Exception ex) + else { - _parent._observer.OnError(ex); - _parent.Dispose(); - return; + if (_other.Done) + { + _parent._observer.OnCompleted(); + _parent.Dispose(); + return; + } + + _queue.Enqueue(value); } + } + } - _parent._observer.OnNext(res); + public void OnError(Exception error) + { + lock (_parent._gate) + { + _parent._observer.OnError(error); + _parent.Dispose(); } - else + } + + public void OnCompleted() + { + lock (_parent._gate) { + Done = true; + if (_other.Done) { _parent._observer.OnCompleted(); _parent.Dispose(); return; } - - _queue.Enqueue(value); + else + { + _self.Dispose(); + } } } - } - public void OnError(Exception error) - { - lock (_parent._gate) + public void Dispose() { - _parent._observer.OnError(error); - _parent.Dispose(); + _queue.Clear(); } } - public void OnCompleted() + private sealed class SecondObserver : IObserver, IDisposable { - lock (_parent._gate) - { - Done = true; + private readonly _ _parent; + private readonly IDisposable _self; + private FirstObserver _other; + private Queue _queue; - if (_other.Done) - { - _parent._observer.OnCompleted(); - _parent.Dispose(); - return; - } - else - { - _self.Dispose(); - } + public SecondObserver(_ parent, IDisposable self) + { + _parent = parent; + _self = self; + _queue = new Queue(); } - } - public void Dispose() - { - _queue.Clear(); - } - } + public FirstObserver Other { set { _other = value; } } - class S : IObserver, IDisposable - { - private readonly _ _parent; - private readonly IDisposable _self; - private F _other; - private Queue _queue; + public Queue Queue => _queue; + public bool Done { get; private set; } - public S(_ parent, IDisposable self) - { - _parent = parent; - _self = self; - _queue = new Queue(); - } - - public F Other { set { _other = value; } } - - public Queue Queue { get { return _queue; } } - public bool Done { get; private set; } - - public void OnNext(TSecond value) - { - lock (_parent._gate) + public void OnNext(TSecond value) { - if (_other.Queue.Count > 0) + lock (_parent._gate) { - var l = _other.Queue.Dequeue(); - - var res = default(TResult); - try + if (_other.Queue.Count > 0) { - res = _parent._parent._resultSelector(l, value); + var l = _other.Queue.Dequeue(); + + var res = default(TResult); + try + { + res = _parent._resultSelector(l, value); + } + catch (Exception ex) + { + _parent._observer.OnError(ex); + _parent.Dispose(); + return; + } + + _parent._observer.OnNext(res); } - catch (Exception ex) + else { - _parent._observer.OnError(ex); - _parent.Dispose(); - return; + if (_other.Done) + { + _parent._observer.OnCompleted(); + _parent.Dispose(); + return; + } + + _queue.Enqueue(value); } + } + } - _parent._observer.OnNext(res); + public void OnError(Exception error) + { + lock (_parent._gate) + { + _parent._observer.OnError(error); + _parent.Dispose(); } - else + } + + public void OnCompleted() + { + lock (_parent._gate) { + Done = true; + if (_other.Done) { _parent._observer.OnCompleted(); _parent.Dispose(); return; } - - _queue.Enqueue(value); + else + { + _self.Dispose(); + } } } - } - public void OnError(Exception error) - { - lock (_parent._gate) + public void Dispose() { - _parent._observer.OnError(error); - _parent.Dispose(); + _queue.Clear(); } } - - public void OnCompleted() - { - lock (_parent._gate) - { - Done = true; - - if (_other.Done) - { - _parent._observer.OnCompleted(); - _parent.Dispose(); - return; - } - else - { - _self.Dispose(); - } - } - } - - public void Dispose() - { - _queue.Clear(); - } } } - class ZipImpl : Sink, IObserver + internal sealed class Enumerable : Producer { - private readonly Zip _parent; + private readonly IObservable _first; + private readonly IEnumerable _second; + private readonly Func _resultSelector; - public ZipImpl(Zip parent, IObserver observer, IDisposable cancel) - : base(observer, cancel) + public Enumerable(IObservable first, IEnumerable second, Func resultSelector) { - _parent = parent; + _first = first; + _second = second; + _resultSelector = resultSelector; } - private IEnumerator _rightEnumerator; - - public IDisposable Run() + protected override IDisposable Run(IObserver observer, IDisposable cancel, Action setSink) { - // - // Notice the evaluation order of obtaining the enumerator and subscribing to the - // observable sequence is reversed compared to the operator's signature. This is - // required to make sure the enumerator is available as soon as the observer can - // be called. Otherwise, we end up having a race for the initialization and use - // of the _rightEnumerator field. - // - try - { - _rightEnumerator = _parent._secondE.GetEnumerator(); - } - catch (Exception exception) - { - base._observer.OnError(exception); - base.Dispose(); - return Disposable.Empty; - } - - var leftSubscription = _parent._first.SubscribeSafe(this); - - return StableCompositeDisposable.Create(leftSubscription, _rightEnumerator); + var sink = new _(_resultSelector, observer, cancel); + setSink(sink); + return sink.Run(_first, _second); } - public void OnNext(TFirst value) + private sealed class _ : Sink, IObserver { - var hasNext = false; - try + private readonly Func _resultSelector; + + public _(Func resultSelector, IObserver observer, IDisposable cancel) + : base(observer, cancel) { - hasNext = _rightEnumerator.MoveNext(); + _resultSelector = resultSelector; } - catch (Exception ex) + + private IEnumerator _rightEnumerator; + + public IDisposable Run(IObservable first, IEnumerable second) { - base._observer.OnError(ex); - base.Dispose(); - return; + // + // Notice the evaluation order of obtaining the enumerator and subscribing to the + // observable sequence is reversed compared to the operator's signature. This is + // required to make sure the enumerator is available as soon as the observer can + // be called. Otherwise, we end up having a race for the initialization and use + // of the _rightEnumerator field. + // + try + { + _rightEnumerator = second.GetEnumerator(); + } + catch (Exception exception) + { + base._observer.OnError(exception); + base.Dispose(); + return Disposable.Empty; + } + + var leftSubscription = first.SubscribeSafe(this); + + return StableCompositeDisposable.Create(leftSubscription, _rightEnumerator); } - if (hasNext) + public void OnNext(TFirst value) { - var right = default(TSecond); + var hasNext = false; try { - right = _rightEnumerator.Current; + hasNext = _rightEnumerator.MoveNext(); } catch (Exception ex) { @@ -323,38 +315,53 @@ public void OnNext(TFirst value) return; } - TResult result; - try + if (hasNext) { - result = _parent._resultSelector(value, right); + var right = default(TSecond); + try + { + right = _rightEnumerator.Current; + } + catch (Exception ex) + { + base._observer.OnError(ex); + base.Dispose(); + return; + } + + TResult result; + try + { + result = _resultSelector(value, right); + } + catch (Exception ex) + { + base._observer.OnError(ex); + base.Dispose(); + return; + } + + base._observer.OnNext(result); } - catch (Exception ex) + else { - base._observer.OnError(ex); + base._observer.OnCompleted(); base.Dispose(); - return; } + } - base._observer.OnNext(result); + public void OnError(Exception error) + { + base._observer.OnError(error); + base.Dispose(); } - else + + public void OnCompleted() { base._observer.OnCompleted(); base.Dispose(); } } - - public void OnError(Exception error) - { - base._observer.OnError(error); - base.Dispose(); - } - - public void OnCompleted() - { - base._observer.OnCompleted(); - base.Dispose(); - } } } @@ -364,14 +371,14 @@ public void OnCompleted() #region Helpers for n-ary overloads - interface IZip + internal interface IZip { void Next(int index); void Fail(Exception error); void Done(int index); } - abstract class ZipSink : Sink, IZip + internal abstract class ZipSink : Sink, IZip { protected readonly object _gate; @@ -387,10 +394,7 @@ public ZipSink(int arity, IObserver observer, IDisposable cancel) _queues = new ICollection[arity]; } - public ICollection[] Queues - { - get { return _queues; } - } + public ICollection[] Queues => _queues; public void Next(int index) { @@ -488,10 +492,7 @@ public ZipObserver(object gate, IZip parent, int index, IDisposable self) _values = new Queue(); } - public Queue Values - { - get { return _values; } - } + public Queue Values => _values; public void OnNext(T value) { @@ -545,7 +546,7 @@ protected override IDisposable Run(IObserver> observer, IDisposab return sink.Run(); } - class _ : Sink> + private sealed class _ : Sink> { private readonly Zip _parent; @@ -583,7 +584,7 @@ public IDisposable Run() var d = new SingleAssignmentDisposable(); _subscriptions[j] = d; - var o = new O(this, j); + var o = new SourceObserver(this, j); d.Disposable = srcs[j].SubscribeSafe(o); } @@ -598,10 +599,17 @@ private void OnNext(int index, TSource value) if (_queues.All(q => q.Count > 0)) { - var res = _queues.Select(q => q.Dequeue()).ToList(); + var n = _queues.Length; + + var res = new List(n); + for (var i = 0; i < n; i++) + { + res.Add(_queues[i].Dequeue()); + } + base._observer.OnNext(res); } - else if (_isDone.Where((x, i) => i != index).All(Stubs.I)) + else if (_isDone.AllExcept(index)) { base._observer.OnCompleted(); base.Dispose(); @@ -625,7 +633,7 @@ private void OnCompleted(int index) { _isDone[index] = true; - if (_isDone.All(Stubs.I)) + if (_isDone.All()) { base._observer.OnCompleted(); base.Dispose(); @@ -638,12 +646,12 @@ private void OnCompleted(int index) } } - class O : IObserver + private sealed class SourceObserver : IObserver { private readonly _ _parent; private readonly int _index; - public O(_ parent, int index) + public SourceObserver(_ parent, int index) { _parent = parent; _index = index; diff --git a/Rx.NET/Source/src/System.Reactive/Linq/QueryLanguage.Aggregates.cs b/Rx.NET/Source/src/System.Reactive/Linq/QueryLanguage.Aggregates.cs index a1b0163d99..14b97c0e10 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/QueryLanguage.Aggregates.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/QueryLanguage.Aggregates.cs @@ -4,7 +4,6 @@ using System.Collections.Generic; using System.Linq; -using System.Reactive.Disposables; namespace System.Reactive.Linq { @@ -16,7 +15,7 @@ internal partial class QueryLanguage public virtual IObservable Aggregate(IObservable source, TAccumulate seed, Func accumulator) { - return new Aggregate(source, seed, accumulator, Stubs.I); + return new Aggregate(source, seed, accumulator); } public virtual IObservable Aggregate(IObservable source, TAccumulate seed, Func accumulator, Func resultSelector) @@ -94,12 +93,12 @@ public virtual IObservable All(IObservable source, Func< public virtual IObservable Any(IObservable source) { - return new Any(source); + return new Any.Count(source); } public virtual IObservable Any(IObservable source, Func predicate) { - return new Any(source, predicate); + return new Any.Predicate(source, predicate); } #endregion @@ -176,12 +175,12 @@ public virtual IObservable Contains(IObservable source, public virtual IObservable Count(IObservable source) { - return new Count(source); + return new Count.All(source); } public virtual IObservable Count(IObservable source, Func predicate) { - return new Count(source, predicate); + return new Count.Predicate(source, predicate); } #endregion @@ -190,7 +189,7 @@ public virtual IObservable Count(IObservable source, Func public virtual IObservable ElementAt(IObservable source, int index) { - return new ElementAt(source, index, true); + return new ElementAt(source, index); } #endregion @@ -199,7 +198,7 @@ public virtual IObservable ElementAt(IObservable sour public virtual IObservable ElementAtOrDefault(IObservable source, int index) { - return new ElementAt(source, index, false); + return new ElementAtOrDefault(source, index); } #endregion @@ -208,12 +207,12 @@ public virtual IObservable ElementAtOrDefault(IObservable FirstAsync(IObservable source) { - return new FirstAsync(source, null, true); + return new FirstAsync.Sequence(source); } public virtual IObservable FirstAsync(IObservable source, Func predicate) { - return new FirstAsync(source, predicate, true); + return new FirstAsync.Predicate(source, predicate); } #endregion @@ -222,12 +221,12 @@ public virtual IObservable FirstAsync(IObservable sou public virtual IObservable FirstOrDefaultAsync(IObservable source) { - return new FirstAsync(source, null, false); + return new FirstOrDefaultAsync.Sequence(source); } public virtual IObservable FirstOrDefaultAsync(IObservable source, Func predicate) { - return new FirstAsync(source, predicate, false); + return new FirstOrDefaultAsync.Predicate(source, predicate); } #endregion @@ -245,12 +244,12 @@ public virtual IObservable IsEmpty(IObservable source) public virtual IObservable LastAsync(IObservable source) { - return new LastAsync(source, null, true); + return new LastAsync.Sequence(source); } public virtual IObservable LastAsync(IObservable source, Func predicate) { - return new LastAsync(source, predicate, true); + return new LastAsync.Predicate(source, predicate); } #endregion @@ -259,12 +258,12 @@ public virtual IObservable LastAsync(IObservable sour public virtual IObservable LastOrDefaultAsync(IObservable source) { - return new LastAsync(source, null, false); + return new LastOrDefaultAsync.Sequence(source); } public virtual IObservable LastOrDefaultAsync(IObservable source, Func predicate) { - return new LastAsync(source, predicate, false); + return new LastOrDefaultAsync.Predicate(source, predicate); } #endregion @@ -273,12 +272,12 @@ public virtual IObservable LastOrDefaultAsync(IObservable LongCount(IObservable source) { - return new LongCount(source); + return new LongCount.All(source); } public virtual IObservable LongCount(IObservable source, Func predicate) { - return new LongCount(source, predicate); + return new LongCount.Predicate(source, predicate); } #endregion @@ -567,22 +566,22 @@ public virtual IObservable> MinBy(IObservable SequenceEqual(IObservable first, IObservable second) { - return new SequenceEqual(first, second, EqualityComparer.Default); + return new SequenceEqual.Observable(first, second, EqualityComparer.Default); } public virtual IObservable SequenceEqual(IObservable first, IObservable second, IEqualityComparer comparer) { - return new SequenceEqual(first, second, comparer); + return new SequenceEqual.Observable(first, second, comparer); } public virtual IObservable SequenceEqual(IObservable first, IEnumerable second) { - return new SequenceEqual(first, second, EqualityComparer.Default); + return new SequenceEqual.Enumerable(first, second, EqualityComparer.Default); } public virtual IObservable SequenceEqual(IObservable first, IEnumerable second, IEqualityComparer comparer) { - return new SequenceEqual(first, second, comparer); + return new SequenceEqual.Enumerable(first, second, comparer); } #endregion @@ -591,12 +590,12 @@ public virtual IObservable SequenceEqual(IObservable fir public virtual IObservable SingleAsync(IObservable source) { - return new SingleAsync(source, null, true); + return new SingleAsync.Sequence(source); } public virtual IObservable SingleAsync(IObservable source, Func predicate) { - return new SingleAsync(source, predicate, true); + return new SingleAsync.Predicate(source, predicate); } #endregion @@ -605,12 +604,12 @@ public virtual IObservable SingleAsync(IObservable so public virtual IObservable SingleOrDefaultAsync(IObservable source) { - return new SingleAsync(source, null, false); + return new SingleOrDefaultAsync.Sequence(source); } public virtual IObservable SingleOrDefaultAsync(IObservable source, Func predicate) { - return new SingleAsync(source, predicate, false); + return new SingleOrDefaultAsync.Predicate(source, predicate); } #endregion diff --git a/Rx.NET/Source/src/System.Reactive/Linq/QueryLanguage.Awaiter.cs b/Rx.NET/Source/src/System.Reactive/Linq/QueryLanguage.Awaiter.cs index 4d7c7a4a53..beb5716819 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/QueryLanguage.Awaiter.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/QueryLanguage.Awaiter.cs @@ -2,7 +2,6 @@ // The .NET Foundation licenses this file to you under the Apache 2.0 License. // See the LICENSE file in the project root for more information. -using System; using System.Threading; using System.Reactive.Disposables; using System.Reactive.Subjects; diff --git a/Rx.NET/Source/src/System.Reactive/Linq/QueryLanguage.Blocking.cs b/Rx.NET/Source/src/System.Reactive/Linq/QueryLanguage.Blocking.cs index 703b4e27b7..18a771872d 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/QueryLanguage.Blocking.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/QueryLanguage.Blocking.cs @@ -2,10 +2,8 @@ // The .NET Foundation licenses this file to you under the Apache 2.0 License. // See the LICENSE file in the project root for more information. -using System.Collections; using System.Collections.Generic; using System.Threading; -using System.Reactive.Disposables; namespace System.Reactive.Linq { @@ -118,7 +116,7 @@ public virtual void ForEach(IObservable source, Action._(onNext, () => evt.Set()); + var sink = new ForEach.Observer(onNext, () => evt.Set()); using (source.SubscribeSafe(sink)) { @@ -133,7 +131,7 @@ public virtual void ForEach(IObservable source, Action.ForEachImpl(onNext, () => evt.Set()); + var sink = new ForEach.ObserverIndexed(onNext, () => evt.Set()); using (source.SubscribeSafe(sink)) { diff --git a/Rx.NET/Source/src/System.Reactive/Linq/QueryLanguage.Concurrency.cs b/Rx.NET/Source/src/System.Reactive/Linq/QueryLanguage.Concurrency.cs index 8ac7834b90..4e1d5c3c1c 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/QueryLanguage.Concurrency.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/QueryLanguage.Concurrency.cs @@ -3,7 +3,6 @@ // See the LICENSE file in the project root for more information. using System.Reactive.Concurrency; -using System.Reactive.Disposables; using System.Threading; namespace System.Reactive.Linq diff --git a/Rx.NET/Source/src/System.Reactive/Linq/QueryLanguage.Creation.cs b/Rx.NET/Source/src/System.Reactive/Linq/QueryLanguage.Creation.cs index ac21d67f5f..8984100e73 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/QueryLanguage.Creation.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/QueryLanguage.Creation.cs @@ -148,12 +148,12 @@ public virtual IObservable Empty(IScheduler scheduler) public virtual IObservable Generate(TState initialState, Func condition, Func iterate, Func resultSelector) { - return new Generate(initialState, condition, iterate, resultSelector, SchedulerDefaults.Iteration); + return new Generate.NoTime(initialState, condition, iterate, resultSelector, SchedulerDefaults.Iteration); } public virtual IObservable Generate(TState initialState, Func condition, Func iterate, Func resultSelector, IScheduler scheduler) { - return new Generate(initialState, condition, iterate, resultSelector, scheduler); + return new Generate.NoTime(initialState, condition, iterate, resultSelector, scheduler); } #endregion @@ -190,22 +190,22 @@ private static IObservable Range_(int start, int count, IScheduler schedule public virtual IObservable Repeat(TResult value) { - return new Repeat(value, null, SchedulerDefaults.Iteration); + return new Repeat.Forever(value, SchedulerDefaults.Iteration); } public virtual IObservable Repeat(TResult value, IScheduler scheduler) { - return new Repeat(value, null, scheduler); + return new Repeat.Forever(value, scheduler); } public virtual IObservable Repeat(TResult value, int repeatCount) { - return new Repeat(value, repeatCount, SchedulerDefaults.Iteration); + return new Repeat.Count(value, repeatCount, SchedulerDefaults.Iteration); } public virtual IObservable Repeat(TResult value, int repeatCount, IScheduler scheduler) { - return new Repeat(value, repeatCount, scheduler); + return new Repeat.Count(value, repeatCount, scheduler); } #endregion diff --git a/Rx.NET/Source/src/System.Reactive/Linq/QueryLanguage.Multiple.cs b/Rx.NET/Source/src/System.Reactive/Linq/QueryLanguage.Multiple.cs index 7b2f7ba7e5..7d42abf259 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/QueryLanguage.Multiple.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/QueryLanguage.Multiple.cs @@ -2,13 +2,9 @@ // The .NET Foundation licenses this file to you under the Apache 2.0 License. // See the LICENSE file in the project root for more information. -using System.Collections; using System.Collections.Generic; -using System.Collections.ObjectModel; using System.Linq; using System.Reactive.Concurrency; -using System.Reactive.Disposables; -using System.Reactive.Subjects; using System.Reactive.Threading.Tasks; using System.Threading.Tasks; @@ -51,7 +47,7 @@ private static IObservable Amb_(IObservable leftSourc public virtual IObservable> Buffer(IObservable source, Func> bufferClosingSelector) { - return new Buffer(source, bufferClosingSelector); + return new Buffer.Selector(source, bufferClosingSelector); } public virtual IObservable> Buffer(IObservable source, IObservable bufferOpenings, Func> bufferClosingSelector) @@ -61,7 +57,7 @@ public virtual IObservable> Buffer> Buffer(IObservable source, IObservable bufferBoundaries) { - return new Buffer(source, bufferBoundaries); + return new Buffer.Boundaries(source, bufferBoundaries); } #endregion @@ -248,7 +244,7 @@ public virtual IObservable Merge(IObservable Merge(IObservable> sources) { - return new Merge(sources); + return new Merge.Tasks(sources); } public virtual IObservable Merge(IObservable> sources, int maxConcurrent) @@ -298,12 +294,12 @@ public virtual IObservable Merge(IEnumerable Merge_(IObservable> sources) { - return new Merge(sources); + return new Merge.Observables(sources); } private static IObservable Merge_(IObservable> sources, int maxConcurrent) { - return new Merge(sources, maxConcurrent); + return new Merge.ObservablesMaxConcurrency(sources, maxConcurrent); } #endregion @@ -373,7 +369,7 @@ public virtual IObservable TakeUntil(IObservable> Window(IObservable source, Func> windowClosingSelector) { - return new Window(source, windowClosingSelector); + return new Window.Selector(source, windowClosingSelector); } public virtual IObservable> Window(IObservable source, IObservable windowOpenings, Func> windowClosingSelector) @@ -383,7 +379,7 @@ public virtual IObservable> Window> Window(IObservable source, IObservable windowBoundaries) { - return new Window(source, windowBoundaries); + return new Window.Boundaries(source, windowBoundaries); } #endregion @@ -401,7 +397,7 @@ public virtual IObservable WithLatestFrom(IOb public virtual IObservable Zip(IObservable first, IObservable second, Func resultSelector) { - return new Zip(first, second, resultSelector); + return new Zip.Observable(first, second, resultSelector); } public virtual IObservable Zip(IEnumerable> sources, Func, TResult> resultSelector) @@ -502,7 +498,7 @@ public virtual IObservable Zip Zip(IObservable first, IEnumerable second, Func resultSelector) { - return new Zip(first, second, resultSelector); + return new Zip.Enumerable(first, second, resultSelector); } #endregion diff --git a/Rx.NET/Source/src/System.Reactive/Linq/QueryLanguage.Single.cs b/Rx.NET/Source/src/System.Reactive/Linq/QueryLanguage.Single.cs index 91e0681a4b..3a4292b25a 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/QueryLanguage.Single.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/QueryLanguage.Single.cs @@ -5,8 +5,6 @@ using System.Collections.Generic; using System.Linq; using System.Reactive.Concurrency; -using System.Reactive.Disposables; -using System.Reactive.Subjects; namespace System.Reactive.Linq { @@ -41,7 +39,7 @@ public virtual IObservable> Buffer(IObservable private static IObservable> Buffer_(IObservable source, int count, int skip) { - return new Buffer(source, count, skip); + return new Buffer.Count(source, count, skip); } #endregion @@ -92,7 +90,7 @@ private static IObservable DistinctUntilChanged_(IObserv public virtual IObservable Do(IObservable source, Action onNext) { - return Do_(source, onNext, Stubs.Ignore, Stubs.Nop); + return new Do.OnNext(source, onNext); } public virtual IObservable Do(IObservable source, Action onNext, Action onCompleted) @@ -112,12 +110,12 @@ public virtual IObservable Do(IObservable source, Act public virtual IObservable Do(IObservable source, IObserver observer) { - return Do_(source, observer.OnNext, observer.OnError, observer.OnCompleted); + return new Do.Observer(source, observer); } private static IObservable Do_(IObservable source, Action onNext, Action onError, Action onCompleted) { - return new Do(source, onNext, onError, onCompleted); + return new Do.Actions(source, onNext, onError, onCompleted); } #endregion @@ -211,7 +209,7 @@ public virtual IObservable Scan(IObservable source, F public virtual IObservable SkipLast(IObservable source, int count) { - return new SkipLast(source, count); + return new SkipLast.Count(source, count); } #endregion @@ -272,12 +270,12 @@ public virtual IObservable TakeLast(IObservable sourc private static IObservable TakeLast_(IObservable source, int count, IScheduler scheduler) { - return new TakeLast(source, count, scheduler); + return new TakeLast.Count(source, count, scheduler); } public virtual IObservable> TakeLastBuffer(IObservable source, int count) { - return new TakeLastBuffer(source, count); + return new TakeLastBuffer.Count(source, count); } #endregion @@ -296,7 +294,7 @@ public virtual IObservable> Window(IObservable> Window_(IObservable source, int count, int skip) { - return new Window(source, count, skip); + return new Window.Count(source, count, skip); } #endregion diff --git a/Rx.NET/Source/src/System.Reactive/Linq/QueryLanguage.StandardSequenceOperators.cs b/Rx.NET/Source/src/System.Reactive/Linq/QueryLanguage.StandardSequenceOperators.cs index 6b2f40a78d..74966aea79 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/QueryLanguage.StandardSequenceOperators.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/QueryLanguage.StandardSequenceOperators.cs @@ -199,12 +199,14 @@ public virtual IObservable OfType(IObservable source) public virtual IObservable Select(IObservable source, Func selector) { - return new Select(source, selector); + // CONSIDER: Add fusion for Select/Select pairs. + + return new Select.Selector(source, selector); } public virtual IObservable Select(IObservable source, Func selector) { - return new Select(source, selector); + return new Select.SelectorIndexed(source, selector); } #endregion @@ -228,22 +230,22 @@ public virtual IObservable SelectMany(IObservable SelectMany(IObservable source, Func> selector) { - return new SelectMany(source, (x, token) => selector(x)); + return new SelectMany.TaskSelector(source, (x, token) => selector(x)); } public virtual IObservable SelectMany(IObservable source, Func> selector) { - return new SelectMany(source, (x, i, token) => selector(x, i)); + return new SelectMany.TaskSelectorIndexed(source, (x, i, token) => selector(x, i)); } public virtual IObservable SelectMany(IObservable source, Func> selector) { - return new SelectMany(source, selector); + return new SelectMany.TaskSelector(source, selector); } public virtual IObservable SelectMany(IObservable source, Func> selector) { - return new SelectMany(source, selector); + return new SelectMany.TaskSelectorIndexed(source, selector); } public virtual IObservable SelectMany(IObservable source, Func> collectionSelector, Func resultSelector) @@ -258,62 +260,62 @@ public virtual IObservable SelectMany(IO public virtual IObservable SelectMany(IObservable source, Func> taskSelector, Func resultSelector) { - return new SelectMany(source, (x, token) => taskSelector(x), resultSelector); + return new SelectMany.TaskSelector(source, (x, token) => taskSelector(x), resultSelector); } public virtual IObservable SelectMany(IObservable source, Func> taskSelector, Func resultSelector) { - return new SelectMany(source, (x, i, token) => taskSelector(x, i), resultSelector); + return new SelectMany.TaskSelectorIndexed(source, (x, i, token) => taskSelector(x, i), resultSelector); } public virtual IObservable SelectMany(IObservable source, Func> taskSelector, Func resultSelector) { - return new SelectMany(source, taskSelector, resultSelector); + return new SelectMany.TaskSelector(source, taskSelector, resultSelector); } public virtual IObservable SelectMany(IObservable source, Func> taskSelector, Func resultSelector) { - return new SelectMany(source, taskSelector, resultSelector); + return new SelectMany.TaskSelectorIndexed(source, taskSelector, resultSelector); } private static IObservable SelectMany_(IObservable source, Func> selector) { - return new SelectMany(source, selector); + return new SelectMany.ObservableSelector(source, selector); } private static IObservable SelectMany_(IObservable source, Func> selector) { - return new SelectMany(source, selector); + return new SelectMany.ObservableSelectorIndexed(source, selector); } private static IObservable SelectMany_(IObservable source, Func> collectionSelector, Func resultSelector) { - return new SelectMany(source, collectionSelector, resultSelector); + return new SelectMany.ObservableSelector(source, collectionSelector, resultSelector); } private static IObservable SelectMany_(IObservable source, Func> collectionSelector, Func resultSelector) { - return new SelectMany(source, collectionSelector, resultSelector); + return new SelectMany.ObservableSelectorIndexed(source, collectionSelector, resultSelector); } public virtual IObservable SelectMany(IObservable source, Func> onNext, Func> onError, Func> onCompleted) { - return new SelectMany(source, onNext, onError, onCompleted); + return new SelectMany.ObservableSelectors(source, onNext, onError, onCompleted); } public virtual IObservable SelectMany(IObservable source, Func> onNext, Func> onError, Func> onCompleted) { - return new SelectMany(source, onNext, onError, onCompleted); + return new SelectMany.ObservableSelectorsIndexed(source, onNext, onError, onCompleted); } public virtual IObservable SelectMany(IObservable source, Func> selector) { - return new SelectMany(source, selector); + return new SelectMany.EnumerableSelector(source, selector); } public virtual IObservable SelectMany(IObservable source, Func> selector) { - return new SelectMany(source, selector); + return new SelectMany.EnumerableSelectorIndexed(source, selector); } public virtual IObservable SelectMany(IObservable source, Func> collectionSelector, Func resultSelector) @@ -328,12 +330,12 @@ public virtual IObservable SelectMany(IO private static IObservable SelectMany_(IObservable source, Func> collectionSelector, Func resultSelector) { - return new SelectMany(source, collectionSelector, resultSelector); + return new SelectMany.EnumerableSelector(source, collectionSelector, resultSelector); } private static IObservable SelectMany_(IObservable source, Func> collectionSelector, Func resultSelector) { - return new SelectMany(source, collectionSelector, resultSelector); + return new SelectMany.EnumerableSelectorIndexed(source, collectionSelector, resultSelector); } #endregion @@ -342,11 +344,11 @@ private static IObservable SelectMany_(I public virtual IObservable Skip(IObservable source, int count) { - var skip = source as Skip; - if (skip != null && skip._scheduler == null) + var skip = source as Skip.Count; + if (skip != null) return skip.Combine(count); - return new Skip(source, count); + return new Skip.Count(source, count); } #endregion @@ -355,12 +357,12 @@ public virtual IObservable Skip(IObservable source, i public virtual IObservable SkipWhile(IObservable source, Func predicate) { - return new SkipWhile(source, predicate); + return new SkipWhile.Predicate(source, predicate); } public virtual IObservable SkipWhile(IObservable source, Func predicate) { - return new SkipWhile(source, predicate); + return new SkipWhile.PredicateIndexed(source, predicate); } #endregion @@ -385,11 +387,11 @@ public virtual IObservable Take(IObservable source, i private static IObservable Take_(IObservable source, int count) { - var take = source as Take; - if (take != null && take._scheduler == null) + var take = source as Take.Count; + if (take != null) return take.Combine(count); - return new Take(source, count); + return new Take.Count(source, count); } #endregion @@ -398,12 +400,12 @@ private static IObservable Take_(IObservable source, public virtual IObservable TakeWhile(IObservable source, Func predicate) { - return new TakeWhile(source, predicate); + return new TakeWhile.Predicate(source, predicate); } public virtual IObservable TakeWhile(IObservable source, Func predicate) { - return new TakeWhile(source, predicate); + return new TakeWhile.PredicateIndexed(source, predicate); } #endregion @@ -412,16 +414,16 @@ public virtual IObservable TakeWhile(IObservable sour public virtual IObservable Where(IObservable source, Func predicate) { - var where = source as Where; + var where = source as Where.Predicate; if (where != null) return where.Combine(predicate); - return new Where(source, predicate); + return new Where.Predicate(source, predicate); } public virtual IObservable Where(IObservable source, Func predicate) { - return new Where(source, predicate); + return new Where.PredicateIndexed(source, predicate); } #endregion diff --git a/Rx.NET/Source/src/System.Reactive/Linq/QueryLanguage.Time.cs b/Rx.NET/Source/src/System.Reactive/Linq/QueryLanguage.Time.cs index 3c380bd272..d0c674519e 100644 --- a/Rx.NET/Source/src/System.Reactive/Linq/QueryLanguage.Time.cs +++ b/Rx.NET/Source/src/System.Reactive/Linq/QueryLanguage.Time.cs @@ -19,12 +19,17 @@ internal partial class QueryLanguage public virtual IObservable> Buffer(IObservable source, TimeSpan timeSpan) { - return Buffer_(source, timeSpan, timeSpan, SchedulerDefaults.TimeBasedOperations); + return Buffer_(source, timeSpan, SchedulerDefaults.TimeBasedOperations); } public virtual IObservable> Buffer(IObservable source, TimeSpan timeSpan, IScheduler scheduler) { - return Buffer_(source, timeSpan, timeSpan, scheduler); + return Buffer_(source, timeSpan, scheduler); + } + + private static IObservable> Buffer_(IObservable source, TimeSpan timeSpan, IScheduler scheduler) + { + return new Buffer.TimeHopping(source, timeSpan, scheduler); } public virtual IObservable> Buffer(IObservable source, TimeSpan timeSpan, TimeSpan timeShift) @@ -39,7 +44,7 @@ public virtual IObservable> Buffer(IObservable private static IObservable> Buffer_(IObservable source, TimeSpan timeSpan, TimeSpan timeShift, IScheduler scheduler) { - return new Buffer(source, timeSpan, timeShift, scheduler); + return new Buffer.TimeSliding(source, timeSpan, timeShift, scheduler); } #endregion @@ -58,7 +63,7 @@ public virtual IObservable> Buffer(IObservable private static IObservable> Buffer_(IObservable source, TimeSpan timeSpan, int count, IScheduler scheduler) { - return new Buffer(source, timeSpan, count, scheduler); + return new Buffer.Ferry(source, timeSpan, count, scheduler); } #endregion @@ -81,7 +86,7 @@ public virtual IObservable Delay(IObservable source, private static IObservable Delay_(IObservable source, TimeSpan dueTime, IScheduler scheduler) { - return new Delay(source, dueTime, scheduler); + return new Delay.Relative(source, dueTime, scheduler); } #endregion @@ -100,7 +105,7 @@ public virtual IObservable Delay(IObservable source, private static IObservable Delay_(IObservable source, DateTimeOffset dueTime, IScheduler scheduler) { - return new Delay(source, dueTime, scheduler); + return new Delay.Absolute(source, dueTime, scheduler); } #endregion @@ -109,17 +114,12 @@ private static IObservable Delay_(IObservable source, public virtual IObservable Delay(IObservable source, Func> delayDurationSelector) { - return Delay_(source, null, delayDurationSelector); + return new Delay.Selector(source, delayDurationSelector); } public virtual IObservable Delay(IObservable source, IObservable subscriptionDelay, Func> delayDurationSelector) { - return Delay_(source, subscriptionDelay, delayDurationSelector); - } - - private static IObservable Delay_(IObservable source, IObservable subscriptionDelay, Func> delayDurationSelector) - { - return new Delay(source, subscriptionDelay, delayDurationSelector); + return new Delay.SelectorWithSubscriptionDelay(source, subscriptionDelay, delayDurationSelector); } #endregion @@ -140,7 +140,7 @@ public virtual IObservable DelaySubscription(IObservable DelaySubscription_(IObservable source, TimeSpan dueTime, IScheduler scheduler) { - return new DelaySubscription(source, dueTime, scheduler); + return new DelaySubscription.Relative(source, dueTime, scheduler); } public virtual IObservable DelaySubscription(IObservable source, DateTimeOffset dueTime) @@ -155,7 +155,7 @@ public virtual IObservable DelaySubscription(IObservable DelaySubscription_(IObservable source, DateTimeOffset dueTime, IScheduler scheduler) { - return new DelaySubscription(source, dueTime, scheduler); + return new DelaySubscription.Absolute(source, dueTime, scheduler); } #endregion @@ -174,7 +174,7 @@ public virtual IObservable Generate(TState initialStat private static IObservable Generate_(TState initialState, Func condition, Func iterate, Func resultSelector, Func timeSelector, IScheduler scheduler) { - return new Generate(initialState, condition, iterate, resultSelector, timeSelector, scheduler); + return new Generate.Relative(initialState, condition, iterate, resultSelector, timeSelector, scheduler); } public virtual IObservable Generate(TState initialState, Func condition, Func iterate, Func resultSelector, Func timeSelector) @@ -189,7 +189,7 @@ public virtual IObservable Generate(TState initialStat private static IObservable Generate_(TState initialState, Func condition, Func iterate, Func resultSelector, Func timeSelector, IScheduler scheduler) { - return new Generate(initialState, condition, iterate, resultSelector, timeSelector, scheduler); + return new Generate.Absolute(initialState, condition, iterate, resultSelector, timeSelector, scheduler); } #endregion @@ -251,11 +251,11 @@ public virtual IObservable Skip(IObservable source, T private static IObservable Skip_(IObservable source, TimeSpan duration, IScheduler scheduler) { - var skip = source as Skip; + var skip = source as Skip.Time; if (skip != null && skip._scheduler == scheduler) return skip.Combine(duration); - return new Skip(source, duration, scheduler); + return new Skip.Time(source, duration, scheduler); } #endregion @@ -274,7 +274,7 @@ public virtual IObservable SkipLast(IObservable sourc private static IObservable SkipLast_(IObservable source, TimeSpan duration, IScheduler scheduler) { - return new SkipLast(source, duration, scheduler); + return new SkipLast.Time(source, duration, scheduler); } #endregion @@ -316,11 +316,11 @@ public virtual IObservable Take(IObservable source, T private static IObservable Take_(IObservable source, TimeSpan duration, IScheduler scheduler) { - var take = source as Take; + var take = source as Take.Time; if (take != null && take._scheduler == scheduler) return take.Combine(duration); - return new Take(source, duration, scheduler); + return new Take.Time(source, duration, scheduler); } #endregion @@ -344,7 +344,7 @@ public virtual IObservable TakeLast(IObservable sourc private static IObservable TakeLast_(IObservable source, TimeSpan duration, IScheduler timerScheduler, IScheduler loopScheduler) { - return new TakeLast(source, duration, timerScheduler, loopScheduler); + return new TakeLast.Time(source, duration, timerScheduler, loopScheduler); } public virtual IObservable> TakeLastBuffer(IObservable source, TimeSpan duration) @@ -359,7 +359,7 @@ public virtual IObservable> TakeLastBuffer(IObservable> TakeLastBuffer_(IObservable source, TimeSpan duration, IScheduler scheduler) { - return new TakeLastBuffer(source, duration, scheduler); + return new TakeLastBuffer.Time(source, duration, scheduler); } #endregion @@ -456,7 +456,7 @@ public virtual IObservable Timeout(IObservable source private static IObservable Timeout_(IObservable source, TimeSpan dueTime, IObservable other, IScheduler scheduler) { - return new Timeout(source, dueTime, other, scheduler); + return new Timeout.Relative(source, dueTime, other, scheduler); } #endregion @@ -485,7 +485,7 @@ public virtual IObservable Timeout(IObservable source private static IObservable Timeout_(IObservable source, DateTimeOffset dueTime, IObservable other, IScheduler scheduler) { - return new Timeout(source, dueTime, other, scheduler); + return new Timeout.Absolute(source, dueTime, other, scheduler); } #endregion @@ -565,22 +565,22 @@ public virtual IObservable Timer(DateTimeOffset dueTime, TimeSpan period, private static IObservable Timer_(TimeSpan dueTime, IScheduler scheduler) { - return new Timer(dueTime, null, scheduler); + return new Timer.Single.Relative(dueTime, scheduler); } private static IObservable Timer_(TimeSpan dueTime, TimeSpan period, IScheduler scheduler) { - return new Timer(dueTime, period, scheduler); + return new Timer.Periodic.Relative(dueTime, period, scheduler); } private static IObservable Timer_(DateTimeOffset dueTime, IScheduler scheduler) { - return new Timer(dueTime, null, scheduler); + return new Timer.Single.Absolute(dueTime, scheduler); } private static IObservable Timer_(DateTimeOffset dueTime, TimeSpan period, IScheduler scheduler) { - return new Timer(dueTime, period, scheduler); + return new Timer.Periodic.Absolute(dueTime, period, scheduler); } #endregion @@ -610,12 +610,17 @@ private static IObservable> Timestamp_(IObservable public virtual IObservable> Window(IObservable source, TimeSpan timeSpan) { - return Window_(source, timeSpan, timeSpan, SchedulerDefaults.TimeBasedOperations); + return Window_(source, timeSpan, SchedulerDefaults.TimeBasedOperations); } public virtual IObservable> Window(IObservable source, TimeSpan timeSpan, IScheduler scheduler) { - return Window_(source, timeSpan, timeSpan, scheduler); + return Window_(source, timeSpan, scheduler); + } + + private static IObservable> Window_(IObservable source, TimeSpan timeSpan, IScheduler scheduler) + { + return new Window.TimeHopping(source, timeSpan, scheduler); } public virtual IObservable> Window(IObservable source, TimeSpan timeSpan, TimeSpan timeShift) @@ -630,7 +635,7 @@ public virtual IObservable> Window(IObservable> Window_(IObservable source, TimeSpan timeSpan, TimeSpan timeShift, IScheduler scheduler) { - return new Window(source, timeSpan, timeShift, scheduler); + return new Window.TimeSliding(source, timeSpan, timeShift, scheduler); } #endregion @@ -649,7 +654,7 @@ public virtual IObservable> Window(IObservable> Window_(IObservable source, TimeSpan timeSpan, int count, IScheduler scheduler) { - return new Window(source, timeSpan, count, scheduler); + return new Window.Ferry(source, timeSpan, count, scheduler); } #endregion