Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/rx.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable')
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/AddRef.cs55
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Aggregate.cs158
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/All.cs73
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Amb.cs173
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Any.cs115
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/AsObservable.cs60
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Average.cs703
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Buffer.cs709
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Case.cs85
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Cast.cs62
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Catch.cs183
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Collect.cs139
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/CombineLatest.cs1863
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Concat.cs52
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Contains.cs76
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Count.cs124
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/DefaultIfEmpty.cs60
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Defer.cs76
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Delay.cs768
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/DelaySubscription.cs76
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Dematerialize.cs63
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Distinct.cs75
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/DistinctUntilChanged.cs94
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Do.cs92
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/DoWhile.cs54
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/ElementAt.cs75
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Empty.cs48
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Finally.cs73
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/FirstAsync.cs132
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/For.cs53
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/ForEach.cs122
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/FromEvent.cs368
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/FromEventPattern.cs143
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Generate.cs292
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/GetEnumerator.cs102
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/GroupBy.cs167
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/GroupByUntil.cs374
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/GroupJoin.cs302
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/If.cs81
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/IgnoreElements.cs54
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/IsEmpty.cs53
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Join.cs336
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/LastAsync.cs140
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Latest.cs145
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/LongCount.cs124
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Materialize.cs57
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Max.cs792
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/MaxBy.cs108
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Merge.cs403
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Min.cs792
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/MinBy.cs108
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/MostRecent.cs85
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Multicast.cs82
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Never.cs20
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Next.cs156
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/ObserveOn.cs89
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/OfType.cs53
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/OnErrorResumeNext.cs60
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/PushToPullAdapter.cs93
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Range.cs83
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/RefCount.cs88
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Repeat.cs127
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Return.cs51
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Sample.cs243
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Scan.cs146
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Select.cs138
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/SelectMany.cs888
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/SequenceEqual.cs322
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/SingleAsync.cs154
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Skip.cs151
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/SkipLast.cs125
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/SkipUntil.cs210
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/SkipWhile.cs139
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Sum.cs517
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Switch.cs152
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Synchronize.cs71
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Take.cs176
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/TakeLast.cs230
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/TakeLastBuffer.cs141
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/TakeUntil.cs258
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/TakeWhile.cs149
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Throttle.cs280
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Throw.cs50
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/TimeInterval.cs73
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Timeout.cs432
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Timer.cs264
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Timestamp.cs56
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/ToArray.cs55
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/ToDictionary.cs71
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/ToList.cs55
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/ToLookup.cs72
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/ToObservable.cs174
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Using.cs76
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Where.cs135
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/While.cs53
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Window.cs758
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Zip.cs2326
-rw-r--r--Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/_.cs9
98 files changed, 21568 insertions, 0 deletions
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/AddRef.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/AddRef.cs
new file mode 100644
index 0000000..3fc6962
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/AddRef.cs
@@ -0,0 +1,55 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+using System.Reactive.Disposables;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class AddRef<TSource> : Producer<TSource>
+ {
+ private readonly IObservable<TSource> _source;
+ private readonly RefCountDisposable _refCount;
+
+ public AddRef(IObservable<TSource> source, RefCountDisposable refCount)
+ {
+ _source = source;
+ _refCount = refCount;
+ }
+
+ protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var d = new CompositeDisposable(_refCount.GetDisposable(), cancel);
+
+ var sink = new _(observer, d);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+
+ class _ : Sink<TSource>, IObserver<TSource>
+ {
+ public _(IObserver<TSource> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ }
+
+ public void OnNext(TSource value)
+ {
+ base._observer.OnNext(value);
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Aggregate.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Aggregate.cs
new file mode 100644
index 0000000..d1b6ef8
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Aggregate.cs
@@ -0,0 +1,158 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class Aggregate<TSource, TAccumulate, TResult> : Producer<TResult>
+ {
+ private readonly IObservable<TSource> _source;
+ private readonly TAccumulate _seed;
+ private readonly Func<TAccumulate, TSource, TAccumulate> _accumulator;
+ private readonly Func<TAccumulate, TResult> _resultSelector;
+
+ public Aggregate(IObservable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> accumulator, Func<TAccumulate, TResult> resultSelector)
+ {
+ _source = source;
+ _seed = seed;
+ _accumulator = accumulator;
+ _resultSelector = resultSelector;
+ }
+
+ protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+
+ class _ : Sink<TResult>, IObserver<TSource>
+ {
+ private readonly Aggregate<TSource, TAccumulate, TResult> _parent;
+ private TAccumulate _accumulation;
+
+ public _(Aggregate<TSource, TAccumulate, TResult> parent, IObserver<TResult> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ _accumulation = _parent._seed;
+ }
+
+ public void OnNext(TSource value)
+ {
+ try
+ {
+ _accumulation = _parent._accumulator(_accumulation, value);
+ }
+ catch (Exception exception)
+ {
+ base._observer.OnError(exception);
+ base.Dispose();
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ var result = default(TResult);
+ try
+ {
+ result = _parent._resultSelector(_accumulation);
+ }
+ catch (Exception exception)
+ {
+ base._observer.OnError(exception);
+ base.Dispose();
+ return;
+ }
+
+ base._observer.OnNext(result);
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+
+ class Aggregate<TSource> : Producer<TSource>
+ {
+ private readonly IObservable<TSource> _source;
+ private readonly Func<TSource, TSource, TSource> _accumulator;
+
+ public Aggregate(IObservable<TSource> source, Func<TSource, TSource, TSource> accumulator)
+ {
+ _source = source;
+ _accumulator = accumulator;
+ }
+
+ protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+
+ class _ : Sink<TSource>, IObserver<TSource>
+ {
+ private readonly Aggregate<TSource> _parent;
+ private TSource _accumulation;
+ private bool _hasAccumulation;
+
+ public _(Aggregate<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ _accumulation = default(TSource);
+ _hasAccumulation = false;
+ }
+
+ public void OnNext(TSource value)
+ {
+ if (!_hasAccumulation)
+ {
+ _accumulation = value;
+ _hasAccumulation = true;
+ }
+ else
+ {
+ try
+ {
+ _accumulation = _parent._accumulator(_accumulation, value);
+ }
+ catch (Exception exception)
+ {
+ base._observer.OnError(exception);
+ base.Dispose();
+ }
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ if (!_hasAccumulation)
+ {
+ base._observer.OnError(new InvalidOperationException(Strings_Linq.NO_ELEMENTS));
+ base.Dispose();
+ }
+ else
+ {
+ base._observer.OnNext(_accumulation);
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/All.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/All.cs
new file mode 100644
index 0000000..09c825d
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/All.cs
@@ -0,0 +1,73 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class All<TSource> : Producer<bool>
+ {
+ private readonly IObservable<TSource> _source;
+ private readonly Func<TSource, bool> _predicate;
+
+ public All(IObservable<TSource> source, Func<TSource, bool> predicate)
+ {
+ _source = source;
+ _predicate = predicate;
+ }
+
+ protected override IDisposable Run(IObserver<bool> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+
+ class _ : Sink<bool>, IObserver<TSource>
+ {
+ private readonly All<TSource> _parent;
+
+ public _(All<TSource> parent, IObserver<bool> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ public void OnNext(TSource value)
+ {
+ var res = false;
+ try
+ {
+ res = _parent._predicate(value);
+ }
+ catch (Exception ex)
+ {
+ base._observer.OnError(ex);
+ base.Dispose();
+ return;
+ }
+
+ if (!res)
+ {
+ 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(true);
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Amb.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Amb.cs
new file mode 100644
index 0000000..7272cee
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Amb.cs
@@ -0,0 +1,173 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+using System.Reactive.Disposables;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class Amb<TSource> : Producer<TSource>
+ {
+ private readonly IObservable<TSource> _left;
+ private readonly IObservable<TSource> _right;
+
+ public Amb(IObservable<TSource> left, IObservable<TSource> right)
+ {
+ _left = left;
+ _right = right;
+ }
+
+ protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+
+ class _ : Sink<TSource>
+ {
+ private readonly Amb<TSource> _parent;
+
+ public _(Amb<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ private AmbState _choice;
+
+ public IDisposable Run()
+ {
+ var ls = new SingleAssignmentDisposable();
+ var rs = new SingleAssignmentDisposable();
+ var d = new CompositeDisposable(ls, rs);
+
+ var gate = new object();
+
+ var lo = new AmbObserver();
+ lo._disposable = d;
+ lo._target = new DecisionObserver(this, gate, AmbState.Left, ls, rs, lo);
+
+ var ro = new AmbObserver();
+ ro._disposable = d;
+ ro._target = new DecisionObserver(this, gate, AmbState.Right, rs, ls, ro);
+
+ _choice = AmbState.Neither;
+
+ ls.Disposable = _parent._left.SubscribeSafe(lo);
+ rs.Disposable = _parent._right.SubscribeSafe(ro);
+
+ return d;
+ }
+
+ class DecisionObserver : IObserver<TSource>
+ {
+ private readonly _ _parent;
+ private readonly AmbState _me;
+ private readonly IDisposable _subscription;
+ private readonly IDisposable _otherSubscription;
+ private readonly object _gate;
+ private readonly AmbObserver _observer;
+
+ public DecisionObserver(_ parent, object gate, AmbState me, IDisposable subscription, IDisposable otherSubscription, AmbObserver observer)
+ {
+ _parent = parent;
+ _gate = gate;
+ _me = me;
+ _subscription = subscription;
+ _otherSubscription = otherSubscription;
+ _observer = observer;
+ }
+
+ public void OnNext(TSource value)
+ {
+ lock (_gate)
+ {
+ if (_parent._choice == AmbState.Neither)
+ {
+ _parent._choice = _me;
+ _otherSubscription.Dispose();
+ _observer._disposable = _subscription;
+ _observer._target = _parent._observer;
+ }
+
+ if (_parent._choice == _me)
+ _parent._observer.OnNext(value);
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ lock (_gate)
+ {
+ if (_parent._choice == AmbState.Neither)
+ {
+ _parent._choice = _me;
+ _otherSubscription.Dispose();
+ _observer._disposable = _subscription;
+ _observer._target = _parent._observer;
+ }
+
+ if (_parent._choice == _me)
+ {
+ _parent._observer.OnError(error);
+ _parent.Dispose();
+ }
+ }
+ }
+
+ public void OnCompleted()
+ {
+ lock (_gate)
+ {
+ if (_parent._choice == AmbState.Neither)
+ {
+ _parent._choice = _me;
+ _otherSubscription.Dispose();
+ _observer._disposable = _subscription;
+ _observer._target = _parent._observer;
+ }
+
+ if (_parent._choice == _me)
+ {
+ _parent._observer.OnCompleted();
+ _parent.Dispose();
+ }
+ }
+ }
+ }
+
+ class AmbObserver : IObserver<TSource>
+ {
+ public IObserver<TSource> _target;
+
+ public IDisposable _disposable;
+
+ public void OnNext(TSource value)
+ {
+ _target.OnNext(value);
+ }
+
+ public void OnError(Exception error)
+ {
+ _target.OnError(error);
+ _disposable.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ _target.OnCompleted();
+ _disposable.Dispose();
+ }
+ }
+
+ enum AmbState
+ {
+ Left,
+ Right,
+ Neither
+ }
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Any.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Any.cs
new file mode 100644
index 0000000..1414bdd
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Any.cs
@@ -0,0 +1,115 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class Any<TSource> : Producer<bool>
+ {
+ private readonly IObservable<TSource> _source;
+ private readonly Func<TSource, bool> _predicate;
+
+ public Any(IObservable<TSource> source)
+ {
+ _source = source;
+ }
+
+ public Any(IObservable<TSource> source, Func<TSource, bool> predicate)
+ {
+ _source = source;
+ _predicate = predicate;
+ }
+
+ protected override IDisposable Run(IObserver<bool> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ if (_predicate != null)
+ {
+ var sink = new π(this, observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+ else
+ {
+ var sink = new _(observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+ }
+
+ class _ : Sink<bool>, IObserver<TSource>
+ {
+ public _(IObserver<bool> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ }
+
+ 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 OnCompleted()
+ {
+ base._observer.OnNext(false);
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+
+ class π : Sink<bool>, IObserver<TSource>
+ {
+ private readonly Any<TSource> _parent;
+
+ public π(Any<TSource> parent, IObserver<bool> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ public void OnNext(TSource value)
+ {
+ var res = false;
+ try
+ {
+ res = _parent._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(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ base._observer.OnNext(false);
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/AsObservable.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/AsObservable.cs
new file mode 100644
index 0000000..09d5f14
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/AsObservable.cs
@@ -0,0 +1,60 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class AsObservable<TSource> : Producer<TSource>, IEvaluatableObservable<TSource>
+ {
+ private readonly IObservable<TSource> _source;
+
+ public AsObservable(IObservable<TSource> source)
+ {
+ _source = source;
+ }
+
+ public IObservable<TSource> Ω()
+ {
+ return this;
+ }
+
+ public IObservable<TSource> Eval()
+ {
+ return _source;
+ }
+
+ protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+
+ class _ : Sink<TSource>, IObserver<TSource>
+ {
+ public _(IObserver<TSource> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ }
+
+ public void OnNext(TSource value)
+ {
+ base._observer.OnNext(value);
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Average.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Average.cs
new file mode 100644
index 0000000..fb2d6b7
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Average.cs
@@ -0,0 +1,703 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class AverageDouble : Producer<double>
+ {
+ private readonly IObservable<double> _source;
+
+ public AverageDouble(IObservable<double> source)
+ {
+ _source = source;
+ }
+
+ protected override IDisposable Run(IObserver<double> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+
+ class _ : Sink<double>, IObserver<double>
+ {
+ private double _sum;
+ private long _count;
+
+ public _(IObserver<double> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _sum = 0.0;
+ _count = 0L;
+ }
+
+ public void OnNext(double value)
+ {
+ try
+ {
+ checked
+ {
+ _sum += value;
+ _count++;
+ }
+ }
+ catch (Exception ex)
+ {
+ base._observer.OnError(ex);
+ base.Dispose();
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ if (_count > 0)
+ {
+ base._observer.OnNext(_sum / _count);
+ base._observer.OnCompleted();
+ }
+ else
+ {
+ base._observer.OnError(new InvalidOperationException(Strings_Linq.NO_ELEMENTS));
+ }
+
+ base.Dispose();
+ }
+ }
+ }
+
+ class AverageSingle : Producer<float>
+ {
+ private readonly IObservable<float> _source;
+
+ public AverageSingle(IObservable<float> source)
+ {
+ _source = source;
+ }
+
+ protected override IDisposable Run(IObserver<float> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+
+ class _ : Sink<float>, IObserver<float>
+ {
+ private double _sum; // NOTE: Uses a different accumulator type (double), conform LINQ to Objects.
+ private long _count;
+
+ public _(IObserver<float> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _sum = 0.0;
+ _count = 0L;
+ }
+
+ public void OnNext(float value)
+ {
+ try
+ {
+ checked
+ {
+ _sum += value;
+ _count++;
+ }
+ }
+ catch (Exception ex)
+ {
+ base._observer.OnError(ex);
+ base.Dispose();
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ if (_count > 0)
+ {
+ base._observer.OnNext((float)(_sum / _count));
+ base._observer.OnCompleted();
+ }
+ else
+ {
+ base._observer.OnError(new InvalidOperationException(Strings_Linq.NO_ELEMENTS));
+ }
+
+ base.Dispose();
+ }
+ }
+ }
+
+ class AverageDecimal : Producer<decimal>
+ {
+ private readonly IObservable<decimal> _source;
+
+ public AverageDecimal(IObservable<decimal> source)
+ {
+ _source = source;
+ }
+
+ protected override IDisposable Run(IObserver<decimal> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+
+ class _ : Sink<decimal>, IObserver<decimal>
+ {
+ private decimal _sum;
+ private long _count;
+
+ public _(IObserver<decimal> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _sum = 0M;
+ _count = 0L;
+ }
+
+ public void OnNext(decimal value)
+ {
+ try
+ {
+ checked
+ {
+ _sum += value;
+ _count++;
+ }
+ }
+ catch (Exception ex)
+ {
+ base._observer.OnError(ex);
+ base.Dispose();
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ if (_count > 0)
+ {
+ base._observer.OnNext(_sum / _count);
+ base._observer.OnCompleted();
+ }
+ else
+ {
+ base._observer.OnError(new InvalidOperationException(Strings_Linq.NO_ELEMENTS));
+ }
+
+ base.Dispose();
+ }
+ }
+ }
+
+ class AverageInt32 : Producer<double>
+ {
+ private readonly IObservable<int> _source;
+
+ public AverageInt32(IObservable<int> source)
+ {
+ _source = source;
+ }
+
+ protected override IDisposable Run(IObserver<double> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+
+ class _ : Sink<double>, IObserver<int>
+ {
+ private long _sum;
+ private long _count;
+
+ public _(IObserver<double> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _sum = 0L;
+ _count = 0L;
+ }
+
+ public void OnNext(int value)
+ {
+ try
+ {
+ checked
+ {
+ _sum += value;
+ _count++;
+ }
+ }
+ catch (Exception ex)
+ {
+ base._observer.OnError(ex);
+ base.Dispose();
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ if (_count > 0)
+ {
+ base._observer.OnNext((double)_sum / _count);
+ base._observer.OnCompleted();
+ }
+ else
+ {
+ base._observer.OnError(new InvalidOperationException(Strings_Linq.NO_ELEMENTS));
+ }
+
+ base.Dispose();
+ }
+ }
+ }
+
+ class AverageInt64 : Producer<double>
+ {
+ private readonly IObservable<long> _source;
+
+ public AverageInt64(IObservable<long> source)
+ {
+ _source = source;
+ }
+
+ protected override IDisposable Run(IObserver<double> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+
+ class _ : Sink<double>, IObserver<long>
+ {
+ private long _sum;
+ private long _count;
+
+ public _(IObserver<double> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _sum = 0L;
+ _count = 0L;
+ }
+
+ public void OnNext(long value)
+ {
+ try
+ {
+ checked
+ {
+ _sum += value;
+ _count++;
+ }
+ }
+ catch (Exception ex)
+ {
+ base._observer.OnError(ex);
+ base.Dispose();
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ if (_count > 0)
+ {
+ base._observer.OnNext((double)_sum / _count);
+ base._observer.OnCompleted();
+ }
+ else
+ {
+ base._observer.OnError(new InvalidOperationException(Strings_Linq.NO_ELEMENTS));
+ }
+
+ base.Dispose();
+ }
+ }
+ }
+
+ class AverageDoubleNullable : Producer<double?>
+ {
+ private readonly IObservable<double?> _source;
+
+ public AverageDoubleNullable(IObservable<double?> source)
+ {
+ _source = source;
+ }
+
+ protected override IDisposable Run(IObserver<double?> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+
+ class _ : Sink<double?>, IObserver<double?>
+ {
+ private double _sum;
+ private long _count;
+
+ public _(IObserver<double?> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _sum = 0.0;
+ _count = 0L;
+ }
+
+ public void OnNext(double? value)
+ {
+ try
+ {
+ checked
+ {
+ if (value != null)
+ {
+ _sum += value.Value;
+ _count++;
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ base._observer.OnError(ex);
+ base.Dispose();
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ if (_count > 0)
+ {
+ base._observer.OnNext(_sum / _count);
+ }
+ else
+ {
+ base._observer.OnNext(null);
+ }
+
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+
+ class AverageSingleNullable : Producer<float?>
+ {
+ private readonly IObservable<float?> _source;
+
+ public AverageSingleNullable(IObservable<float?> source)
+ {
+ _source = source;
+ }
+
+ protected override IDisposable Run(IObserver<float?> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+
+ class _ : Sink<float?>, IObserver<float?>
+ {
+ private double _sum; // NOTE: Uses a different accumulator type (double), conform LINQ to Objects.
+ private long _count;
+
+ public _(IObserver<float?> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _sum = 0.0;
+ _count = 0L;
+ }
+
+ public void OnNext(float? value)
+ {
+ try
+ {
+ checked
+ {
+ if (value != null)
+ {
+ _sum += value.Value;
+ _count++;
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ base._observer.OnError(ex);
+ base.Dispose();
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ if (_count > 0)
+ {
+ base._observer.OnNext((float)(_sum / _count));
+ }
+ else
+ {
+ base._observer.OnNext(null);
+ }
+
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+
+ class AverageDecimalNullable : Producer<decimal?>
+ {
+ private readonly IObservable<decimal?> _source;
+
+ public AverageDecimalNullable(IObservable<decimal?> source)
+ {
+ _source = source;
+ }
+
+ protected override IDisposable Run(IObserver<decimal?> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+
+ class _ : Sink<decimal?>, IObserver<decimal?>
+ {
+ private decimal _sum;
+ private long _count;
+
+ public _(IObserver<decimal?> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _sum = 0M;
+ _count = 0L;
+ }
+
+ public void OnNext(decimal? value)
+ {
+ try
+ {
+ checked
+ {
+ if (value != null)
+ {
+ _sum += value.Value;
+ _count++;
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ base._observer.OnError(ex);
+ base.Dispose();
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ if (_count > 0)
+ {
+ base._observer.OnNext(_sum / _count);
+ }
+ else
+ {
+ base._observer.OnNext(null);
+ }
+
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+
+ class AverageInt32Nullable : Producer<double?>
+ {
+ private readonly IObservable<int?> _source;
+
+ public AverageInt32Nullable(IObservable<int?> source)
+ {
+ _source = source;
+ }
+
+ protected override IDisposable Run(IObserver<double?> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+
+ class _ : Sink<double?>, IObserver<int?>
+ {
+ private long _sum;
+ private long _count;
+
+ public _(IObserver<double?> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _sum = 0L;
+ _count = 0L;
+ }
+
+ public void OnNext(int? value)
+ {
+ try
+ {
+ checked
+ {
+ if (value != null)
+ {
+ _sum += value.Value;
+ _count++;
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ base._observer.OnError(ex);
+ base.Dispose();
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ if (_count > 0)
+ {
+ base._observer.OnNext((double)_sum / _count);
+ }
+ else
+ {
+ base._observer.OnNext(null);
+ }
+
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+
+ class AverageInt64Nullable : Producer<double?>
+ {
+ private readonly IObservable<long?> _source;
+
+ public AverageInt64Nullable(IObservable<long?> source)
+ {
+ _source = source;
+ }
+
+ protected override IDisposable Run(IObserver<double?> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+
+ class _ : Sink<double?>, IObserver<long?>
+ {
+ private long _sum;
+ private long _count;
+
+ public _(IObserver<double?> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _sum = 0L;
+ _count = 0L;
+ }
+
+ public void OnNext(long? value)
+ {
+ try
+ {
+ checked
+ {
+ if (value != null)
+ {
+ _sum += value.Value;
+ _count++;
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ base._observer.OnError(ex);
+ base.Dispose();
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ if (_count > 0)
+ {
+ base._observer.OnNext((double)_sum / _count);
+ }
+ else
+ {
+ base._observer.OnNext(null);
+ }
+
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Buffer.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Buffer.cs
new file mode 100644
index 0000000..a82b550
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Buffer.cs
@@ -0,0 +1,709 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Reactive.Concurrency;
+using System.Reactive.Disposables;
+using System.Threading;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class Buffer<TSource> : Producer<IList<TSource>>
+ {
+ private readonly IObservable<TSource> _source;
+ private readonly int _count;
+ private readonly int _skip;
+
+ private readonly TimeSpan _timeSpan;
+ private readonly TimeSpan _timeShift;
+ private readonly IScheduler _scheduler;
+
+ public Buffer(IObservable<TSource> source, int count, int skip)
+ {
+ _source = source;
+ _count = count;
+ _skip = skip;
+ }
+
+ public Buffer(IObservable<TSource> source, TimeSpan timeSpan, TimeSpan timeShift, IScheduler scheduler)
+ {
+ _source = source;
+ _timeSpan = timeSpan;
+ _timeShift = timeShift;
+ _scheduler = scheduler;
+ }
+
+ public Buffer(IObservable<TSource> source, TimeSpan timeSpan, int count, IScheduler scheduler)
+ {
+ _source = source;
+ _timeSpan = timeSpan;
+ _count = count;
+ _scheduler = scheduler;
+ }
+
+ protected override IDisposable Run(IObserver<IList<TSource>> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ if (_scheduler == null)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+ else if (_count > 0)
+ {
+ var sink = new μ(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+ else
+ {
+ if (_timeSpan == _timeShift)
+ {
+ var sink = new π(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+ else
+ {
+ var sink = new τ(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+ }
+ }
+
+ class _ : Sink<IList<TSource>>, IObserver<TSource>
+ {
+ private readonly Buffer<TSource> _parent;
+
+ public _(Buffer<TSource> parent, IObserver<IList<TSource>> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ private Queue<IList<TSource>> _queue;
+ private int _n;
+
+ public IDisposable Run()
+ {
+ _queue = new Queue<IList<TSource>>();
+ _n = 0;
+
+ CreateWindow();
+ return _parent._source.SubscribeSafe(this);
+ }
+
+ private void CreateWindow()
+ {
+ var s = new List<TSource>();
+ _queue.Enqueue(s);
+ }
+
+ public void OnNext(TSource value)
+ {
+ foreach (var s in _queue)
+ s.Add(value);
+
+ var c = _n - _parent._count + 1;
+ if (c >= 0 && c % _parent._skip == 0)
+ {
+ var s = _queue.Dequeue();
+ if (s.Count > 0)
+ base._observer.OnNext(s);
+ }
+
+ _n++;
+ if (_n % _parent._skip == 0)
+ CreateWindow();
+ }
+
+ public void OnError(Exception error)
+ {
+ while (_queue.Count > 0)
+ _queue.Dequeue().Clear();
+
+ base._observer.OnError(error);
+ 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 τ : Sink<IList<TSource>>, IObserver<TSource>
+ {
+ private readonly Buffer<TSource> _parent;
+
+ public τ(Buffer<TSource> parent, IObserver<IList<TSource>> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ private TimeSpan _totalTime;
+ private TimeSpan _nextShift;
+ private TimeSpan _nextSpan;
+
+ private object _gate;
+ private Queue<List<TSource>> _q;
+
+ private SerialDisposable _timerD;
+
+ public IDisposable Run()
+ {
+ _totalTime = TimeSpan.Zero;
+ _nextShift = _parent._timeShift;
+ _nextSpan = _parent._timeSpan;
+
+ _gate = new object();
+ _q = new Queue<List<TSource>>();
+
+ _timerD = new SerialDisposable();
+
+ CreateWindow();
+ CreateTimer();
+
+ var subscription = _parent._source.SubscribeSafe(this);
+
+ return new CompositeDisposable { _timerD, subscription };
+ }
+
+ private void CreateWindow()
+ {
+ var s = new List<TSource>();
+ _q.Enqueue(s);
+ }
+
+ private void CreateTimer()
+ {
+ var m = new SingleAssignmentDisposable();
+ _timerD.Disposable = m;
+
+ var isSpan = false;
+ var isShift = false;
+ if (_nextSpan == _nextShift)
+ {
+ isSpan = true;
+ isShift = true;
+ }
+ else if (_nextSpan < _nextShift)
+ isSpan = true;
+ else
+ isShift = true;
+
+ var newTotalTime = isSpan ? _nextSpan : _nextShift;
+ var ts = newTotalTime - _totalTime;
+ _totalTime = newTotalTime;
+
+ if (isSpan)
+ _nextSpan += _parent._timeShift;
+ if (isShift)
+ _nextShift += _parent._timeShift;
+
+ m.Disposable = _parent._scheduler.Schedule(new State { isSpan = isSpan, isShift = isShift }, ts, Tick);
+ }
+
+ struct State
+ {
+ public bool isSpan;
+ public bool isShift;
+ }
+
+ private IDisposable Tick(IScheduler self, State state)
+ {
+ lock (_gate)
+ {
+ //
+ // 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();
+
+ return Disposable.Empty;
+ }
+
+ public void OnNext(TSource value)
+ {
+ lock (_gate)
+ {
+ foreach (var s in _q)
+ s.Add(value);
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ lock (_gate)
+ {
+ while (_q.Count > 0)
+ _q.Dequeue().Clear();
+
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+ }
+
+ public void OnCompleted()
+ {
+ lock (_gate)
+ {
+ while (_q.Count > 0)
+ base._observer.OnNext(_q.Dequeue());
+
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+
+ class π : Sink<IList<TSource>>, IObserver<TSource>
+ {
+ private readonly Buffer<TSource> _parent;
+
+ public π(Buffer<TSource> parent, IObserver<IList<TSource>> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ private object _gate;
+ private List<TSource> _list;
+
+ public IDisposable Run()
+ {
+ _gate = new object();
+ _list = new List<TSource>();
+
+ var d = _parent._scheduler.SchedulePeriodic(_parent._timeSpan, Tick);
+ var s = _parent._source.SubscribeSafe(this);
+
+ return new CompositeDisposable(d, s);
+ }
+
+ private void Tick()
+ {
+ lock (_gate)
+ {
+ base._observer.OnNext(_list);
+ _list = new List<TSource>();
+ }
+ }
+
+ public void OnNext(TSource value)
+ {
+ lock (_gate)
+ {
+ _list.Add(value);
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ lock (_gate)
+ {
+ _list.Clear();
+
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+ }
+
+ public void OnCompleted()
+ {
+ lock (_gate)
+ {
+ base._observer.OnNext(_list);
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+
+ class μ : Sink<IList<TSource>>, IObserver<TSource>
+ {
+ private readonly Buffer<TSource> _parent;
+
+ public μ(Buffer<TSource> parent, IObserver<IList<TSource>> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ private object _gate;
+ private IList<TSource> _s;
+ private int _n;
+ private int _windowId;
+
+ private SerialDisposable _timerD;
+
+ public IDisposable Run()
+ {
+ _gate = new object();
+ _s = default(IList<TSource>);
+ _n = 0;
+ _windowId = 0;
+
+ _timerD = new SerialDisposable();
+
+ _s = new List<TSource>();
+ CreateTimer(0);
+
+ var subscription = _parent._source.SubscribeSafe(this);
+
+ return new CompositeDisposable { _timerD, subscription };
+ }
+
+ private void CreateTimer(int id)
+ {
+ var m = new SingleAssignmentDisposable();
+ _timerD.Disposable = m;
+
+ m.Disposable = _parent._scheduler.Schedule(id, _parent._timeSpan, Tick);
+ }
+
+ private IDisposable Tick(IScheduler self, int id)
+ {
+ var d = Disposable.Empty;
+
+ var newId = 0;
+ lock (_gate)
+ {
+ if (id != _windowId)
+ return d;
+
+ _n = 0;
+ newId = ++_windowId;
+
+ var res = _s;
+ _s = new List<TSource>();
+ base._observer.OnNext(res);
+ }
+
+ CreateTimer(newId);
+
+ return d;
+ }
+
+ public void OnNext(TSource value)
+ {
+ 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<TSource>();
+ base._observer.OnNext(res);
+ }
+ }
+
+ if (newWindow)
+ CreateTimer(newId);
+ }
+
+ public void OnError(Exception error)
+ {
+ lock (_gate)
+ {
+ _s.Clear();
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+ }
+
+ public void OnCompleted()
+ {
+ lock (_gate)
+ {
+ base._observer.OnNext(_s);
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+ }
+
+ class Buffer<TSource, TBufferClosing> : Producer<IList<TSource>>
+ {
+ private readonly IObservable<TSource> _source;
+ private readonly Func<IObservable<TBufferClosing>> _bufferClosingSelector;
+ private readonly IObservable<TBufferClosing> _bufferBoundaries;
+
+ public Buffer(IObservable<TSource> source, Func<IObservable<TBufferClosing>> bufferClosingSelector)
+ {
+ _source = source;
+ _bufferClosingSelector = bufferClosingSelector;
+ }
+
+ public Buffer(IObservable<TSource> source, IObservable<TBufferClosing> bufferBoundaries)
+ {
+ _source = source;
+ _bufferBoundaries = bufferBoundaries;
+ }
+
+ protected override IDisposable Run(IObserver<IList<TSource>> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ if (_bufferClosingSelector != null)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+ else
+ {
+ var sink = new β(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+ }
+
+ class _ : Sink<IList<TSource>>, IObserver<TSource>
+ {
+ private readonly Buffer<TSource, TBufferClosing> _parent;
+
+ public _(Buffer<TSource, TBufferClosing> parent, IObserver<IList<TSource>> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ private IList<TSource> _buffer;
+ private object _gate;
+ private AsyncLock _bufferGate;
+
+ private SerialDisposable _m;
+
+ public IDisposable Run()
+ {
+ _buffer = new List<TSource>();
+ _gate = new object();
+ _bufferGate = new AsyncLock();
+
+ _m = new SerialDisposable();
+ var groupDisposable = new CompositeDisposable(2) { _m };
+
+ groupDisposable.Add(_parent._source.SubscribeSafe(this));
+
+ _bufferGate.Wait(CreateBufferClose);
+
+ return groupDisposable;
+ }
+
+ private void CreateBufferClose()
+ {
+ var bufferClose = default(IObservable<TBufferClosing>);
+ try
+ {
+ bufferClose = _parent._bufferClosingSelector();
+ }
+ catch (Exception exception)
+ {
+ lock (_gate)
+ {
+ base._observer.OnError(exception);
+ base.Dispose();
+ }
+ return;
+ }
+
+ var closingSubscription = new SingleAssignmentDisposable();
+ _m.Disposable = closingSubscription;
+ closingSubscription.Disposable = bufferClose.SubscribeSafe(new ω(this, closingSubscription));
+ }
+
+ private void CloseBuffer(IDisposable closingSubscription)
+ {
+ closingSubscription.Dispose();
+
+ lock (_gate)
+ {
+ var res = _buffer;
+ _buffer = new List<TSource>();
+ base._observer.OnNext(res);
+ }
+
+ _bufferGate.Wait(CreateBufferClose);
+ }
+
+ class ω : IObserver<TBufferClosing>
+ {
+ private readonly _ _parent;
+ private readonly IDisposable _self;
+
+ public ω(_ parent, IDisposable self)
+ {
+ _parent = parent;
+ _self = self;
+ }
+
+ public void OnNext(TBufferClosing value)
+ {
+ _parent.CloseBuffer(_self);
+ }
+
+ public void OnError(Exception error)
+ {
+ _parent.OnError(error);
+ }
+
+ public void OnCompleted()
+ {
+ _parent.CloseBuffer(_self);
+ }
+ }
+
+ 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();
+ }
+ }
+ }
+
+ class β : Sink<IList<TSource>>, IObserver<TSource>
+ {
+ private readonly Buffer<TSource, TBufferClosing> _parent;
+
+ public β(Buffer<TSource, TBufferClosing> parent, IObserver<IList<TSource>> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ private IList<TSource> _buffer;
+ private object _gate;
+
+ private RefCountDisposable _refCountDisposable;
+
+ public IDisposable Run()
+ {
+ _buffer = new List<TSource>();
+ _gate = new object();
+
+ var d = new CompositeDisposable(2);
+ _refCountDisposable = new RefCountDisposable(d);
+
+ d.Add(_parent._source.SubscribeSafe(this));
+ d.Add(_parent._bufferBoundaries.SubscribeSafe(new ω(this)));
+
+ return _refCountDisposable;
+ }
+
+ class ω : IObserver<TBufferClosing>
+ {
+ private readonly β _parent;
+
+ public ω(β parent)
+ {
+ _parent = parent;
+ }
+
+ public void OnNext(TBufferClosing value)
+ {
+ lock (_parent._gate)
+ {
+ var res = _parent._buffer;
+ _parent._buffer = new List<TSource>();
+ _parent._observer.OnNext(res);
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ _parent.OnError(error);
+ }
+
+ 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();
+ }
+ }
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Case.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Case.cs
new file mode 100644
index 0000000..b104050
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Case.cs
@@ -0,0 +1,85 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+using System.Collections.Generic;
+using System.Reactive.Disposables;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class Case<TValue, TResult> : Producer<TResult>, IEvaluatableObservable<TResult>
+ {
+ private readonly Func<TValue> _selector;
+ private readonly IDictionary<TValue, IObservable<TResult>> _sources;
+ private readonly IObservable<TResult> _defaultSource;
+
+ public Case(Func<TValue> selector, IDictionary<TValue, IObservable<TResult>> sources, IObservable<TResult> defaultSource)
+ {
+ _selector = selector;
+ _sources = sources;
+ _defaultSource = defaultSource;
+ }
+
+ public IObservable<TResult> Eval()
+ {
+ var res = default(IObservable<TResult>);
+ if (_sources.TryGetValue(_selector(), out res))
+ return res;
+
+ return _defaultSource;
+ }
+
+ protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+
+ class _ : Sink<TResult>, IObserver<TResult>
+ {
+ private readonly Case<TValue, TResult> _parent;
+
+ public _(Case<TValue, TResult> parent, IObserver<TResult> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ public IDisposable Run()
+ {
+ var result = default(IObservable<TResult>);
+ try
+ {
+ result = _parent.Eval();
+ }
+ catch (Exception exception)
+ {
+ base._observer.OnError(exception);
+ base.Dispose();
+ return Disposable.Empty;
+ }
+
+ return result.SubscribeSafe(this);
+ }
+
+ public void OnNext(TResult value)
+ {
+ base._observer.OnNext(value);
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+}
+#endif
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Cast.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Cast.cs
new file mode 100644
index 0000000..48820b3
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Cast.cs
@@ -0,0 +1,62 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class Cast<TSource, TResult> : Producer<TResult> /* Could optimize further by deriving from Select<TResult> and providing Ω<TResult2>. We're not doing this (yet) for debuggability. */
+ {
+ private readonly IObservable<TSource> _source;
+
+ public Cast(IObservable<TSource> source)
+ {
+ _source = source;
+ }
+
+ protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+
+ class _ : Sink<TResult>, IObserver<TSource>
+ {
+ public _(IObserver<TResult> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ }
+
+ public void OnNext(TSource value)
+ {
+ var result = default(TResult);
+ try
+ {
+ result = (TResult)(object)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.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Catch.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Catch.cs
new file mode 100644
index 0000000..71e0037
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Catch.cs
@@ -0,0 +1,183 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+using System.Collections.Generic;
+using System.Reactive.Concurrency;
+using System.Reactive.Disposables;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class Catch<TSource> : Producer<TSource>
+ {
+ private readonly IEnumerable<IObservable<TSource>> _sources;
+
+ public Catch(IEnumerable<IObservable<TSource>> sources)
+ {
+ _sources = sources;
+ }
+
+ protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(observer, cancel);
+ setSink(sink);
+ return sink.Run(_sources);
+ }
+
+ class _ : TailRecursiveSink<TSource>
+ {
+ public _(IObserver<TSource> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ }
+
+ protected override IEnumerable<IObservable<TSource>> Extract(IObservable<TSource> source)
+ {
+ var @catch = source as Catch<TSource>;
+ if (@catch != null)
+ return @catch._sources;
+
+ return null;
+ }
+
+ public override void OnNext(TSource value)
+ {
+ base._observer.OnNext(value);
+ }
+
+ private Exception _lastException;
+
+ public override void OnError(Exception error)
+ {
+ _lastException = error;
+ _recurse();
+ }
+
+ public override void OnCompleted()
+ {
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+
+ protected override void Done()
+ {
+ if (_lastException != null)
+ base._observer.OnError(_lastException);
+ else
+ base._observer.OnCompleted();
+
+ base.Dispose();
+ }
+ }
+ }
+
+ class Catch<TSource, TException> : Producer<TSource> where TException : Exception
+ {
+ private readonly IObservable<TSource> _source;
+ private readonly Func<TException, IObservable<TSource>> _handler;
+
+ public Catch(IObservable<TSource> source, Func<TException, IObservable<TSource>> handler)
+ {
+ _source = source;
+ _handler = handler;
+ }
+
+ protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+
+ class _ : Sink<TSource>, IObserver<TSource>
+ {
+ private readonly Catch<TSource, TException> _parent;
+
+ public _(Catch<TSource, TException> parent, IObserver<TSource> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ private SerialDisposable _subscription;
+
+ public IDisposable Run()
+ {
+ _subscription = new SerialDisposable();
+
+ var d1 = new SingleAssignmentDisposable();
+ _subscription.Disposable = d1;
+ d1.Disposable = _parent._source.SubscribeSafe(this);
+
+ return _subscription;
+ }
+
+ public void OnNext(TSource value)
+ {
+ base._observer.OnNext(value);
+ }
+
+ public void OnError(Exception error)
+ {
+ var e = error as TException;
+ if (e != null)
+ {
+ var result = default(IObservable<TSource>);
+ try
+ {
+ result = _parent._handler(e);
+ }
+ catch (Exception ex)
+ {
+ base._observer.OnError(ex);
+ base.Dispose();
+ return;
+ }
+
+ var d = new SingleAssignmentDisposable();
+ _subscription.Disposable = d;
+ d.Disposable = result.SubscribeSafe(new ε(this));
+ }
+ else
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+ }
+
+ public void OnCompleted()
+ {
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+
+ class ε : IObserver<TSource>
+ {
+ private readonly _ _parent;
+
+ public ε(_ parent)
+ {
+ _parent = parent;
+ }
+
+ public void OnNext(TSource value)
+ {
+ _parent._observer.OnNext(value);
+ }
+
+ public void OnError(Exception error)
+ {
+ _parent._observer.OnError(error);
+ _parent.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ _parent._observer.OnCompleted();
+ _parent.Dispose();
+ }
+ }
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Collect.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Collect.cs
new file mode 100644
index 0000000..2cfd240
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Collect.cs
@@ -0,0 +1,139 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+using System.Collections.Generic;
+using System.Reactive;
+using System.Reactive.Threading;
+using System.Threading;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class Collect<TSource, TResult> : PushToPullAdapter<TSource, TResult>
+ {
+ private readonly Func<TResult> _getInitialCollector;
+ private readonly Func<TResult, TSource, TResult> _merge;
+ private readonly Func<TResult, TResult> _getNewCollector;
+
+ public Collect(IObservable<TSource> source, Func<TResult> getInitialCollector, Func<TResult, TSource, TResult> merge, Func<TResult, TResult> getNewCollector)
+ : base(source)
+ {
+ _getInitialCollector = getInitialCollector;
+ _merge = merge;
+ _getNewCollector = getNewCollector;
+ }
+
+ protected override PushToPullSink<TSource, TResult> Run(IDisposable subscription)
+ {
+ var sink = new _(this, subscription);
+ sink.Initialize();
+ return sink;
+ }
+
+ class _ : PushToPullSink<TSource, TResult>
+ {
+ private readonly Collect<TSource, TResult> _parent;
+
+ public _(Collect<TSource, TResult> parent, IDisposable subscription)
+ : base(subscription)
+ {
+ _parent = parent;
+ }
+
+ private object _gate;
+ private TResult _collector;
+ private bool _hasFailed;
+ private Exception _error;
+ private bool _hasCompleted;
+ private bool _done;
+
+ public void Initialize()
+ {
+ _gate = new object();
+ _collector = _parent._getInitialCollector();
+ }
+
+ public override void OnNext(TSource value)
+ {
+ lock (_gate)
+ {
+ try
+ {
+ _collector = _parent._merge(_collector, value);
+ }
+ catch (Exception ex)
+ {
+ _error = ex;
+ _hasFailed = true;
+
+ base.Dispose();
+ }
+ }
+ }
+
+ public override void OnError(Exception error)
+ {
+ base.Dispose();
+
+ lock (_gate)
+ {
+ _error = error;
+ _hasFailed = true;
+ }
+ }
+
+ public override void OnCompleted()
+ {
+ base.Dispose();
+
+ lock (_gate)
+ {
+ _hasCompleted = true;
+ }
+ }
+
+ public override bool TryMoveNext(out TResult current)
+ {
+ lock (_gate)
+ {
+ if (_hasFailed)
+ {
+ current = default(TResult);
+ _error.Throw();
+ }
+ else
+ {
+ if (_hasCompleted)
+ {
+ if (_done)
+ {
+ current = default(TResult);
+ return false;
+ }
+
+ current = _collector;
+ _done = true;
+ }
+ else
+ {
+ current = _collector;
+
+ try
+ {
+ _collector = _parent._getNewCollector(current);
+ }
+ catch
+ {
+ base.Dispose();
+ throw;
+ }
+ }
+ }
+
+ return true;
+ }
+ }
+ }
+ }
+}
+#endif
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/CombineLatest.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/CombineLatest.cs
new file mode 100644
index 0000000..2188307
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/CombineLatest.cs
@@ -0,0 +1,1863 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Reactive.Disposables;
+
+namespace System.Reactive.Linq.Observαble
+{
+ #region Binary
+
+ class CombineLatest<TFirst, TSecond, TResult> : Producer<TResult>
+ {
+ private readonly IObservable<TFirst> _first;
+ private readonly IObservable<TSecond> _second;
+ private readonly Func<TFirst, TSecond, TResult> _resultSelector;
+
+ public CombineLatest(IObservable<TFirst> first, IObservable<TSecond> second, Func<TFirst, TSecond, TResult> resultSelector)
+ {
+ _first = first;
+ _second = second;
+ _resultSelector = resultSelector;
+ }
+
+ protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+
+ class _ : Sink<TResult>
+ {
+ private readonly CombineLatest<TFirst, TSecond, TResult> _parent;
+
+ public _(CombineLatest<TFirst, TSecond, TResult> parent, IObserver<TResult> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ private object _gate;
+
+ public IDisposable Run()
+ {
+ _gate = new object();
+
+ var fstSubscription = new SingleAssignmentDisposable();
+ var sndSubscription = new SingleAssignmentDisposable();
+
+ var fstO = new F(this, fstSubscription);
+ var sndO = new S(this, sndSubscription);
+
+ fstO.Other = sndO;
+ sndO.Other = fstO;
+
+ fstSubscription.Disposable = _parent._first.SubscribeSafe(fstO);
+ sndSubscription.Disposable = _parent._second.SubscribeSafe(sndO);
+
+ return new CompositeDisposable(fstSubscription, sndSubscription);
+ }
+
+ class F : IObserver<TFirst>
+ {
+ private readonly _ _parent;
+ private readonly IDisposable _self;
+ private S _other;
+
+ public F(_ parent, IDisposable self)
+ {
+ _parent = parent;
+ _self = self;
+ }
+
+ public S Other { set { _other = value; } }
+
+ public bool HasValue { get; private set; }
+ public TFirst Value { get; private set; }
+ public bool Done { get; private set; }
+
+ public void OnNext(TFirst value)
+ {
+ lock (_parent._gate)
+ {
+ HasValue = true;
+ Value = value;
+
+ if (_other.HasValue)
+ {
+ var res = default(TResult);
+ try
+ {
+ res = _parent._parent._resultSelector(value, _other.Value);
+ }
+ catch (Exception ex)
+ {
+ _parent._observer.OnError(ex);
+ _parent.Dispose();
+ return;
+ }
+
+ _parent._observer.OnNext(res);
+ }
+ else if (_other.Done)
+ {
+ _parent._observer.OnCompleted();
+ _parent.Dispose();
+ return;
+ }
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ lock (_parent._gate)
+ {
+ _parent._observer.OnError(error);
+ _parent.Dispose();
+ }
+ }
+
+ public void OnCompleted()
+ {
+ lock (_parent._gate)
+ {
+ Done = true;
+
+ if (_other.Done)
+ {
+ _parent._observer.OnCompleted();
+ _parent.Dispose();
+ return;
+ }
+ else
+ {
+ _self.Dispose();
+ }
+ }
+ }
+ }
+
+ class S : IObserver<TSecond>
+ {
+ private readonly _ _parent;
+ private readonly IDisposable _self;
+ private F _other;
+
+ public S(_ parent, IDisposable self)
+ {
+ _parent = parent;
+ _self = self;
+ }
+
+ public F Other { set { _other = value; } }
+
+ public bool HasValue { get; private set; }
+ public TSecond Value { get; private set; }
+ public bool Done { get; private set; }
+
+ public void OnNext(TSecond value)
+ {
+ lock (_parent._gate)
+ {
+ HasValue = true;
+ Value = value;
+
+ if (_other.HasValue)
+ {
+ var res = default(TResult);
+ try
+ {
+ res = _parent._parent._resultSelector(_other.Value, value);
+ }
+ catch (Exception ex)
+ {
+ _parent._observer.OnError(ex);
+ _parent.Dispose();
+ return;
+ }
+
+ _parent._observer.OnNext(res);
+ }
+ else if (_other.Done)
+ {
+ _parent._observer.OnCompleted();
+ _parent.Dispose();
+ return;
+ }
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ lock (_parent._gate)
+ {
+ _parent._observer.OnError(error);
+ _parent.Dispose();
+ }
+ }
+
+ public void OnCompleted()
+ {
+ lock (_parent._gate)
+ {
+ Done = true;
+
+ if (_other.Done)
+ {
+ _parent._observer.OnCompleted();
+ _parent.Dispose();
+ return;
+ }
+ else
+ {
+ _self.Dispose();
+ }
+ }
+ }
+ }
+ }
+ }
+
+ #endregion
+
+ #region [3,16]-ary
+
+ /* The following code is generated by a tool checked in to $/.../Source/Tools/CodeGenerators. */
+
+ #region CombineLatest auto-generated code (6/10/2012 7:22:14 PM)
+
+ class CombineLatest<T1, T2, T3, TResult> : Producer<TResult>
+ {
+ private readonly IObservable<T1> _source1;
+ private readonly IObservable<T2> _source2;
+ private readonly IObservable<T3> _source3;
+ private readonly Func<T1, T2, T3, TResult> _resultSelector;
+
+ public CombineLatest(IObservable<T1> source1, IObservable<T2> source2, IObservable<T3> source3, Func<T1, T2, T3, TResult> resultSelector)
+ {
+ _source1 = source1;
+ _source2 = source2;
+ _source3 = source3;
+ _resultSelector = resultSelector;
+ }
+
+ protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+
+ class _ : CombineLatestSink<TResult>
+ {
+ private readonly CombineLatest<T1, T2, T3, TResult> _parent;
+
+ public _(CombineLatest<T1, T2, T3, TResult> parent, IObserver<TResult> observer, IDisposable cancel)
+ : base(3, observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ private CombineLatestObserver<T1> _observer1;
+ private CombineLatestObserver<T2> _observer2;
+ private CombineLatestObserver<T3> _observer3;
+
+ public IDisposable Run()
+ {
+ var subscriptions = new SingleAssignmentDisposable[3];
+ for (int i = 0; i < 3; i++)
+ subscriptions[i] = new SingleAssignmentDisposable();
+
+ _observer1 = new CombineLatestObserver<T1>(_gate, this, 0, subscriptions[0]);
+ _observer2 = new CombineLatestObserver<T2>(_gate, this, 1, subscriptions[1]);
+ _observer3 = new CombineLatestObserver<T3>(_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);
+
+ return new CompositeDisposable(subscriptions);
+ }
+
+ protected override TResult GetResult()
+ {
+ return _parent._resultSelector(_observer1.Value, _observer2.Value, _observer3.Value);
+ }
+ }
+ }
+
+ class CombineLatest<T1, T2, T3, T4, TResult> : Producer<TResult>
+ {
+ private readonly IObservable<T1> _source1;
+ private readonly IObservable<T2> _source2;
+ private readonly IObservable<T3> _source3;
+ private readonly IObservable<T4> _source4;
+ private readonly Func<T1, T2, T3, T4, TResult> _resultSelector;
+
+ public CombineLatest(IObservable<T1> source1, IObservable<T2> source2, IObservable<T3> source3, IObservable<T4> source4, Func<T1, T2, T3, T4, TResult> resultSelector)
+ {
+ _source1 = source1;
+ _source2 = source2;
+ _source3 = source3;
+ _source4 = source4;
+ _resultSelector = resultSelector;
+ }
+
+ protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+
+ class _ : CombineLatestSink<TResult>
+ {
+ private readonly CombineLatest<T1, T2, T3, T4, TResult> _parent;
+
+ public _(CombineLatest<T1, T2, T3, T4, TResult> parent, IObserver<TResult> observer, IDisposable cancel)
+ : base(4, observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ private CombineLatestObserver<T1> _observer1;
+ private CombineLatestObserver<T2> _observer2;
+ private CombineLatestObserver<T3> _observer3;
+ private CombineLatestObserver<T4> _observer4;
+
+ public IDisposable Run()
+ {
+ var subscriptions = new SingleAssignmentDisposable[4];
+ for (int i = 0; i < 4; i++)
+ subscriptions[i] = new SingleAssignmentDisposable();
+
+ _observer1 = new CombineLatestObserver<T1>(_gate, this, 0, subscriptions[0]);
+ _observer2 = new CombineLatestObserver<T2>(_gate, this, 1, subscriptions[1]);
+ _observer3 = new CombineLatestObserver<T3>(_gate, this, 2, subscriptions[2]);
+ _observer4 = new CombineLatestObserver<T4>(_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);
+
+ return new CompositeDisposable(subscriptions);
+ }
+
+ protected override TResult GetResult()
+ {
+ return _parent._resultSelector(_observer1.Value, _observer2.Value, _observer3.Value, _observer4.Value);
+ }
+ }
+ }
+
+#if !NO_LARGEARITY
+
+ class CombineLatest<T1, T2, T3, T4, T5, TResult> : Producer<TResult>
+ {
+ private readonly IObservable<T1> _source1;
+ private readonly IObservable<T2> _source2;
+ private readonly IObservable<T3> _source3;
+ private readonly IObservable<T4> _source4;
+ private readonly IObservable<T5> _source5;
+ private readonly Func<T1, T2, T3, T4, T5, TResult> _resultSelector;
+
+ public CombineLatest(IObservable<T1> source1, IObservable<T2> source2, IObservable<T3> source3, IObservable<T4> source4, IObservable<T5> source5, Func<T1, T2, T3, T4, T5, TResult> resultSelector)
+ {
+ _source1 = source1;
+ _source2 = source2;
+ _source3 = source3;
+ _source4 = source4;
+ _source5 = source5;
+ _resultSelector = resultSelector;
+ }
+
+ protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+
+ class _ : CombineLatestSink<TResult>
+ {
+ private readonly CombineLatest<T1, T2, T3, T4, T5, TResult> _parent;
+
+ public _(CombineLatest<T1, T2, T3, T4, T5, TResult> parent, IObserver<TResult> observer, IDisposable cancel)
+ : base(5, observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ private CombineLatestObserver<T1> _observer1;
+ private CombineLatestObserver<T2> _observer2;
+ private CombineLatestObserver<T3> _observer3;
+ private CombineLatestObserver<T4> _observer4;
+ private CombineLatestObserver<T5> _observer5;
+
+ public IDisposable Run()
+ {
+ var subscriptions = new SingleAssignmentDisposable[5];
+ for (int i = 0; i < 5; i++)
+ subscriptions[i] = new SingleAssignmentDisposable();
+
+ _observer1 = new CombineLatestObserver<T1>(_gate, this, 0, subscriptions[0]);
+ _observer2 = new CombineLatestObserver<T2>(_gate, this, 1, subscriptions[1]);
+ _observer3 = new CombineLatestObserver<T3>(_gate, this, 2, subscriptions[2]);
+ _observer4 = new CombineLatestObserver<T4>(_gate, this, 3, subscriptions[3]);
+ _observer5 = new CombineLatestObserver<T5>(_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);
+
+ return new CompositeDisposable(subscriptions);
+ }
+
+ protected override TResult GetResult()
+ {
+ return _parent._resultSelector(_observer1.Value, _observer2.Value, _observer3.Value, _observer4.Value, _observer5.Value);
+ }
+ }
+ }
+
+ class CombineLatest<T1, T2, T3, T4, T5, T6, TResult> : Producer<TResult>
+ {
+ private readonly IObservable<T1> _source1;
+ private readonly IObservable<T2> _source2;
+ private readonly IObservable<T3> _source3;
+ private readonly IObservable<T4> _source4;
+ private readonly IObservable<T5> _source5;
+ private readonly IObservable<T6> _source6;
+ private readonly Func<T1, T2, T3, T4, T5, T6, TResult> _resultSelector;
+
+ public CombineLatest(IObservable<T1> source1, IObservable<T2> source2, IObservable<T3> source3, IObservable<T4> source4, IObservable<T5> source5, IObservable<T6> source6, Func<T1, T2, T3, T4, T5, T6, TResult> resultSelector)
+ {
+ _source1 = source1;
+ _source2 = source2;
+ _source3 = source3;
+ _source4 = source4;
+ _source5 = source5;
+ _source6 = source6;
+ _resultSelector = resultSelector;
+ }
+
+ protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+
+ class _ : CombineLatestSink<TResult>
+ {
+ private readonly CombineLatest<T1, T2, T3, T4, T5, T6, TResult> _parent;
+
+ public _(CombineLatest<T1, T2, T3, T4, T5, T6, TResult> parent, IObserver<TResult> observer, IDisposable cancel)
+ : base(6, observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ private CombineLatestObserver<T1> _observer1;
+ private CombineLatestObserver<T2> _observer2;
+ private CombineLatestObserver<T3> _observer3;
+ private CombineLatestObserver<T4> _observer4;
+ private CombineLatestObserver<T5> _observer5;
+ private CombineLatestObserver<T6> _observer6;
+
+ public IDisposable Run()
+ {
+ var subscriptions = new SingleAssignmentDisposable[6];
+ for (int i = 0; i < 6; i++)
+ subscriptions[i] = new SingleAssignmentDisposable();
+
+ _observer1 = new CombineLatestObserver<T1>(_gate, this, 0, subscriptions[0]);
+ _observer2 = new CombineLatestObserver<T2>(_gate, this, 1, subscriptions[1]);
+ _observer3 = new CombineLatestObserver<T3>(_gate, this, 2, subscriptions[2]);
+ _observer4 = new CombineLatestObserver<T4>(_gate, this, 3, subscriptions[3]);
+ _observer5 = new CombineLatestObserver<T5>(_gate, this, 4, subscriptions[4]);
+ _observer6 = new CombineLatestObserver<T6>(_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);
+
+ return new CompositeDisposable(subscriptions);
+ }
+
+ protected override TResult GetResult()
+ {
+ return _parent._resultSelector(_observer1.Value, _observer2.Value, _observer3.Value, _observer4.Value, _observer5.Value, _observer6.Value);
+ }
+ }
+ }
+
+ class CombineLatest<T1, T2, T3, T4, T5, T6, T7, TResult> : Producer<TResult>
+ {
+ private readonly IObservable<T1> _source1;
+ private readonly IObservable<T2> _source2;
+ private readonly IObservable<T3> _source3;
+ private readonly IObservable<T4> _source4;
+ private readonly IObservable<T5> _source5;
+ private readonly IObservable<T6> _source6;
+ private readonly IObservable<T7> _source7;
+ private readonly Func<T1, T2, T3, T4, T5, T6, T7, TResult> _resultSelector;
+
+ public CombineLatest(IObservable<T1> source1, IObservable<T2> source2, IObservable<T3> source3, IObservable<T4> source4, IObservable<T5> source5, IObservable<T6> source6, IObservable<T7> source7, Func<T1, T2, T3, T4, T5, T6, T7, TResult> resultSelector)
+ {
+ _source1 = source1;
+ _source2 = source2;
+ _source3 = source3;
+ _source4 = source4;
+ _source5 = source5;
+ _source6 = source6;
+ _source7 = source7;
+ _resultSelector = resultSelector;
+ }
+
+ protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+
+ class _ : CombineLatestSink<TResult>
+ {
+ private readonly CombineLatest<T1, T2, T3, T4, T5, T6, T7, TResult> _parent;
+
+ public _(CombineLatest<T1, T2, T3, T4, T5, T6, T7, TResult> parent, IObserver<TResult> observer, IDisposable cancel)
+ : base(7, observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ private CombineLatestObserver<T1> _observer1;
+ private CombineLatestObserver<T2> _observer2;
+ private CombineLatestObserver<T3> _observer3;
+ private CombineLatestObserver<T4> _observer4;
+ private CombineLatestObserver<T5> _observer5;
+ private CombineLatestObserver<T6> _observer6;
+ private CombineLatestObserver<T7> _observer7;
+
+ public IDisposable Run()
+ {
+ var subscriptions = new SingleAssignmentDisposable[7];
+ for (int i = 0; i < 7; i++)
+ subscriptions[i] = new SingleAssignmentDisposable();
+
+ _observer1 = new CombineLatestObserver<T1>(_gate, this, 0, subscriptions[0]);
+ _observer2 = new CombineLatestObserver<T2>(_gate, this, 1, subscriptions[1]);
+ _observer3 = new CombineLatestObserver<T3>(_gate, this, 2, subscriptions[2]);
+ _observer4 = new CombineLatestObserver<T4>(_gate, this, 3, subscriptions[3]);
+ _observer5 = new CombineLatestObserver<T5>(_gate, this, 4, subscriptions[4]);
+ _observer6 = new CombineLatestObserver<T6>(_gate, this, 5, subscriptions[5]);
+ _observer7 = new CombineLatestObserver<T7>(_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);
+
+ return new CompositeDisposable(subscriptions);
+ }
+
+ protected override TResult GetResult()
+ {
+ return _parent._resultSelector(_observer1.Value, _observer2.Value, _observer3.Value, _observer4.Value, _observer5.Value, _observer6.Value, _observer7.Value);
+ }
+ }
+ }
+
+ class CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, TResult> : Producer<TResult>
+ {
+ private readonly IObservable<T1> _source1;
+ private readonly IObservable<T2> _source2;
+ private readonly IObservable<T3> _source3;
+ private readonly IObservable<T4> _source4;
+ private readonly IObservable<T5> _source5;
+ private readonly IObservable<T6> _source6;
+ private readonly IObservable<T7> _source7;
+ private readonly IObservable<T8> _source8;
+ private readonly Func<T1, T2, T3, T4, T5, T6, T7, T8, TResult> _resultSelector;
+
+ public CombineLatest(IObservable<T1> source1, IObservable<T2> source2, IObservable<T3> source3, IObservable<T4> source4, IObservable<T5> source5, IObservable<T6> source6, IObservable<T7> source7, IObservable<T8> source8, Func<T1, T2, T3, T4, T5, T6, T7, T8, TResult> resultSelector)
+ {
+ _source1 = source1;
+ _source2 = source2;
+ _source3 = source3;
+ _source4 = source4;
+ _source5 = source5;
+ _source6 = source6;
+ _source7 = source7;
+ _source8 = source8;
+ _resultSelector = resultSelector;
+ }
+
+ protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+
+ class _ : CombineLatestSink<TResult>
+ {
+ private readonly CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, TResult> _parent;
+
+ public _(CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, TResult> parent, IObserver<TResult> observer, IDisposable cancel)
+ : base(8, observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ private CombineLatestObserver<T1> _observer1;
+ private CombineLatestObserver<T2> _observer2;
+ private CombineLatestObserver<T3> _observer3;
+ private CombineLatestObserver<T4> _observer4;
+ private CombineLatestObserver<T5> _observer5;
+ private CombineLatestObserver<T6> _observer6;
+ private CombineLatestObserver<T7> _observer7;
+ private CombineLatestObserver<T8> _observer8;
+
+ public IDisposable Run()
+ {
+ var subscriptions = new SingleAssignmentDisposable[8];
+ for (int i = 0; i < 8; i++)
+ subscriptions[i] = new SingleAssignmentDisposable();
+
+ _observer1 = new CombineLatestObserver<T1>(_gate, this, 0, subscriptions[0]);
+ _observer2 = new CombineLatestObserver<T2>(_gate, this, 1, subscriptions[1]);
+ _observer3 = new CombineLatestObserver<T3>(_gate, this, 2, subscriptions[2]);
+ _observer4 = new CombineLatestObserver<T4>(_gate, this, 3, subscriptions[3]);
+ _observer5 = new CombineLatestObserver<T5>(_gate, this, 4, subscriptions[4]);
+ _observer6 = new CombineLatestObserver<T6>(_gate, this, 5, subscriptions[5]);
+ _observer7 = new CombineLatestObserver<T7>(_gate, this, 6, subscriptions[6]);
+ _observer8 = new CombineLatestObserver<T8>(_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);
+
+ return new CompositeDisposable(subscriptions);
+ }
+
+ protected override TResult GetResult()
+ {
+ return _parent._resultSelector(_observer1.Value, _observer2.Value, _observer3.Value, _observer4.Value, _observer5.Value, _observer6.Value, _observer7.Value, _observer8.Value);
+ }
+ }
+ }
+
+ class CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, TResult> : Producer<TResult>
+ {
+ private readonly IObservable<T1> _source1;
+ private readonly IObservable<T2> _source2;
+ private readonly IObservable<T3> _source3;
+ private readonly IObservable<T4> _source4;
+ private readonly IObservable<T5> _source5;
+ private readonly IObservable<T6> _source6;
+ private readonly IObservable<T7> _source7;
+ private readonly IObservable<T8> _source8;
+ private readonly IObservable<T9> _source9;
+ private readonly Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, TResult> _resultSelector;
+
+ public CombineLatest(IObservable<T1> source1, IObservable<T2> source2, IObservable<T3> source3, IObservable<T4> source4, IObservable<T5> source5, IObservable<T6> source6, IObservable<T7> source7, IObservable<T8> source8, IObservable<T9> source9, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, TResult> resultSelector)
+ {
+ _source1 = source1;
+ _source2 = source2;
+ _source3 = source3;
+ _source4 = source4;
+ _source5 = source5;
+ _source6 = source6;
+ _source7 = source7;
+ _source8 = source8;
+ _source9 = source9;
+ _resultSelector = resultSelector;
+ }
+
+ protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+
+ class _ : CombineLatestSink<TResult>
+ {
+ private readonly CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, TResult> _parent;
+
+ public _(CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, TResult> parent, IObserver<TResult> observer, IDisposable cancel)
+ : base(9, observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ private CombineLatestObserver<T1> _observer1;
+ private CombineLatestObserver<T2> _observer2;
+ private CombineLatestObserver<T3> _observer3;
+ private CombineLatestObserver<T4> _observer4;
+ private CombineLatestObserver<T5> _observer5;
+ private CombineLatestObserver<T6> _observer6;
+ private CombineLatestObserver<T7> _observer7;
+ private CombineLatestObserver<T8> _observer8;
+ private CombineLatestObserver<T9> _observer9;
+
+ public IDisposable Run()
+ {
+ var subscriptions = new SingleAssignmentDisposable[9];
+ for (int i = 0; i < 9; i++)
+ subscriptions[i] = new SingleAssignmentDisposable();
+
+ _observer1 = new CombineLatestObserver<T1>(_gate, this, 0, subscriptions[0]);
+ _observer2 = new CombineLatestObserver<T2>(_gate, this, 1, subscriptions[1]);
+ _observer3 = new CombineLatestObserver<T3>(_gate, this, 2, subscriptions[2]);
+ _observer4 = new CombineLatestObserver<T4>(_gate, this, 3, subscriptions[3]);
+ _observer5 = new CombineLatestObserver<T5>(_gate, this, 4, subscriptions[4]);
+ _observer6 = new CombineLatestObserver<T6>(_gate, this, 5, subscriptions[5]);
+ _observer7 = new CombineLatestObserver<T7>(_gate, this, 6, subscriptions[6]);
+ _observer8 = new CombineLatestObserver<T8>(_gate, this, 7, subscriptions[7]);
+ _observer9 = new CombineLatestObserver<T9>(_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);
+
+ return new CompositeDisposable(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);
+ }
+ }
+ }
+
+ class CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TResult> : Producer<TResult>
+ {
+ private readonly IObservable<T1> _source1;
+ private readonly IObservable<T2> _source2;
+ private readonly IObservable<T3> _source3;
+ private readonly IObservable<T4> _source4;
+ private readonly IObservable<T5> _source5;
+ private readonly IObservable<T6> _source6;
+ private readonly IObservable<T7> _source7;
+ private readonly IObservable<T8> _source8;
+ private readonly IObservable<T9> _source9;
+ private readonly IObservable<T10> _source10;
+ private readonly Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TResult> _resultSelector;
+
+ public CombineLatest(IObservable<T1> source1, IObservable<T2> source2, IObservable<T3> source3, IObservable<T4> source4, IObservable<T5> source5, IObservable<T6> source6, IObservable<T7> source7, IObservable<T8> source8, IObservable<T9> source9, IObservable<T10> source10, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TResult> resultSelector)
+ {
+ _source1 = source1;
+ _source2 = source2;
+ _source3 = source3;
+ _source4 = source4;
+ _source5 = source5;
+ _source6 = source6;
+ _source7 = source7;
+ _source8 = source8;
+ _source9 = source9;
+ _source10 = source10;
+ _resultSelector = resultSelector;
+ }
+
+ protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+
+ class _ : CombineLatestSink<TResult>
+ {
+ private readonly CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TResult> _parent;
+
+ public _(CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TResult> parent, IObserver<TResult> observer, IDisposable cancel)
+ : base(10, observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ private CombineLatestObserver<T1> _observer1;
+ private CombineLatestObserver<T2> _observer2;
+ private CombineLatestObserver<T3> _observer3;
+ private CombineLatestObserver<T4> _observer4;
+ private CombineLatestObserver<T5> _observer5;
+ private CombineLatestObserver<T6> _observer6;
+ private CombineLatestObserver<T7> _observer7;
+ private CombineLatestObserver<T8> _observer8;
+ private CombineLatestObserver<T9> _observer9;
+ private CombineLatestObserver<T10> _observer10;
+
+ public IDisposable Run()
+ {
+ var subscriptions = new SingleAssignmentDisposable[10];
+ for (int i = 0; i < 10; i++)
+ subscriptions[i] = new SingleAssignmentDisposable();
+
+ _observer1 = new CombineLatestObserver<T1>(_gate, this, 0, subscriptions[0]);
+ _observer2 = new CombineLatestObserver<T2>(_gate, this, 1, subscriptions[1]);
+ _observer3 = new CombineLatestObserver<T3>(_gate, this, 2, subscriptions[2]);
+ _observer4 = new CombineLatestObserver<T4>(_gate, this, 3, subscriptions[3]);
+ _observer5 = new CombineLatestObserver<T5>(_gate, this, 4, subscriptions[4]);
+ _observer6 = new CombineLatestObserver<T6>(_gate, this, 5, subscriptions[5]);
+ _observer7 = new CombineLatestObserver<T7>(_gate, this, 6, subscriptions[6]);
+ _observer8 = new CombineLatestObserver<T8>(_gate, this, 7, subscriptions[7]);
+ _observer9 = new CombineLatestObserver<T9>(_gate, this, 8, subscriptions[8]);
+ _observer10 = new CombineLatestObserver<T10>(_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);
+
+ return new CompositeDisposable(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);
+ }
+ }
+ }
+
+ class CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TResult> : Producer<TResult>
+ {
+ private readonly IObservable<T1> _source1;
+ private readonly IObservable<T2> _source2;
+ private readonly IObservable<T3> _source3;
+ private readonly IObservable<T4> _source4;
+ private readonly IObservable<T5> _source5;
+ private readonly IObservable<T6> _source6;
+ private readonly IObservable<T7> _source7;
+ private readonly IObservable<T8> _source8;
+ private readonly IObservable<T9> _source9;
+ private readonly IObservable<T10> _source10;
+ private readonly IObservable<T11> _source11;
+ private readonly Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TResult> _resultSelector;
+
+ public CombineLatest(IObservable<T1> source1, IObservable<T2> source2, IObservable<T3> source3, IObservable<T4> source4, IObservable<T5> source5, IObservable<T6> source6, IObservable<T7> source7, IObservable<T8> source8, IObservable<T9> source9, IObservable<T10> source10, IObservable<T11> source11, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TResult> resultSelector)
+ {
+ _source1 = source1;
+ _source2 = source2;
+ _source3 = source3;
+ _source4 = source4;
+ _source5 = source5;
+ _source6 = source6;
+ _source7 = source7;
+ _source8 = source8;
+ _source9 = source9;
+ _source10 = source10;
+ _source11 = source11;
+ _resultSelector = resultSelector;
+ }
+
+ protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+
+ class _ : CombineLatestSink<TResult>
+ {
+ private readonly CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TResult> _parent;
+
+ public _(CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TResult> parent, IObserver<TResult> observer, IDisposable cancel)
+ : base(11, observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ private CombineLatestObserver<T1> _observer1;
+ private CombineLatestObserver<T2> _observer2;
+ private CombineLatestObserver<T3> _observer3;
+ private CombineLatestObserver<T4> _observer4;
+ private CombineLatestObserver<T5> _observer5;
+ private CombineLatestObserver<T6> _observer6;
+ private CombineLatestObserver<T7> _observer7;
+ private CombineLatestObserver<T8> _observer8;
+ private CombineLatestObserver<T9> _observer9;
+ private CombineLatestObserver<T10> _observer10;
+ private CombineLatestObserver<T11> _observer11;
+
+ public IDisposable Run()
+ {
+ var subscriptions = new SingleAssignmentDisposable[11];
+ for (int i = 0; i < 11; i++)
+ subscriptions[i] = new SingleAssignmentDisposable();
+
+ _observer1 = new CombineLatestObserver<T1>(_gate, this, 0, subscriptions[0]);
+ _observer2 = new CombineLatestObserver<T2>(_gate, this, 1, subscriptions[1]);
+ _observer3 = new CombineLatestObserver<T3>(_gate, this, 2, subscriptions[2]);
+ _observer4 = new CombineLatestObserver<T4>(_gate, this, 3, subscriptions[3]);
+ _observer5 = new CombineLatestObserver<T5>(_gate, this, 4, subscriptions[4]);
+ _observer6 = new CombineLatestObserver<T6>(_gate, this, 5, subscriptions[5]);
+ _observer7 = new CombineLatestObserver<T7>(_gate, this, 6, subscriptions[6]);
+ _observer8 = new CombineLatestObserver<T8>(_gate, this, 7, subscriptions[7]);
+ _observer9 = new CombineLatestObserver<T9>(_gate, this, 8, subscriptions[8]);
+ _observer10 = new CombineLatestObserver<T10>(_gate, this, 9, subscriptions[9]);
+ _observer11 = new CombineLatestObserver<T11>(_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);
+
+ return new CompositeDisposable(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);
+ }
+ }
+ }
+
+ class CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TResult> : Producer<TResult>
+ {
+ private readonly IObservable<T1> _source1;
+ private readonly IObservable<T2> _source2;
+ private readonly IObservable<T3> _source3;
+ private readonly IObservable<T4> _source4;
+ private readonly IObservable<T5> _source5;
+ private readonly IObservable<T6> _source6;
+ private readonly IObservable<T7> _source7;
+ private readonly IObservable<T8> _source8;
+ private readonly IObservable<T9> _source9;
+ private readonly IObservable<T10> _source10;
+ private readonly IObservable<T11> _source11;
+ private readonly IObservable<T12> _source12;
+ private readonly Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TResult> _resultSelector;
+
+ public CombineLatest(IObservable<T1> source1, IObservable<T2> source2, IObservable<T3> source3, IObservable<T4> source4, IObservable<T5> source5, IObservable<T6> source6, IObservable<T7> source7, IObservable<T8> source8, IObservable<T9> source9, IObservable<T10> source10, IObservable<T11> source11, IObservable<T12> source12, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TResult> resultSelector)
+ {
+ _source1 = source1;
+ _source2 = source2;
+ _source3 = source3;
+ _source4 = source4;
+ _source5 = source5;
+ _source6 = source6;
+ _source7 = source7;
+ _source8 = source8;
+ _source9 = source9;
+ _source10 = source10;
+ _source11 = source11;
+ _source12 = source12;
+ _resultSelector = resultSelector;
+ }
+
+ protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+
+ class _ : CombineLatestSink<TResult>
+ {
+ private readonly CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TResult> _parent;
+
+ public _(CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TResult> parent, IObserver<TResult> observer, IDisposable cancel)
+ : base(12, observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ private CombineLatestObserver<T1> _observer1;
+ private CombineLatestObserver<T2> _observer2;
+ private CombineLatestObserver<T3> _observer3;
+ private CombineLatestObserver<T4> _observer4;
+ private CombineLatestObserver<T5> _observer5;
+ private CombineLatestObserver<T6> _observer6;
+ private CombineLatestObserver<T7> _observer7;
+ private CombineLatestObserver<T8> _observer8;
+ private CombineLatestObserver<T9> _observer9;
+ private CombineLatestObserver<T10> _observer10;
+ private CombineLatestObserver<T11> _observer11;
+ private CombineLatestObserver<T12> _observer12;
+
+ public IDisposable Run()
+ {
+ var subscriptions = new SingleAssignmentDisposable[12];
+ for (int i = 0; i < 12; i++)
+ subscriptions[i] = new SingleAssignmentDisposable();
+
+ _observer1 = new CombineLatestObserver<T1>(_gate, this, 0, subscriptions[0]);
+ _observer2 = new CombineLatestObserver<T2>(_gate, this, 1, subscriptions[1]);
+ _observer3 = new CombineLatestObserver<T3>(_gate, this, 2, subscriptions[2]);
+ _observer4 = new CombineLatestObserver<T4>(_gate, this, 3, subscriptions[3]);
+ _observer5 = new CombineLatestObserver<T5>(_gate, this, 4, subscriptions[4]);
+ _observer6 = new CombineLatestObserver<T6>(_gate, this, 5, subscriptions[5]);
+ _observer7 = new CombineLatestObserver<T7>(_gate, this, 6, subscriptions[6]);
+ _observer8 = new CombineLatestObserver<T8>(_gate, this, 7, subscriptions[7]);
+ _observer9 = new CombineLatestObserver<T9>(_gate, this, 8, subscriptions[8]);
+ _observer10 = new CombineLatestObserver<T10>(_gate, this, 9, subscriptions[9]);
+ _observer11 = new CombineLatestObserver<T11>(_gate, this, 10, subscriptions[10]);
+ _observer12 = new CombineLatestObserver<T12>(_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);
+
+ return new CompositeDisposable(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);
+ }
+ }
+ }
+
+ class CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TResult> : Producer<TResult>
+ {
+ private readonly IObservable<T1> _source1;
+ private readonly IObservable<T2> _source2;
+ private readonly IObservable<T3> _source3;
+ private readonly IObservable<T4> _source4;
+ private readonly IObservable<T5> _source5;
+ private readonly IObservable<T6> _source6;
+ private readonly IObservable<T7> _source7;
+ private readonly IObservable<T8> _source8;
+ private readonly IObservable<T9> _source9;
+ private readonly IObservable<T10> _source10;
+ private readonly IObservable<T11> _source11;
+ private readonly IObservable<T12> _source12;
+ private readonly IObservable<T13> _source13;
+ private readonly Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TResult> _resultSelector;
+
+ public CombineLatest(IObservable<T1> source1, IObservable<T2> source2, IObservable<T3> source3, IObservable<T4> source4, IObservable<T5> source5, IObservable<T6> source6, IObservable<T7> source7, IObservable<T8> source8, IObservable<T9> source9, IObservable<T10> source10, IObservable<T11> source11, IObservable<T12> source12, IObservable<T13> source13, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TResult> resultSelector)
+ {
+ _source1 = source1;
+ _source2 = source2;
+ _source3 = source3;
+ _source4 = source4;
+ _source5 = source5;
+ _source6 = source6;
+ _source7 = source7;
+ _source8 = source8;
+ _source9 = source9;
+ _source10 = source10;
+ _source11 = source11;
+ _source12 = source12;
+ _source13 = source13;
+ _resultSelector = resultSelector;
+ }
+
+ protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+
+ class _ : CombineLatestSink<TResult>
+ {
+ private readonly CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TResult> _parent;
+
+ public _(CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TResult> parent, IObserver<TResult> observer, IDisposable cancel)
+ : base(13, observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ private CombineLatestObserver<T1> _observer1;
+ private CombineLatestObserver<T2> _observer2;
+ private CombineLatestObserver<T3> _observer3;
+ private CombineLatestObserver<T4> _observer4;
+ private CombineLatestObserver<T5> _observer5;
+ private CombineLatestObserver<T6> _observer6;
+ private CombineLatestObserver<T7> _observer7;
+ private CombineLatestObserver<T8> _observer8;
+ private CombineLatestObserver<T9> _observer9;
+ private CombineLatestObserver<T10> _observer10;
+ private CombineLatestObserver<T11> _observer11;
+ private CombineLatestObserver<T12> _observer12;
+ private CombineLatestObserver<T13> _observer13;
+
+ public IDisposable Run()
+ {
+ var subscriptions = new SingleAssignmentDisposable[13];
+ for (int i = 0; i < 13; i++)
+ subscriptions[i] = new SingleAssignmentDisposable();
+
+ _observer1 = new CombineLatestObserver<T1>(_gate, this, 0, subscriptions[0]);
+ _observer2 = new CombineLatestObserver<T2>(_gate, this, 1, subscriptions[1]);
+ _observer3 = new CombineLatestObserver<T3>(_gate, this, 2, subscriptions[2]);
+ _observer4 = new CombineLatestObserver<T4>(_gate, this, 3, subscriptions[3]);
+ _observer5 = new CombineLatestObserver<T5>(_gate, this, 4, subscriptions[4]);
+ _observer6 = new CombineLatestObserver<T6>(_gate, this, 5, subscriptions[5]);
+ _observer7 = new CombineLatestObserver<T7>(_gate, this, 6, subscriptions[6]);
+ _observer8 = new CombineLatestObserver<T8>(_gate, this, 7, subscriptions[7]);
+ _observer9 = new CombineLatestObserver<T9>(_gate, this, 8, subscriptions[8]);
+ _observer10 = new CombineLatestObserver<T10>(_gate, this, 9, subscriptions[9]);
+ _observer11 = new CombineLatestObserver<T11>(_gate, this, 10, subscriptions[10]);
+ _observer12 = new CombineLatestObserver<T12>(_gate, this, 11, subscriptions[11]);
+ _observer13 = new CombineLatestObserver<T13>(_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);
+
+ return new CompositeDisposable(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);
+ }
+ }
+ }
+
+ class CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TResult> : Producer<TResult>
+ {
+ private readonly IObservable<T1> _source1;
+ private readonly IObservable<T2> _source2;
+ private readonly IObservable<T3> _source3;
+ private readonly IObservable<T4> _source4;
+ private readonly IObservable<T5> _source5;
+ private readonly IObservable<T6> _source6;
+ private readonly IObservable<T7> _source7;
+ private readonly IObservable<T8> _source8;
+ private readonly IObservable<T9> _source9;
+ private readonly IObservable<T10> _source10;
+ private readonly IObservable<T11> _source11;
+ private readonly IObservable<T12> _source12;
+ private readonly IObservable<T13> _source13;
+ private readonly IObservable<T14> _source14;
+ private readonly Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TResult> _resultSelector;
+
+ public CombineLatest(IObservable<T1> source1, IObservable<T2> source2, IObservable<T3> source3, IObservable<T4> source4, IObservable<T5> source5, IObservable<T6> source6, IObservable<T7> source7, IObservable<T8> source8, IObservable<T9> source9, IObservable<T10> source10, IObservable<T11> source11, IObservable<T12> source12, IObservable<T13> source13, IObservable<T14> source14, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TResult> resultSelector)
+ {
+ _source1 = source1;
+ _source2 = source2;
+ _source3 = source3;
+ _source4 = source4;
+ _source5 = source5;
+ _source6 = source6;
+ _source7 = source7;
+ _source8 = source8;
+ _source9 = source9;
+ _source10 = source10;
+ _source11 = source11;
+ _source12 = source12;
+ _source13 = source13;
+ _source14 = source14;
+ _resultSelector = resultSelector;
+ }
+
+ protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+
+ class _ : CombineLatestSink<TResult>
+ {
+ private readonly CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TResult> _parent;
+
+ public _(CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TResult> parent, IObserver<TResult> observer, IDisposable cancel)
+ : base(14, observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ private CombineLatestObserver<T1> _observer1;
+ private CombineLatestObserver<T2> _observer2;
+ private CombineLatestObserver<T3> _observer3;
+ private CombineLatestObserver<T4> _observer4;
+ private CombineLatestObserver<T5> _observer5;
+ private CombineLatestObserver<T6> _observer6;
+ private CombineLatestObserver<T7> _observer7;
+ private CombineLatestObserver<T8> _observer8;
+ private CombineLatestObserver<T9> _observer9;
+ private CombineLatestObserver<T10> _observer10;
+ private CombineLatestObserver<T11> _observer11;
+ private CombineLatestObserver<T12> _observer12;
+ private CombineLatestObserver<T13> _observer13;
+ private CombineLatestObserver<T14> _observer14;
+
+ public IDisposable Run()
+ {
+ var subscriptions = new SingleAssignmentDisposable[14];
+ for (int i = 0; i < 14; i++)
+ subscriptions[i] = new SingleAssignmentDisposable();
+
+ _observer1 = new CombineLatestObserver<T1>(_gate, this, 0, subscriptions[0]);
+ _observer2 = new CombineLatestObserver<T2>(_gate, this, 1, subscriptions[1]);
+ _observer3 = new CombineLatestObserver<T3>(_gate, this, 2, subscriptions[2]);
+ _observer4 = new CombineLatestObserver<T4>(_gate, this, 3, subscriptions[3]);
+ _observer5 = new CombineLatestObserver<T5>(_gate, this, 4, subscriptions[4]);
+ _observer6 = new CombineLatestObserver<T6>(_gate, this, 5, subscriptions[5]);
+ _observer7 = new CombineLatestObserver<T7>(_gate, this, 6, subscriptions[6]);
+ _observer8 = new CombineLatestObserver<T8>(_gate, this, 7, subscriptions[7]);
+ _observer9 = new CombineLatestObserver<T9>(_gate, this, 8, subscriptions[8]);
+ _observer10 = new CombineLatestObserver<T10>(_gate, this, 9, subscriptions[9]);
+ _observer11 = new CombineLatestObserver<T11>(_gate, this, 10, subscriptions[10]);
+ _observer12 = new CombineLatestObserver<T12>(_gate, this, 11, subscriptions[11]);
+ _observer13 = new CombineLatestObserver<T13>(_gate, this, 12, subscriptions[12]);
+ _observer14 = new CombineLatestObserver<T14>(_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);
+
+ return new CompositeDisposable(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);
+ }
+ }
+ }
+
+ class CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TResult> : Producer<TResult>
+ {
+ private readonly IObservable<T1> _source1;
+ private readonly IObservable<T2> _source2;
+ private readonly IObservable<T3> _source3;
+ private readonly IObservable<T4> _source4;
+ private readonly IObservable<T5> _source5;
+ private readonly IObservable<T6> _source6;
+ private readonly IObservable<T7> _source7;
+ private readonly IObservable<T8> _source8;
+ private readonly IObservable<T9> _source9;
+ private readonly IObservable<T10> _source10;
+ private readonly IObservable<T11> _source11;
+ private readonly IObservable<T12> _source12;
+ private readonly IObservable<T13> _source13;
+ private readonly IObservable<T14> _source14;
+ private readonly IObservable<T15> _source15;
+ private readonly Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TResult> _resultSelector;
+
+ public CombineLatest(IObservable<T1> source1, IObservable<T2> source2, IObservable<T3> source3, IObservable<T4> source4, IObservable<T5> source5, IObservable<T6> source6, IObservable<T7> source7, IObservable<T8> source8, IObservable<T9> source9, IObservable<T10> source10, IObservable<T11> source11, IObservable<T12> source12, IObservable<T13> source13, IObservable<T14> source14, IObservable<T15> source15, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TResult> resultSelector)
+ {
+ _source1 = source1;
+ _source2 = source2;
+ _source3 = source3;
+ _source4 = source4;
+ _source5 = source5;
+ _source6 = source6;
+ _source7 = source7;
+ _source8 = source8;
+ _source9 = source9;
+ _source10 = source10;
+ _source11 = source11;
+ _source12 = source12;
+ _source13 = source13;
+ _source14 = source14;
+ _source15 = source15;
+ _resultSelector = resultSelector;
+ }
+
+ protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+
+ class _ : CombineLatestSink<TResult>
+ {
+ private readonly CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TResult> _parent;
+
+ public _(CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TResult> parent, IObserver<TResult> observer, IDisposable cancel)
+ : base(15, observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ private CombineLatestObserver<T1> _observer1;
+ private CombineLatestObserver<T2> _observer2;
+ private CombineLatestObserver<T3> _observer3;
+ private CombineLatestObserver<T4> _observer4;
+ private CombineLatestObserver<T5> _observer5;
+ private CombineLatestObserver<T6> _observer6;
+ private CombineLatestObserver<T7> _observer7;
+ private CombineLatestObserver<T8> _observer8;
+ private CombineLatestObserver<T9> _observer9;
+ private CombineLatestObserver<T10> _observer10;
+ private CombineLatestObserver<T11> _observer11;
+ private CombineLatestObserver<T12> _observer12;
+ private CombineLatestObserver<T13> _observer13;
+ private CombineLatestObserver<T14> _observer14;
+ private CombineLatestObserver<T15> _observer15;
+
+ public IDisposable Run()
+ {
+ var subscriptions = new SingleAssignmentDisposable[15];
+ for (int i = 0; i < 15; i++)
+ subscriptions[i] = new SingleAssignmentDisposable();
+
+ _observer1 = new CombineLatestObserver<T1>(_gate, this, 0, subscriptions[0]);
+ _observer2 = new CombineLatestObserver<T2>(_gate, this, 1, subscriptions[1]);
+ _observer3 = new CombineLatestObserver<T3>(_gate, this, 2, subscriptions[2]);
+ _observer4 = new CombineLatestObserver<T4>(_gate, this, 3, subscriptions[3]);
+ _observer5 = new CombineLatestObserver<T5>(_gate, this, 4, subscriptions[4]);
+ _observer6 = new CombineLatestObserver<T6>(_gate, this, 5, subscriptions[5]);
+ _observer7 = new CombineLatestObserver<T7>(_gate, this, 6, subscriptions[6]);
+ _observer8 = new CombineLatestObserver<T8>(_gate, this, 7, subscriptions[7]);
+ _observer9 = new CombineLatestObserver<T9>(_gate, this, 8, subscriptions[8]);
+ _observer10 = new CombineLatestObserver<T10>(_gate, this, 9, subscriptions[9]);
+ _observer11 = new CombineLatestObserver<T11>(_gate, this, 10, subscriptions[10]);
+ _observer12 = new CombineLatestObserver<T12>(_gate, this, 11, subscriptions[11]);
+ _observer13 = new CombineLatestObserver<T13>(_gate, this, 12, subscriptions[12]);
+ _observer14 = new CombineLatestObserver<T14>(_gate, this, 13, subscriptions[13]);
+ _observer15 = new CombineLatestObserver<T15>(_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);
+
+ return new CompositeDisposable(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);
+ }
+ }
+ }
+
+ class CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, TResult> : Producer<TResult>
+ {
+ private readonly IObservable<T1> _source1;
+ private readonly IObservable<T2> _source2;
+ private readonly IObservable<T3> _source3;
+ private readonly IObservable<T4> _source4;
+ private readonly IObservable<T5> _source5;
+ private readonly IObservable<T6> _source6;
+ private readonly IObservable<T7> _source7;
+ private readonly IObservable<T8> _source8;
+ private readonly IObservable<T9> _source9;
+ private readonly IObservable<T10> _source10;
+ private readonly IObservable<T11> _source11;
+ private readonly IObservable<T12> _source12;
+ private readonly IObservable<T13> _source13;
+ private readonly IObservable<T14> _source14;
+ private readonly IObservable<T15> _source15;
+ private readonly IObservable<T16> _source16;
+ private readonly Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, TResult> _resultSelector;
+
+ public CombineLatest(IObservable<T1> source1, IObservable<T2> source2, IObservable<T3> source3, IObservable<T4> source4, IObservable<T5> source5, IObservable<T6> source6, IObservable<T7> source7, IObservable<T8> source8, IObservable<T9> source9, IObservable<T10> source10, IObservable<T11> source11, IObservable<T12> source12, IObservable<T13> source13, IObservable<T14> source14, IObservable<T15> source15, IObservable<T16> source16, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, TResult> resultSelector)
+ {
+ _source1 = source1;
+ _source2 = source2;
+ _source3 = source3;
+ _source4 = source4;
+ _source5 = source5;
+ _source6 = source6;
+ _source7 = source7;
+ _source8 = source8;
+ _source9 = source9;
+ _source10 = source10;
+ _source11 = source11;
+ _source12 = source12;
+ _source13 = source13;
+ _source14 = source14;
+ _source15 = source15;
+ _source16 = source16;
+ _resultSelector = resultSelector;
+ }
+
+ protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+
+ class _ : CombineLatestSink<TResult>
+ {
+ private readonly CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, TResult> _parent;
+
+ public _(CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, TResult> parent, IObserver<TResult> observer, IDisposable cancel)
+ : base(16, observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ private CombineLatestObserver<T1> _observer1;
+ private CombineLatestObserver<T2> _observer2;
+ private CombineLatestObserver<T3> _observer3;
+ private CombineLatestObserver<T4> _observer4;
+ private CombineLatestObserver<T5> _observer5;
+ private CombineLatestObserver<T6> _observer6;
+ private CombineLatestObserver<T7> _observer7;
+ private CombineLatestObserver<T8> _observer8;
+ private CombineLatestObserver<T9> _observer9;
+ private CombineLatestObserver<T10> _observer10;
+ private CombineLatestObserver<T11> _observer11;
+ private CombineLatestObserver<T12> _observer12;
+ private CombineLatestObserver<T13> _observer13;
+ private CombineLatestObserver<T14> _observer14;
+ private CombineLatestObserver<T15> _observer15;
+ private CombineLatestObserver<T16> _observer16;
+
+ public IDisposable Run()
+ {
+ var subscriptions = new SingleAssignmentDisposable[16];
+ for (int i = 0; i < 16; i++)
+ subscriptions[i] = new SingleAssignmentDisposable();
+
+ _observer1 = new CombineLatestObserver<T1>(_gate, this, 0, subscriptions[0]);
+ _observer2 = new CombineLatestObserver<T2>(_gate, this, 1, subscriptions[1]);
+ _observer3 = new CombineLatestObserver<T3>(_gate, this, 2, subscriptions[2]);
+ _observer4 = new CombineLatestObserver<T4>(_gate, this, 3, subscriptions[3]);
+ _observer5 = new CombineLatestObserver<T5>(_gate, this, 4, subscriptions[4]);
+ _observer6 = new CombineLatestObserver<T6>(_gate, this, 5, subscriptions[5]);
+ _observer7 = new CombineLatestObserver<T7>(_gate, this, 6, subscriptions[6]);
+ _observer8 = new CombineLatestObserver<T8>(_gate, this, 7, subscriptions[7]);
+ _observer9 = new CombineLatestObserver<T9>(_gate, this, 8, subscriptions[8]);
+ _observer10 = new CombineLatestObserver<T10>(_gate, this, 9, subscriptions[9]);
+ _observer11 = new CombineLatestObserver<T11>(_gate, this, 10, subscriptions[10]);
+ _observer12 = new CombineLatestObserver<T12>(_gate, this, 11, subscriptions[11]);
+ _observer13 = new CombineLatestObserver<T13>(_gate, this, 12, subscriptions[12]);
+ _observer14 = new CombineLatestObserver<T14>(_gate, this, 13, subscriptions[13]);
+ _observer15 = new CombineLatestObserver<T15>(_gate, this, 14, subscriptions[14]);
+ _observer16 = new CombineLatestObserver<T16>(_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);
+
+ return new CompositeDisposable(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);
+ }
+ }
+ }
+
+#endif
+
+ #endregion
+
+ #region Helpers for n-ary overloads
+
+ interface ICombineLatest
+ {
+ void Next(int index);
+ void Fail(Exception error);
+ void Done(int index);
+ }
+
+ abstract class CombineLatestSink<TResult> : Sink<TResult>, ICombineLatest
+ {
+ protected readonly object _gate;
+
+ private bool _hasValueAll;
+ private readonly bool[] _hasValue;
+ private readonly bool[] _isDone;
+
+ public CombineLatestSink(int arity, IObserver<TResult> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _gate = new object();
+
+ _hasValue = new bool[arity];
+ _isDone = new bool[arity];
+ }
+
+ public void Next(int index)
+ {
+ if (!_hasValueAll)
+ {
+ _hasValue[index] = true;
+
+ var hasValueAll = true;
+ foreach (var hasValue in _hasValue)
+ {
+ if (!hasValue)
+ {
+ hasValueAll = false;
+ break;
+ }
+ }
+
+ _hasValueAll = hasValueAll;
+ }
+
+ if (_hasValueAll)
+ {
+ var res = default(TResult);
+ try
+ {
+ res = GetResult();
+ }
+ catch (Exception ex)
+ {
+ base._observer.OnError(ex);
+ base.Dispose();
+ return;
+ }
+
+ base._observer.OnNext(res);
+ }
+ else
+ {
+ var allOthersDone = true;
+ for (int i = 0; i < _isDone.Length; i++)
+ {
+ if (i != index && !_isDone[i])
+ {
+ allOthersDone = false;
+ break;
+ }
+ }
+
+ if (allOthersDone)
+ {
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+
+ protected abstract TResult GetResult();
+
+ public void Fail(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void Done(int index)
+ {
+ _isDone[index] = true;
+
+ var allDone = true;
+ foreach (var isDone in _isDone)
+ {
+ if (!isDone)
+ {
+ allDone = false;
+ break;
+ }
+ }
+
+ if (allDone)
+ {
+ base._observer.OnCompleted();
+ base.Dispose();
+ return;
+ }
+ }
+ }
+
+ class CombineLatestObserver<T> : IObserver<T>
+ {
+ private readonly object _gate;
+ private readonly ICombineLatest _parent;
+ private readonly int _index;
+ private readonly IDisposable _self;
+ private T _value;
+
+ public CombineLatestObserver(object gate, ICombineLatest parent, int index, IDisposable self)
+ {
+ _gate = gate;
+ _parent = parent;
+ _index = index;
+ _self = self;
+ }
+
+ public T Value
+ {
+ get { return _value; }
+ }
+
+ public void OnNext(T value)
+ {
+ lock (_gate)
+ {
+ _value = value;
+ _parent.Next(_index);
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ _self.Dispose();
+
+ lock (_gate)
+ {
+ _parent.Fail(error);
+ }
+ }
+
+ public void OnCompleted()
+ {
+ _self.Dispose();
+
+ lock (_gate)
+ {
+ _parent.Done(_index);
+ }
+ }
+ }
+
+ #endregion
+
+ #endregion
+
+ #region N-ary
+
+ class CombineLatest<TSource, TResult> : Producer<TResult>
+ {
+ private readonly IEnumerable<IObservable<TSource>> _sources;
+ private readonly Func<IList<TSource>, TResult> _resultSelector;
+
+ public CombineLatest(IEnumerable<IObservable<TSource>> sources, Func<IList<TSource>, TResult> resultSelector)
+ {
+ _sources = sources;
+ _resultSelector = resultSelector;
+ }
+
+ protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+
+ class _ : Sink<TResult>
+ {
+ private readonly CombineLatest<TSource, TResult> _parent;
+
+ public _(CombineLatest<TSource, TResult> parent, IObserver<TResult> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ private object _gate;
+ private bool[] _hasValue;
+ private bool _hasValueAll;
+ private List<TSource> _values;
+ private bool[] _isDone;
+ private IDisposable[] _subscriptions;
+
+ public IDisposable Run()
+ {
+ var srcs = _parent._sources.ToArray();
+
+ var N = srcs.Length;
+
+ _hasValue = new bool[N];
+ _hasValueAll = false;
+
+ _values = new List<TSource>(N);
+ for (int i = 0; i < N; i++)
+ _values.Add(default(TSource));
+
+ _isDone = new bool[N];
+
+ _subscriptions = new IDisposable[N];
+
+ _gate = new object();
+
+ for (int i = 0; i < N; i++)
+ {
+ var j = i;
+
+ var d = new SingleAssignmentDisposable();
+ _subscriptions[j] = d;
+
+ var o = new O(this, j);
+ d.Disposable = srcs[j].SubscribeSafe(o);
+ }
+
+ return new CompositeDisposable(_subscriptions);
+ }
+
+ private void OnNext(int index, TSource value)
+ {
+ lock (_gate)
+ {
+ _values[index] = value;
+
+ _hasValue[index] = true;
+
+ if (_hasValueAll || (_hasValueAll = _hasValue.All(Stubs<bool>.I)))
+ {
+ var res = default(TResult);
+ try
+ {
+ res = _parent._resultSelector(new ReadOnlyCollection<TSource>(_values));
+ }
+ catch (Exception ex)
+ {
+ base._observer.OnError(ex);
+ base.Dispose();
+ return;
+ }
+
+ _observer.OnNext(res);
+ }
+ else if (_isDone.Where((x, i) => i != index).All(Stubs<bool>.I))
+ {
+ base._observer.OnCompleted();
+ base.Dispose();
+ return;
+ }
+ }
+ }
+
+ private void OnError(Exception error)
+ {
+ lock (_gate)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+ }
+
+ private void OnCompleted(int index)
+ {
+ lock (_gate)
+ {
+ _isDone[index] = true;
+
+ if (_isDone.All(Stubs<bool>.I))
+ {
+ base._observer.OnCompleted();
+ base.Dispose();
+ return;
+ }
+ else
+ {
+ _subscriptions[index].Dispose();
+ }
+ }
+ }
+
+ class O : IObserver<TSource>
+ {
+ private readonly _ _parent;
+ private readonly int _index;
+
+ public O(_ parent, int index)
+ {
+ _parent = parent;
+ _index = index;
+ }
+
+ public void OnNext(TSource value)
+ {
+ _parent.OnNext(_index, value);
+ }
+
+ public void OnError(Exception error)
+ {
+ _parent.OnError(error);
+ }
+
+ public void OnCompleted()
+ {
+ _parent.OnCompleted(_index);
+ }
+ }
+ }
+ }
+
+ #endregion
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Concat.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Concat.cs
new file mode 100644
index 0000000..5a9b2e4
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Concat.cs
@@ -0,0 +1,52 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+using System.Collections.Generic;
+using System.Reactive.Concurrency;
+using System.Reactive.Disposables;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class Concat<TSource> : Producer<TSource>, IConcatenatable<TSource>
+ {
+ private readonly IEnumerable<IObservable<TSource>> _sources;
+
+ public Concat(IEnumerable<IObservable<TSource>> sources)
+ {
+ _sources = sources;
+ }
+
+ protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(observer, cancel);
+ setSink(sink);
+ return sink.Run(_sources);
+ }
+
+ public IEnumerable<IObservable<TSource>> GetSources()
+ {
+ return _sources;
+ }
+
+ class _ : ConcatSink<TSource>
+ {
+ public _(IObserver<TSource> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ }
+
+ public override void OnNext(TSource value)
+ {
+ base._observer.OnNext(value);
+ }
+
+ public override void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Contains.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Contains.cs
new file mode 100644
index 0000000..b26e2d4
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Contains.cs
@@ -0,0 +1,76 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+using System.Collections.Generic;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class Contains<TSource> : Producer<bool>
+ {
+ private readonly IObservable<TSource> _source;
+ private readonly TSource _value;
+ private readonly IEqualityComparer<TSource> _comparer;
+
+ public Contains(IObservable<TSource> source, TSource value, IEqualityComparer<TSource> comparer)
+ {
+ _source = source;
+ _value = value;
+ _comparer = comparer;
+ }
+
+ protected override IDisposable Run(IObserver<bool> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+
+ class _ : Sink<bool>, IObserver<TSource>
+ {
+ private readonly Contains<TSource> _parent;
+
+ public _(Contains<TSource> parent, IObserver<bool> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ public void OnNext(TSource value)
+ {
+ var res = false;
+ try
+ {
+ res = _parent._comparer.Equals(value, _parent._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(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ base._observer.OnNext(false);
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Count.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Count.cs
new file mode 100644
index 0000000..7432816
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Count.cs
@@ -0,0 +1,124 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class Count<TSource> : Producer<int>
+ {
+ private readonly IObservable<TSource> _source;
+ private readonly Func<TSource, bool> _predicate;
+
+ public Count(IObservable<TSource> source)
+ {
+ _source = source;
+ }
+
+ public Count(IObservable<TSource> source, Func<TSource, bool> predicate)
+ {
+ _source = source;
+ _predicate = predicate;
+ }
+
+ protected override IDisposable Run(IObserver<int> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ if (_predicate == null)
+ {
+ var sink = new _(observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+ else
+ {
+ var sink = new π(this, observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+ }
+
+ class _ : Sink<int>, IObserver<TSource>
+ {
+ private int _count;
+
+ public _(IObserver<int> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _count = 0;
+ }
+
+ public void OnNext(TSource value)
+ {
+ try
+ {
+ checked
+ {
+ _count++;
+ }
+ }
+ catch (Exception ex)
+ {
+ base._observer.OnError(ex);
+ 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();
+ }
+ }
+
+ class π : Sink<int>, IObserver<TSource>
+ {
+ private readonly Count<TSource> _parent;
+ private int _count;
+
+ public π(Count<TSource> parent, IObserver<int> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ _count = 0;
+ }
+
+ public void OnNext(TSource value)
+ {
+ try
+ {
+ checked
+ {
+ if (_parent._predicate(value))
+ _count++;
+ }
+ }
+ catch (Exception ex)
+ {
+ base._observer.OnError(ex);
+ 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();
+ }
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/DefaultIfEmpty.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/DefaultIfEmpty.cs
new file mode 100644
index 0000000..ed4bb89
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/DefaultIfEmpty.cs
@@ -0,0 +1,60 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class DefaultIfEmpty<TSource> : Producer<TSource>
+ {
+ private readonly IObservable<TSource> _source;
+ private readonly TSource _defaultValue;
+
+ public DefaultIfEmpty(IObservable<TSource> source, TSource defaultValue)
+ {
+ _source = source;
+ _defaultValue = defaultValue;
+ }
+
+ protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+
+ class _ : Sink<TSource>, IObserver<TSource>
+ {
+ private readonly DefaultIfEmpty<TSource> _parent;
+ private bool _found;
+
+ public _(DefaultIfEmpty<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ _found = false;
+ }
+
+ public void OnNext(TSource value)
+ {
+ _found = true;
+ base._observer.OnNext(value);
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ if (!_found)
+ base._observer.OnNext(_parent._defaultValue);
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Defer.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Defer.cs
new file mode 100644
index 0000000..ba3dcc4
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Defer.cs
@@ -0,0 +1,76 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+using System.Reactive.Disposables;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class Defer<TValue> : Producer<TValue>, IEvaluatableObservable<TValue>
+ {
+ private readonly Func<IObservable<TValue>> _observableFactory;
+
+ public Defer(Func<IObservable<TValue>> observableFactory)
+ {
+ _observableFactory = observableFactory;
+ }
+
+ protected override IDisposable Run(IObserver<TValue> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+
+ public IObservable<TValue> Eval()
+ {
+ return _observableFactory();
+ }
+
+ class _ : Sink<TValue>, IObserver<TValue>
+ {
+ private readonly Defer<TValue> _parent;
+
+ public _(Defer<TValue> parent, IObserver<TValue> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ public IDisposable Run()
+ {
+ var result = default(IObservable<TValue>);
+ try
+ {
+ result = _parent.Eval();
+ }
+ catch (Exception exception)
+ {
+ base._observer.OnError(exception);
+ base.Dispose();
+ return Disposable.Empty;
+ }
+
+ return result.SubscribeSafe(this);
+ }
+
+ public void OnNext(TValue value)
+ {
+ base._observer.OnNext(value);
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Delay.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Delay.cs
new file mode 100644
index 0000000..3e2cbba
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Delay.cs
@@ -0,0 +1,768 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System.Collections.Generic;
+using System.Reactive.Concurrency;
+using System.Reactive.Disposables;
+using System.Threading;
+
+#if NO_SEMAPHORE
+using System.Reactive.Threading;
+#endif
+
+namespace System.Reactive.Linq.Observαble
+{
+ class Delay<TSource> : Producer<TSource>
+ {
+ private readonly IObservable<TSource> _source;
+ private readonly TimeSpan? _dueTimeR;
+ private readonly DateTimeOffset? _dueTimeA;
+ private readonly IScheduler _scheduler;
+
+ public Delay(IObservable<TSource> source, TimeSpan dueTime, IScheduler scheduler)
+ {
+ _source = source;
+ _dueTimeR = dueTime;
+ _scheduler = scheduler;
+ }
+
+ public Delay(IObservable<TSource> source, DateTimeOffset dueTime, IScheduler scheduler)
+ {
+ _source = source;
+ _dueTimeA = dueTime;
+ _scheduler = scheduler;
+ }
+
+ protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ if (_scheduler.AsLongRunning() != null)
+ {
+ var sink = new λ(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+ else
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+ }
+
+ class _ : Sink<TSource>, IObserver<TSource>
+ {
+ private readonly Delay<TSource> _parent;
+
+ public _(Delay<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ 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<System.Reactive.TimeInterval<TSource>> _queue;
+ private bool _hasCompleted;
+ private TimeSpan _completeAt;
+ private bool _hasFailed;
+ private Exception _exception;
+
+ public IDisposable Run()
+ {
+ _scheduler = _parent._scheduler;
+
+ _cancelable = new SerialDisposable();
+
+ _gate = new object();
+ _active = false;
+ _running = false;
+ _queue = new Queue<System.Reactive.TimeInterval<TSource>>();
+ _hasCompleted = false;
+ _completeAt = default(TimeSpan);
+ _hasFailed = false;
+ _exception = default(Exception);
+
+ _watch = _scheduler.StartStopwatch();
+
+ if (_parent._dueTimeA.HasValue)
+ {
+ _ready = false;
+
+ var dueTimeA = _parent._dueTimeA.Value;
+ _cancelable.Disposable = _scheduler.Schedule(dueTimeA, Start);
+ }
+ else
+ {
+ _ready = true;
+
+ var dueTimeR = _parent._dueTimeR.Value;
+ _delay = Scheduler.Normalize(dueTimeR);
+ }
+
+ var sourceSubscription = new SingleAssignmentDisposable();
+ _sourceSubscription = sourceSubscription;
+ sourceSubscription.Disposable = _parent._source.SubscribeSafe(this);
+
+ return new CompositeDisposable(_sourceSubscription, _cancelable);
+ }
+
+ private void Start()
+ {
+ var next = default(TimeSpan);
+ var shouldRun = false;
+
+ lock (_gate)
+ {
+ _delay = _watch.Elapsed;
+
+ var oldQueue = _queue;
+ _queue = new Queue<Reactive.TimeInterval<TSource>>();
+
+ if (oldQueue.Count > 0)
+ {
+ next = oldQueue.Peek().Interval;
+
+ while (oldQueue.Count > 0)
+ {
+ var item = oldQueue.Dequeue();
+ _queue.Enqueue(new Reactive.TimeInterval<TSource>(item.Value, item.Interval.Add(_delay)));
+ }
+
+ shouldRun = true;
+ _active = true;
+ }
+
+ _ready = true;
+ }
+
+ if (shouldRun)
+ {
+ _cancelable.Disposable = _scheduler.Schedule(next, DrainQueue);
+ }
+ }
+
+ public void OnNext(TSource value)
+ {
+ var next = _watch.Elapsed.Add(_delay);
+ var shouldRun = false;
+
+ lock (_gate)
+ {
+ _queue.Enqueue(new System.Reactive.TimeInterval<TSource>(value, next));
+
+ shouldRun = _ready && !_active;
+ _active = true;
+ }
+
+ if (shouldRun)
+ {
+ _cancelable.Disposable = _scheduler.Schedule(_delay, DrainQueue);
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ _sourceSubscription.Dispose();
+
+ var shouldRun = false;
+
+ lock (_gate)
+ {
+ _queue.Clear();
+
+ _exception = error;
+ _hasFailed = true;
+
+ shouldRun = !_running;
+ }
+
+ if (shouldRun)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+ }
+
+ public void OnCompleted()
+ {
+ _sourceSubscription.Dispose();
+
+ var next = _watch.Elapsed.Add(_delay);
+ var shouldRun = false;
+
+ lock (_gate)
+ {
+ _completeAt = next;
+ _hasCompleted = true;
+
+ shouldRun = _ready && !_active;
+ _active = true;
+ }
+
+ if (shouldRun)
+ {
+ _cancelable.Disposable = _scheduler.Schedule(_delay, DrainQueue);
+ }
+ }
+
+ private void DrainQueue(Action<TimeSpan> recurse)
+ {
+ 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 λ). 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) */
+ }
+ }
+
+ class λ : Sink<TSource>, IObserver<TSource>
+ {
+ private readonly Delay<TSource> _parent;
+
+ public λ(Delay<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ private IDisposable _sourceSubscription;
+ private SerialDisposable _cancelable;
+ private TimeSpan _delay;
+ private IStopwatch _watch;
+
+ private object _gate;
+#if !NO_CDS
+ private SemaphoreSlim _evt;
+ private CancellationTokenSource _stop;
+#else
+ private Semaphore _evt;
+ private bool _stopped;
+ private ManualResetEvent _stop;
+#endif
+ private Queue<System.Reactive.TimeInterval<TSource>> _queue;
+ private bool _hasCompleted;
+ private TimeSpan _completeAt;
+ private bool _hasFailed;
+ private Exception _exception;
+
+ public IDisposable Run()
+ {
+ _cancelable = new SerialDisposable();
+
+ _gate = new object();
+#if !NO_CDS
+ _evt = new SemaphoreSlim(0);
+#else
+ _evt = new Semaphore(0, int.MaxValue);
+#endif
+ _queue = new Queue<System.Reactive.TimeInterval<TSource>>();
+ _hasCompleted = false;
+ _completeAt = default(TimeSpan);
+ _hasFailed = false;
+ _exception = default(Exception);
+
+ _watch = _parent._scheduler.StartStopwatch();
+
+ if (_parent._dueTimeA.HasValue)
+ {
+ var dueTimeA = _parent._dueTimeA.Value;
+ _cancelable.Disposable = _parent._scheduler.Schedule(dueTimeA, Start);
+ }
+ else
+ {
+ var dueTimeR = _parent._dueTimeR.Value;
+ _delay = Scheduler.Normalize(dueTimeR);
+ ScheduleDrain();
+ }
+
+ var sourceSubscription = new SingleAssignmentDisposable();
+ _sourceSubscription = sourceSubscription;
+ sourceSubscription.Disposable = _parent._source.SubscribeSafe(this);
+
+ return new CompositeDisposable(_sourceSubscription, _cancelable);
+ }
+
+ private void Start()
+ {
+ lock (_gate)
+ {
+ _delay = _watch.Elapsed;
+
+ var oldQueue = _queue;
+ _queue = new Queue<Reactive.TimeInterval<TSource>>();
+
+ while (oldQueue.Count > 0)
+ {
+ var item = oldQueue.Dequeue();
+ _queue.Enqueue(new Reactive.TimeInterval<TSource>(item.Value, item.Interval.Add(_delay)));
+ }
+ }
+
+ ScheduleDrain();
+ }
+
+ private void ScheduleDrain()
+ {
+#if !NO_CDS
+ _stop = new CancellationTokenSource();
+ _cancelable.Disposable = Disposable.Create(() => _stop.Cancel());
+#else
+ _stop = new ManualResetEvent(false);
+ _cancelable.Disposable = Disposable.Create(() =>
+ {
+ _stopped = true;
+ _stop.Set();
+ _evt.Release();
+ });
+#endif
+
+ _parent._scheduler.AsLongRunning().ScheduleLongRunning(DrainQueue);
+ }
+
+ public void OnNext(TSource value)
+ {
+ var next = _watch.Elapsed.Add(_delay);
+
+ lock (_gate)
+ {
+ _queue.Enqueue(new System.Reactive.TimeInterval<TSource>(value, next));
+
+ _evt.Release();
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ _sourceSubscription.Dispose();
+
+ lock (_gate)
+ {
+ _queue.Clear();
+
+ _exception = error;
+ _hasFailed = true;
+
+ _evt.Release();
+ }
+ }
+
+ public void OnCompleted()
+ {
+ _sourceSubscription.Dispose();
+
+ var next = _watch.Elapsed.Add(_delay);
+
+ lock (_gate)
+ {
+ _completeAt = next;
+ _hasCompleted = true;
+
+ _evt.Release();
+ }
+ }
+
+ private void DrainQueue(ICancelable cancel)
+ {
+ while (true)
+ {
+#if !NO_CDS
+ try
+ {
+ _evt.Wait(_stop.Token);
+ }
+ catch (OperationCanceledException)
+ {
+ return;
+ }
+#else
+ _evt.WaitOne();
+ if (_stopped)
+ return;
+#endif
+
+ 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)
+ {
+ error = _exception;
+ hasFailed = true;
+ }
+ else
+ {
+ var now = _watch.Elapsed;
+
+ if (_queue.Count > 0)
+ {
+ 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 if (_hasCompleted)
+ {
+ hasCompleted = true;
+
+ if (_completeAt.CompareTo(now) > 0)
+ {
+ shouldWait = true;
+ waitTime = Scheduler.Normalize(_completeAt.Subtract(now));
+ }
+ }
+ }
+ } /* lock (_gate) */
+
+ if (shouldWait)
+ {
+#if !NO_CDS
+ var timer = new ManualResetEventSlim();
+ _parent._scheduler.Schedule(waitTime, () => { timer.Set(); });
+
+ try
+ {
+ timer.Wait(_stop.Token);
+ }
+ catch (OperationCanceledException)
+ {
+ return;
+ }
+#else
+ var timer = new ManualResetEvent(false);
+ _parent._scheduler.Schedule(waitTime, () => { timer.Set(); });
+ if (WaitHandle.WaitAny(new[] { timer, _stop }) == 1)
+ return;
+#endif
+ }
+
+ if (hasValue)
+ {
+ base._observer.OnNext(value);
+ }
+ else
+ {
+ if (hasCompleted)
+ {
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ else if (hasFailed)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ return;
+ }
+ }
+ }
+ }
+ }
+
+ class Delay<TSource, TDelay> : Producer<TSource>
+ {
+ private readonly IObservable<TSource> _source;
+ private readonly IObservable<TDelay> _subscriptionDelay;
+ private readonly Func<TSource, IObservable<TDelay>> _delaySelector;
+
+ public Delay(IObservable<TSource> source, IObservable<TDelay> subscriptionDelay, Func<TSource, IObservable<TDelay>> delaySelector)
+ {
+ _source = source;
+ _subscriptionDelay = subscriptionDelay;
+ _delaySelector = delaySelector;
+ }
+
+ protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+
+ class _ : Sink<TSource>, IObserver<TSource>
+ {
+ private readonly Delay<TSource, TDelay> _parent;
+
+ public _(Delay<TSource, TDelay> parent, IObserver<TSource> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ private CompositeDisposable _delays;
+ private object _gate;
+ private bool _atEnd;
+ private SerialDisposable _subscription;
+
+ public IDisposable Run()
+ {
+ _delays = new CompositeDisposable();
+ _gate = new object();
+ _atEnd = false;
+ _subscription = new SerialDisposable();
+
+ if (_parent._subscriptionDelay == null)
+ {
+ Start();
+ }
+ else
+ {
+ _subscription.Disposable = _parent._subscriptionDelay.SubscribeSafe(new σ(this));
+ }
+
+ return new CompositeDisposable(_subscription, _delays);
+ }
+
+ private void Start()
+ {
+ _subscription.Disposable = _parent._source.SubscribeSafe(this);
+ }
+
+ public void OnNext(TSource value)
+ {
+ var delay = default(IObservable<TDelay>);
+ try
+ {
+ delay = _parent._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 δ(this, value, d));
+ }
+
+ public void OnError(Exception error)
+ {
+ lock (_gate)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+ }
+
+ public void OnCompleted()
+ {
+ lock (_gate)
+ {
+ _atEnd = true;
+ _subscription.Dispose();
+
+ CheckDone();
+ }
+ }
+
+ private void CheckDone()
+ {
+ if (_atEnd && _delays.Count == 0)
+ {
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+
+ class σ : IObserver<TDelay>
+ {
+ private readonly _ _parent;
+
+ public σ(_ parent)
+ {
+ _parent = parent;
+ }
+
+ public void OnNext(TDelay value)
+ {
+ _parent.Start();
+ }
+
+ public void OnError(Exception error)
+ {
+ _parent._observer.OnError(error);
+ _parent.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ _parent.Start();
+ }
+ }
+
+ class δ : IObserver<TDelay>
+ {
+ private readonly _ _parent;
+ private readonly TSource _value;
+ private readonly IDisposable _self;
+
+ public δ(_ 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();
+ }
+ }
+ }
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/DelaySubscription.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/DelaySubscription.cs
new file mode 100644
index 0000000..c6a05cc
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/DelaySubscription.cs
@@ -0,0 +1,76 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+using System.Reactive.Concurrency;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class DelaySubscription<TSource> : Producer<TSource>
+ {
+ private readonly IObservable<TSource> _source;
+ private readonly DateTimeOffset? _dueTimeA;
+ private readonly TimeSpan? _dueTimeR;
+ private readonly IScheduler _scheduler;
+
+ public DelaySubscription(IObservable<TSource> source, DateTimeOffset dueTime, IScheduler scheduler)
+ {
+ _source = source;
+ _dueTimeA = dueTime;
+ _scheduler = scheduler;
+ }
+
+ public DelaySubscription(IObservable<TSource> source, TimeSpan dueTime, IScheduler scheduler)
+ {
+ _source = source;
+ _dueTimeR = dueTime;
+ _scheduler = scheduler;
+ }
+
+ protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(observer, cancel);
+ setSink(sink);
+
+ if (_dueTimeA.HasValue)
+ {
+ return _scheduler.Schedule(sink, _dueTimeA.Value, Subscribe);
+ }
+ else
+ {
+ return _scheduler.Schedule(sink, _dueTimeR.Value, Subscribe);
+ }
+ }
+
+ private IDisposable Subscribe(IScheduler _, _ sink)
+ {
+ return _source.SubscribeSafe(sink);
+ }
+
+ class _ : Sink<TSource>, IObserver<TSource>
+ {
+ public _(IObserver<TSource> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ }
+
+ public void OnNext(TSource value)
+ {
+ base._observer.OnNext(value);
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Dematerialize.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Dematerialize.cs
new file mode 100644
index 0000000..112b156
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Dematerialize.cs
@@ -0,0 +1,63 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class Dematerialize<TSource> : Producer<TSource>
+ {
+ private readonly IObservable<Notification<TSource>> _source;
+
+ public Dematerialize(IObservable<Notification<TSource>> source)
+ {
+ _source = source;
+ }
+
+ protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+
+ class _ : Sink<TSource>, IObserver<Notification<TSource>>
+ {
+ public _(IObserver<TSource> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ }
+
+ public void OnNext(Notification<TSource> value)
+ {
+ switch (value.Kind)
+ {
+ case NotificationKind.OnNext:
+ base._observer.OnNext(value.Value);
+ break;
+ case NotificationKind.OnError:
+ base._observer.OnError(value.Exception);
+ base.Dispose();
+ break;
+ case NotificationKind.OnCompleted:
+ base._observer.OnCompleted();
+ base.Dispose();
+ break;
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Distinct.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Distinct.cs
new file mode 100644
index 0000000..af20277
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Distinct.cs
@@ -0,0 +1,75 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+using System.Collections.Generic;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class Distinct<TSource, TKey> : Producer<TSource>
+ {
+ private readonly IObservable<TSource> _source;
+ private readonly Func<TSource, TKey> _keySelector;
+ private readonly IEqualityComparer<TKey> _comparer;
+
+ public Distinct(IObservable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
+ {
+ _source = source;
+ _keySelector = keySelector;
+ _comparer = comparer;
+ }
+
+ protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+
+ class _ : Sink<TSource>, IObserver<TSource>
+ {
+ private readonly Distinct<TSource, TKey> _parent;
+ private HashSet<TKey> _hashSet;
+
+ public _(Distinct<TSource, TKey> parent, IObserver<TSource> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ _hashSet = new HashSet<TKey>(_parent._comparer);
+ }
+
+ public void OnNext(TSource value)
+ {
+ var key = default(TKey);
+ var hasAdded = false;
+ try
+ {
+ key = _parent._keySelector(value);
+ hasAdded = _hashSet.Add(key);
+ }
+ catch (Exception exception)
+ {
+ base._observer.OnError(exception);
+ base.Dispose();
+ return;
+ }
+
+ if (hasAdded)
+ base._observer.OnNext(value);
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/DistinctUntilChanged.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/DistinctUntilChanged.cs
new file mode 100644
index 0000000..10c7923
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/DistinctUntilChanged.cs
@@ -0,0 +1,94 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+using System.Collections.Generic;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class DistinctUntilChanged<TSource, TKey> : Producer<TSource>
+ {
+ private readonly IObservable<TSource> _source;
+ private readonly Func<TSource, TKey> _keySelector;
+ private readonly IEqualityComparer<TKey> _comparer;
+
+ public DistinctUntilChanged(IObservable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
+ {
+ _source = source;
+ _keySelector = keySelector;
+ _comparer = comparer;
+ }
+
+ protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+
+ class _ : Sink<TSource>, IObserver<TSource>
+ {
+ private readonly DistinctUntilChanged<TSource, TKey> _parent;
+ private TKey _currentKey;
+ private bool _hasCurrentKey;
+
+ public _(DistinctUntilChanged<TSource, TKey> parent, IObserver<TSource> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ _currentKey = default(TKey);
+ _hasCurrentKey = false;
+ }
+
+ public void OnNext(TSource value)
+ {
+ var key = default(TKey);
+ try
+ {
+ key = _parent._keySelector(value);
+ }
+ catch (Exception exception)
+ {
+ base._observer.OnError(exception);
+ base.Dispose();
+ return;
+ }
+
+ var comparerEquals = false;
+ if (_hasCurrentKey)
+ {
+ try
+ {
+ comparerEquals = _parent._comparer.Equals(_currentKey, key);
+ }
+ catch (Exception exception)
+ {
+ base._observer.OnError(exception);
+ base.Dispose();
+ return;
+ }
+ }
+
+ if (!_hasCurrentKey || !comparerEquals)
+ {
+ _hasCurrentKey = true;
+ _currentKey = key;
+ base._observer.OnNext(value);
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Do.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Do.cs
new file mode 100644
index 0000000..2f73cfa
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Do.cs
@@ -0,0 +1,92 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class Do<TSource> : Producer<TSource>
+ {
+ private readonly IObservable<TSource> _source;
+ private readonly Action<TSource> _onNext;
+ private readonly Action<Exception> _onError;
+ private readonly Action _onCompleted;
+
+ public Do(IObservable<TSource> source, Action<TSource> onNext, Action<Exception> onError, Action onCompleted)
+ {
+ _source = source;
+ _onNext = onNext;
+ _onError = onError;
+ _onCompleted = onCompleted;
+ }
+
+ protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+
+ class _ : Sink<TSource>, IObserver<TSource>
+ {
+ private readonly Do<TSource> _parent;
+
+ public _(Do<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ public void OnNext(TSource value)
+ {
+ try
+ {
+ _parent._onNext(value);
+ }
+ catch (Exception ex)
+ {
+ base._observer.OnError(ex);
+ base.Dispose();
+ return;
+ }
+
+ base._observer.OnNext(value);
+ }
+
+ public void OnError(Exception error)
+ {
+ try
+ {
+ _parent._onError(error);
+ }
+ catch (Exception ex)
+ {
+ base._observer.OnError(ex);
+ base.Dispose();
+ return;
+ }
+
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ try
+ {
+ _parent._onCompleted();
+ }
+ catch (Exception ex)
+ {
+ base._observer.OnError(ex);
+ base.Dispose();
+ return;
+ }
+
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/DoWhile.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/DoWhile.cs
new file mode 100644
index 0000000..3ef40eb
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/DoWhile.cs
@@ -0,0 +1,54 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+using System.Collections.Generic;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class DoWhile<TSource> : Producer<TSource>, IConcatenatable<TSource>
+ {
+ private readonly IObservable<TSource> _source;
+ private readonly Func<bool> _condition;
+
+ public DoWhile(IObservable<TSource> source, Func<bool> condition)
+ {
+ _condition = condition;
+ _source = source;
+ }
+
+ protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(observer, cancel);
+ setSink(sink);
+ return sink.Run(GetSources());
+ }
+
+ public IEnumerable<IObservable<TSource>> GetSources()
+ {
+ yield return _source;
+ while (_condition())
+ yield return _source;
+ }
+
+ class _ : ConcatSink<TSource>
+ {
+ public _(IObserver<TSource> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ }
+
+ public override void OnNext(TSource value)
+ {
+ base._observer.OnNext(value);
+ }
+
+ public override void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+ }
+ }
+}
+#endif
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/ElementAt.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/ElementAt.cs
new file mode 100644
index 0000000..b2b1212
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/ElementAt.cs
@@ -0,0 +1,75 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class ElementAt<TSource> : Producer<TSource>
+ {
+ private readonly IObservable<TSource> _source;
+ private readonly int _index;
+ private readonly bool _throwOnEmpty;
+
+ public ElementAt(IObservable<TSource> source, int index, bool throwOnEmpty)
+ {
+ _source = source;
+ _index = index;
+ _throwOnEmpty = throwOnEmpty;
+ }
+
+ protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+
+ class _ : Sink<TSource>, IObserver<TSource>
+ {
+ private readonly ElementAt<TSource> _parent;
+ private int _i;
+
+ public _(ElementAt<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ _i = _parent._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()
+ {
+ if (_parent._throwOnEmpty)
+ {
+ base._observer.OnError(new ArgumentOutOfRangeException("index"));
+ }
+ else
+ {
+ base._observer.OnNext(default(TSource));
+ base._observer.OnCompleted();
+ }
+
+ base.Dispose();
+ }
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Empty.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Empty.cs
new file mode 100644
index 0000000..42c7241
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Empty.cs
@@ -0,0 +1,48 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+using System.Reactive.Concurrency;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class Empty<TResult> : Producer<TResult>
+ {
+ private readonly IScheduler _scheduler;
+
+ public Empty(IScheduler scheduler)
+ {
+ _scheduler = scheduler;
+ }
+
+ protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+
+ class _ : Sink<TResult>
+ {
+ private readonly Empty<TResult> _parent;
+
+ public _(Empty<TResult> parent, IObserver<TResult> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ public IDisposable Run()
+ {
+ return _parent._scheduler.Schedule(Invoke);
+ }
+
+ private void Invoke()
+ {
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Finally.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Finally.cs
new file mode 100644
index 0000000..ca9a5d8
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Finally.cs
@@ -0,0 +1,73 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+using System.Reactive.Disposables;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class Finally<TSource> : Producer<TSource>
+ {
+ private readonly IObservable<TSource> _source;
+ private readonly Action _finallyAction;
+
+ public Finally(IObservable<TSource> source, Action finallyAction)
+ {
+ _source = source;
+ _finallyAction = finallyAction;
+ }
+
+ protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+
+ class _ : Sink<TSource>, IObserver<TSource>
+ {
+ private readonly Finally<TSource> _parent;
+
+ public _(Finally<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ public IDisposable Run()
+ {
+ var subscription = _parent._source.SubscribeSafe(this);
+
+ return Disposable.Create(() =>
+ {
+ try
+ {
+ subscription.Dispose();
+ }
+ finally
+ {
+ _parent._finallyAction();
+ }
+ });
+ }
+
+ public void OnNext(TSource value)
+ {
+ base._observer.OnNext(value);
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/FirstAsync.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/FirstAsync.cs
new file mode 100644
index 0000000..8d8bba7
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/FirstAsync.cs
@@ -0,0 +1,132 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class FirstAsync<TSource> : Producer<TSource>
+ {
+ private readonly IObservable<TSource> _source;
+ private readonly Func<TSource, bool> _predicate;
+ private readonly bool _throwOnEmpty;
+
+ public FirstAsync(IObservable<TSource> source, Func<TSource, bool> predicate, bool throwOnEmpty)
+ {
+ _source = source;
+ _predicate = predicate;
+ _throwOnEmpty = throwOnEmpty;
+ }
+
+ protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ if (_predicate != null)
+ {
+ var sink = new π(this, observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+ else
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+ }
+
+ class _ : Sink<TSource>, IObserver<TSource>
+ {
+ private readonly FirstAsync<TSource> _parent;
+
+ public _(FirstAsync<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ 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()
+ {
+ if (_parent._throwOnEmpty)
+ {
+ base._observer.OnError(new InvalidOperationException(Strings_Linq.NO_ELEMENTS));
+ }
+ else
+ {
+ base._observer.OnNext(default(TSource));
+ base._observer.OnCompleted();
+ }
+
+ base.Dispose();
+ }
+ }
+
+ class π : Sink<TSource>, IObserver<TSource>
+ {
+ private readonly FirstAsync<TSource> _parent;
+
+ public π(FirstAsync<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ public void OnNext(TSource value)
+ {
+ var b = false;
+
+ try
+ {
+ b = _parent._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()
+ {
+ if (_parent._throwOnEmpty)
+ {
+ base._observer.OnError(new InvalidOperationException(Strings_Linq.NO_MATCHING_ELEMENTS));
+ }
+ else
+ {
+ base._observer.OnNext(default(TSource));
+ base._observer.OnCompleted();
+ }
+
+ base.Dispose();
+ }
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/For.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/For.cs
new file mode 100644
index 0000000..85b9e03
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/For.cs
@@ -0,0 +1,53 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+using System.Collections.Generic;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class For<TSource, TResult> : Producer<TResult>, IConcatenatable<TResult>
+ {
+ private readonly IEnumerable<TSource> _source;
+ private readonly Func<TSource, IObservable<TResult>> _resultSelector;
+
+ public For(IEnumerable<TSource> source, Func<TSource, IObservable<TResult>> resultSelector)
+ {
+ _source = source;
+ _resultSelector = resultSelector;
+ }
+
+ protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(observer, cancel);
+ setSink(sink);
+ return sink.Run(GetSources());
+ }
+
+ public IEnumerable<IObservable<TResult>> GetSources()
+ {
+ foreach (var item in _source)
+ yield return _resultSelector(item);
+ }
+
+ class _ : ConcatSink<TResult>
+ {
+ public _(IObserver<TResult> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ }
+
+ public override void OnNext(TResult value)
+ {
+ base._observer.OnNext(value);
+ }
+
+ public override void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+ }
+ }
+}
+#endif
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/ForEach.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/ForEach.cs
new file mode 100644
index 0000000..38e112d
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/ForEach.cs
@@ -0,0 +1,122 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+using System.Threading;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class ForEach<TSource>
+ {
+ public class _ : IObserver<TSource>
+ {
+ private readonly Action<TSource> _onNext;
+ private readonly Action _done;
+
+ private Exception _exception;
+ private int _stopped;
+
+ public _(Action<TSource> onNext, Action done)
+ {
+ _onNext = onNext;
+ _done = done;
+
+ _stopped = 0;
+ }
+
+ public Exception Error
+ {
+ get { return _exception; }
+ }
+
+ public void OnNext(TSource value)
+ {
+ if (_stopped == 0)
+ {
+ try
+ {
+ _onNext(value);
+ }
+ catch (Exception ex)
+ {
+ OnError(ex);
+ }
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ if (Interlocked.Exchange(ref _stopped, 1) == 0)
+ {
+ _exception = error;
+ _done();
+ }
+ }
+
+ public void OnCompleted()
+ {
+ if (Interlocked.Exchange(ref _stopped, 1) == 0)
+ {
+ _done();
+ }
+ }
+ }
+
+ public class τ : IObserver<TSource>
+ {
+ private readonly Action<TSource, int> _onNext;
+ private readonly Action _done;
+
+ private int _index;
+ private Exception _exception;
+ private int _stopped;
+
+ public τ(Action<TSource, int> onNext, Action done)
+ {
+ _onNext = onNext;
+ _done = done;
+
+ _index = 0;
+ _stopped = 0;
+ }
+
+ public Exception Error
+ {
+ get { return _exception; }
+ }
+
+ public void OnNext(TSource value)
+ {
+ if (_stopped == 0)
+ {
+ try
+ {
+ _onNext(value, checked(_index++));
+ }
+ catch (Exception ex)
+ {
+ OnError(ex);
+ }
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ if (Interlocked.Exchange(ref _stopped, 1) == 0)
+ {
+ _exception = error;
+ _done();
+ }
+ }
+
+ public void OnCompleted()
+ {
+ if (Interlocked.Exchange(ref _stopped, 1) == 0)
+ {
+ _done();
+ }
+ }
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/FromEvent.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/FromEvent.cs
new file mode 100644
index 0000000..82c4348
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/FromEvent.cs
@@ -0,0 +1,368 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+using System.Diagnostics;
+using System.Reactive.Concurrency;
+using System.Reactive.Disposables;
+using System.Reactive.Subjects;
+
+//
+// BREAKING CHANGE v2 > v1.x - FromEvent[Pattern] now has an implicit SubscribeOn and Publish operation.
+//
+// The free-threaded nature of Rx is key to the performance characteristics of the event processing
+// pipeline. However, in places where we bridge with the external world, this sometimes has negative
+// effects due to thread-affine operations involved. The FromEvent[Pattern] bridges are one such
+// place where we reach out to add and remove operations on events.
+//
+// Consider the following piece of code, assuming Rx v1.x usage:
+//
+// var txt = Observable.FromEventPattern(txtInput, "TextChanged");
+// var res = from term in txt
+// from word in svc.Lookup(term).TakeUntil(txt)
+// select word;
+//
+// This code is flawed for various reasons. Seasoned Rx developers will immediately suggest usage of
+// the Publish operator to share the side-effects of subscribing to the txt sequence, resulting in
+// only one subscription to the event:
+//
+// var txt = Observable.FromEventPattern(txtInput, "TextChanged");
+// var res = txt.Publish(txt_ => from term in txt_
+// from word in svc.Lookup(term).TakeUntil(txt_)
+// select word);
+//
+// Customers are typically confused as to why FromEvent[Pattern] causes multiple handlers to be added
+// to the underlying event. This is in contrast with other From* bridges which involve the use of a
+// subject (e.g. FromAsyncPattern, FromAsync, and ToObservable on Task<T>).
+//
+// But there are more issues with the code fragment above. Upon completion of the svc.Lookup(term)
+// sequence, TakeUntil will unsubscribe from both sequences, causing the unsubscription to happen in
+// the context of the source's OnCompleted, which may be the thread pool. Some thread-affine events
+// don't quite like this. In UI frameworks like WPF and Silverlight, this turns out to be not much of
+// a problem typically, but it's merely an accident things work out. From an e-mail conversion with
+// the WPF/SL/Jupiter experts:
+//
+// "Unfortunately, as I expected, it’s confusing, and implementation details are showing through.
+// The bottom line is that event add/remove should always be done on the right thread.
+//
+// Where events are implemented with compiler-generated code, i.e. MultiCastDelegate, the add/remove
+// will be thread safe/agile. Where events are implemented in custom code, across Wpf/SL/WP/Jupiter,
+// the add/remove are expected to happen on the Dispatcher thread.
+//
+// Jupiter actually has the consistent story here, where all the event add/remove implementations do
+// the thread check. It should still be a “wrong thread” error, though, not an AV.
+//
+// In SL there’s a mix of core events (which do the thread check) and framework events (which use
+// compiler-generated event implementations). So you get an exception if you unhook Button.Loaded
+// from off thread, but you don’t get an exception if you unhook Button.Click.
+//
+// In WPF there’s a similar mix (some events are compiler-generated and some use the EventHandlerStore).
+// But I don’t see any thread safety or thread check in the EventHandlerStore. So while it works, IIUC,
+// it should have race conditions and corruptions."
+//
+// Starting with "Jupiter" (Windows XAML aka "Metro"), checks are added to ensure the add and remove
+// operations for UI events are called from the UI thread. As a result, the dictionary suggest sample
+// code shown above starts to fail. A possible fix is to use SubscribeOnDispatcher:
+//
+// var txt = Observable.FromEventPattern(txtInput, "TextChanged").SubscribeOnDispatcher();
+// var res = from term in txt
+// from word in svc.Lookup(term).TakeUntil(txt)
+// select word;
+//
+// This fix has two problems:
+//
+// 1. Customers often don't quite understand the difference between ObserveOn and SubscribeOn. In fact,
+// we've given guidance that use of the latter is typically indicative of a misunderstanding, and
+// is used rarely. Also, the fragment above would likely be extended with some UI binding code where
+// one needs to use ObserveOnDispatcher, so the combination of both becomes even more confusing.
+//
+// 2. There's a subtle race condition now. Upon receiving a new term from the txt sequence, SelectMany's
+// invocation of the result selector involves TakeUntil subscribing to txt again. However, the use
+// of SubscribeOnDispatcher means the subscription is now happening asynchronously, leaving a time
+// gap between returning from Subscribe and doing the += on the underlying event:
+//
+// (Subscription of TakeUntil to txt)
+// |
+// v
+// txt --------------------------------------------------------------
+// |
+// +-----...----+ (SubscribeOnDispatcher's post of Subscribe)
+// |
+// TextChanged ------"re"---------"rea"-------------"reac"-----"react"----...
+// ^
+// |
+// (where += on the event happens)
+//
+// While this problem is rare and sometimes gets mitigated by accident because code is posting back
+// to e.g. the UI message loop, it's extremely hard to debug when things go wrong.
+//
+// In order to fix this behavior such that code has the expected behavior, we do two things in Rx v2.0:
+//
+// - To solve the cross-thread add/remove handler operations and make them single-thread affine, we
+// now do an implicit SubscribeOn with the SynchronizationContext.Current retrieved eagerly upon
+// calling FromEvent[Pattern]. This goes hand-in-hand with a recommendation:
+//
+// "Always call FromEvent[Pattern] in a place where you'd normally write += and -= operations
+// yourself. Don't inline the creation of a FromEvent[Pattern] object inside a query."
+//
+// This recommendation helps to keep code clean (bridging operations are moved outside queries) and
+// ensures the captured SynchronizationContext is the least surprising one. E.g in the sample code
+// above, the whole query likely lives in a button_Click handler or so.
+//
+// - To solve the time gap issue, we now add implicit Publish behavior with ref-counted behavior. In
+// other words, the new FromEvent[Pattern] is pretty much the same as:
+//
+// Observable_v2.FromEvent[Pattern](<args>)
+// ==
+// Observable_v1.FromEvent[Pattern](<args>).SubscribeOn(SynchronizationContext.Current)
+// .Publish()
+// .RefCount()
+//
+// Overloads to FromEvent[Pattern] allow to specify the scheduler used for the SubscribeOn operation
+// that's taking place internally. When omitted, a SynchronizationContextScheduler will be supplied
+// if a current SynchronizationContext is found. If no current SynchronizationContext is found, the
+// default scheduler is the immediate scheduler, falling back to the free-threaded behavior we had
+// before in v1.x. (See GetSchedulerForCurrentContext in QueryLanguage.Events.cs).
+//
+// Notice a time gap can still occur at the point of the first subscription to the event sequence,
+// or when the ref count fell back to zero. In cases of nested uses of the sequence (such as in the
+// running example here), this is fine because the top-level subscription is kept alive for the whole
+// duration. In other cases, there's already a race condition between the underlying event and the
+// observable wrapper (assuming events are hot). For cold events that have side-effects upon add and
+// remove handler operations, use of Observable.Create is recommended. This should be rather rare,
+// as most events follow the typical MulticastDelegate implementation pattern:
+//
+// public event EventHandler<BarEventArgs> Bar;
+//
+// protected void OnBar(int value)
+// {
+// var bar = Bar;
+// if (bar != null)
+// bar(this, new BarEventArgs(value));
+// }
+//
+// In here, there's already a race between the user hooking up an event handler through the += add
+// operation and the event producer (possibly on a different thread) calling OnBar. It's also worth
+// pointing out that this race condition is migitated by a check in SynchronizationContextScheduler
+// causing synchronous execution in case the caller is already on the target SynchronizationContext.
+// This situation is common when using FromEvent[Pattern] immediately after declaring it, e.g. in
+// the context of a UI event handler.
+//
+// Finally, notice we can't simply connect the event to a Subject<T> upon a FromEvent[Pattern] call,
+// because this would make it impossible to get rid of this one event handler (unless we expose some
+// other means of resource maintenance, e.g. by making the returned object implement IDisposable).
+// Also, this would cause the event producer to see the event's delegate in a non-null state all the
+// time, causing event argument objects to be newed up, possibly sending those into a zero-observer
+// subject (which is opaque to the event producer). Not to mention that the subject would always be
+// rooted by the target event (even when the FromEvent[Pattern] observable wrapper is unreachable).
+//
+namespace System.Reactive.Linq.Observαble
+{
+ class FromEvent<TDelegate, TEventArgs> : ClassicEventProducer<TDelegate, TEventArgs>
+ {
+ private readonly Func<Action<TEventArgs>, TDelegate> _conversion;
+
+ public FromEvent(Action<TDelegate> addHandler, Action<TDelegate> removeHandler, IScheduler scheduler)
+ : base(addHandler, removeHandler, scheduler)
+ {
+ }
+
+ public FromEvent(Func<Action<TEventArgs>, TDelegate> conversion, Action<TDelegate> addHandler, Action<TDelegate> removeHandler, IScheduler scheduler)
+ : base(addHandler, removeHandler, scheduler)
+ {
+ _conversion = conversion;
+ }
+
+ protected override TDelegate GetHandler(Action<TEventArgs> onNext)
+ {
+ var handler = default(TDelegate);
+
+ if (_conversion == null)
+ {
+ handler = ReflectionUtils.CreateDelegate<TDelegate>(onNext, typeof(Action<TEventArgs>).GetMethod("Invoke"));
+ }
+ else
+ {
+ handler = _conversion(onNext);
+ }
+
+ return handler;
+ }
+ }
+
+ abstract class EventProducer<TDelegate, TArgs> : Producer<TArgs>
+ {
+ private readonly IScheduler _scheduler;
+ private readonly object _gate;
+
+ public EventProducer(IScheduler scheduler)
+ {
+ _scheduler = scheduler;
+ _gate = new object();
+ }
+
+ protected abstract TDelegate GetHandler(Action<TArgs> onNext);
+ protected abstract IDisposable AddHandler(TDelegate handler);
+
+ private Session _session;
+
+ protected override IDisposable Run(IObserver<TArgs> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var connection = default(IDisposable);
+
+ lock (_gate)
+ {
+ //
+ // A session object holds on to a single handler to the underlying event, feeding
+ // into a subject. It also ref counts the number of connections to the subject.
+ //
+ // When the ref count goes back to zero, the event handler is unregistered, and
+ // the session will reach out to reset the _session field to null under the _gate
+ // lock. Future subscriptions will cause a new session to be created.
+ //
+ if (_session == null)
+ _session = new Session(this);
+
+ connection = _session.Connect(observer);
+ }
+
+ return connection;
+ }
+
+ class Session
+ {
+ private readonly EventProducer<TDelegate, TArgs> _parent;
+ private readonly Subject<TArgs> _subject;
+
+ private SingleAssignmentDisposable _removeHandler;
+ private int _count;
+
+ public Session(EventProducer<TDelegate, TArgs> parent)
+ {
+ _parent = parent;
+ _subject = new Subject<TArgs>();
+ }
+
+ public IDisposable Connect(IObserver<TArgs> observer)
+ {
+ /*
+ * CALLERS - Ensure this is called under the lock!
+ *
+ lock (_parent._gate) */
+ {
+ //
+ // We connect the given observer to the subject first, before performing any kind
+ // of initialization which will register an event handler. This is done to ensure
+ // we don't have a time gap between adding the handler and connecting the user's
+ // subject, e.g. when the ImmediateScheduler is used.
+ //
+ // [OK] Use of unsafe Subscribe: called on a known subject implementation.
+ //
+ var connection = _subject.Subscribe/*Unsafe*/(observer);
+
+ if (++_count == 1)
+ {
+ try
+ {
+ Initialize();
+ }
+ catch (Exception exception)
+ {
+ --_count;
+ connection.Dispose();
+
+ observer.OnError(exception);
+ return Disposable.Empty;
+ }
+ }
+
+ return Disposable.Create(() =>
+ {
+ connection.Dispose();
+
+ lock (_parent._gate)
+ {
+ if (--_count == 0)
+ {
+ _parent._scheduler.Schedule(_removeHandler.Dispose);
+ _parent._session = null;
+ }
+ }
+ });
+ }
+ }
+
+ private void Initialize()
+ {
+ /*
+ * CALLERS - Ensure this is called under the lock!
+ *
+ lock (_parent._gate) */
+ {
+ //
+ // When the ref count goes to zero, no-one should be able to perform operations on
+ // the session object anymore, because it gets nulled out.
+ //
+ Debug.Assert(_removeHandler == null);
+ _removeHandler = new SingleAssignmentDisposable();
+
+ //
+ // Conversion code is supposed to be a pure function and shouldn't be run on the
+ // scheduler, but the add handler call should. Notice the scheduler can be the
+ // ImmediateScheduler, causing synchronous invocation. This is the default when
+ // no SynchronizationContext is found (see QueryLanguage.Events.cs and search for
+ // the GetSchedulerForCurrentContext method).
+ //
+ var onNext = _parent.GetHandler(_subject.OnNext);
+ _parent._scheduler.Schedule(onNext, AddHandler);
+ }
+ }
+
+ private IDisposable AddHandler(IScheduler self, TDelegate onNext)
+ {
+ var removeHandler = default(IDisposable);
+ try
+ {
+ removeHandler = _parent.AddHandler(onNext);
+ }
+ catch (Exception exception)
+ {
+ _subject.OnError(exception);
+ return Disposable.Empty;
+ }
+
+ //
+ // We don't propagate the exception to the OnError channel upon Dispose. This is
+ // not possible at this stage, because we've already auto-detached in the base
+ // class Producer implementation. Even if we would switch the OnError and auto-
+ // detach calls, it wouldn't work because the remove handler logic is scheduled
+ // on the given scheduler, causing asynchrony. We can't block waiting for the
+ // remove handler to run on the scheduler.
+ //
+ _removeHandler.Disposable = removeHandler;
+
+ return Disposable.Empty;
+ }
+ }
+ }
+
+ abstract class ClassicEventProducer<TDelegate, TArgs> : EventProducer<TDelegate, TArgs>
+ {
+ private readonly Action<TDelegate> _addHandler;
+ private readonly Action<TDelegate> _removeHandler;
+
+ public ClassicEventProducer(Action<TDelegate> addHandler, Action<TDelegate> removeHandler, IScheduler scheduler)
+ : base(scheduler)
+ {
+ _addHandler = addHandler;
+ _removeHandler = removeHandler;
+ }
+
+ protected override IDisposable AddHandler(TDelegate handler)
+ {
+ _addHandler(handler);
+ return Disposable.Create(() => _removeHandler(handler));
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/FromEventPattern.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/FromEventPattern.cs
new file mode 100644
index 0000000..76da050
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/FromEventPattern.cs
@@ -0,0 +1,143 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+using System.Reactive.Concurrency;
+using System.Reactive.Disposables;
+using System.Reflection;
+using System.Threading;
+
+//
+// BREAKING CHANGE v2 > v1.x - FromEvent[Pattern] now has an implicit SubscribeOn and Publish operation.
+//
+// See FromEvent.cs for more information.
+//
+namespace System.Reactive.Linq.Observαble
+{
+ class FromEventPattern
+ {
+ public class τ<TDelegate, TEventArgs> : ClassicEventProducer<TDelegate, EventPattern<TEventArgs>>
+#if !NO_EVENTARGS_CONSTRAINT
+ where TEventArgs : EventArgs
+#endif
+ {
+ private readonly Func<EventHandler<TEventArgs>, TDelegate> _conversion;
+
+ public τ(Action<TDelegate> addHandler, Action<TDelegate> removeHandler, IScheduler scheduler)
+ : base(addHandler, removeHandler, scheduler)
+ {
+ }
+
+ public τ(Func<EventHandler<TEventArgs>, TDelegate> conversion, Action<TDelegate> addHandler, Action<TDelegate> removeHandler, IScheduler scheduler)
+ : base(addHandler, removeHandler, scheduler)
+ {
+ _conversion = conversion;
+ }
+
+ protected override TDelegate GetHandler(Action<EventPattern<TEventArgs>> onNext)
+ {
+ var handler = default(TDelegate);
+
+ if (_conversion == null)
+ {
+ Action<object, TEventArgs> h = (sender, eventArgs) => onNext(new EventPattern<TEventArgs>(sender, eventArgs));
+ handler = ReflectionUtils.CreateDelegate<TDelegate>(h, typeof(Action<object, TEventArgs>).GetMethod("Invoke"));
+ }
+ else
+ {
+ handler = _conversion((sender, eventArgs) => onNext(new EventPattern<TEventArgs>(sender, eventArgs)));
+ }
+
+ return handler;
+ }
+ }
+
+ public class τ<TDelegate, TSender, TEventArgs> : ClassicEventProducer<TDelegate, EventPattern<TSender, TEventArgs>>
+#if !NO_EVENTARGS_CONSTRAINT
+ where TEventArgs : EventArgs
+#endif
+ {
+ public τ(Action<TDelegate> addHandler, Action<TDelegate> removeHandler, IScheduler scheduler)
+ : base(addHandler, removeHandler, scheduler)
+ {
+ }
+
+ protected override TDelegate GetHandler(Action<EventPattern<TSender, TEventArgs>> onNext)
+ {
+ Action<TSender, TEventArgs> h = (sender, eventArgs) => onNext(new EventPattern<TSender, TEventArgs>(sender, eventArgs));
+ return ReflectionUtils.CreateDelegate<TDelegate>(h, typeof(Action<TSender, TEventArgs>).GetMethod("Invoke"));
+ }
+ }
+
+ public class ρ<TSender, TEventArgs, TResult> : EventProducer<Delegate, TResult>
+ {
+ private readonly object _target;
+ private readonly Type _delegateType;
+ private readonly MethodInfo _addMethod;
+ private readonly MethodInfo _removeMethod;
+ private readonly Func<TSender, TEventArgs, TResult> _getResult;
+#if HAS_WINRT
+ private readonly bool _isWinRT;
+#endif
+
+ public ρ(object target, Type delegateType, MethodInfo addMethod, MethodInfo removeMethod, Func<TSender, TEventArgs, TResult> getResult, bool isWinRT, IScheduler scheduler)
+ : base(scheduler)
+ {
+#if HAS_WINRT
+ _isWinRT = isWinRT;
+#else
+ System.Diagnostics.Debug.Assert(!isWinRT);
+#endif
+ _target = target;
+ _delegateType = delegateType;
+ _addMethod = addMethod;
+ _removeMethod = removeMethod;
+ _getResult = getResult;
+ }
+
+ protected override Delegate GetHandler(Action<TResult> onNext)
+ {
+ Action<TSender, TEventArgs> h = (sender, eventArgs) => onNext(_getResult(sender, eventArgs));
+ return ReflectionUtils.CreateDelegate(_delegateType, h, typeof(Action<TSender, TEventArgs>).GetMethod("Invoke"));
+ }
+
+ protected override IDisposable AddHandler(Delegate handler)
+ {
+ var removeHandler = default(Action);
+
+ try
+ {
+#if HAS_WINRT
+ if (_isWinRT)
+ {
+ var token = _addMethod.Invoke(_target, new object[] { handler });
+ removeHandler = () => _removeMethod.Invoke(_target, new object[] { token });
+ }
+ else
+#endif
+ {
+ _addMethod.Invoke(_target, new object[] { handler });
+ removeHandler = () => _removeMethod.Invoke(_target, new object[] { handler });
+ }
+ }
+ catch (TargetInvocationException tie)
+ {
+ throw tie.InnerException;
+ }
+
+ return Disposable.Create(() =>
+ {
+ try
+ {
+ removeHandler();
+ }
+ catch (TargetInvocationException tie)
+ {
+ throw tie.InnerException;
+ }
+ });
+ }
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Generate.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Generate.cs
new file mode 100644
index 0000000..89ef862
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Generate.cs
@@ -0,0 +1,292 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+using System.Diagnostics;
+using System.Reactive.Concurrency;
+using System.Reactive.Disposables;
+using System.Threading;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class Generate<TState, TResult> : Producer<TResult>
+ {
+ private readonly TState _initialState;
+ private readonly Func<TState, bool> _condition;
+ private readonly Func<TState, TState> _iterate;
+ private readonly Func<TState, TResult> _resultSelector;
+ private readonly Func<TState, DateTimeOffset> _timeSelectorA;
+ private readonly Func<TState, TimeSpan> _timeSelectorR;
+ private readonly IScheduler _scheduler;
+
+ public Generate(TState initialState, Func<TState, bool> condition, Func<TState, TState> iterate, Func<TState, TResult> resultSelector, IScheduler scheduler)
+ {
+ _initialState = initialState;
+ _condition = condition;
+ _iterate = iterate;
+ _resultSelector = resultSelector;
+ _scheduler = scheduler;
+ }
+
+ public Generate(TState initialState, Func<TState, bool> condition, Func<TState, TState> iterate, Func<TState, TResult> resultSelector, Func<TState, DateTimeOffset> timeSelector, IScheduler scheduler)
+ {
+ _initialState = initialState;
+ _condition = condition;
+ _iterate = iterate;
+ _resultSelector = resultSelector;
+ _timeSelectorA = timeSelector;
+ _scheduler = scheduler;
+ }
+
+ public Generate(TState initialState, Func<TState, bool> condition, Func<TState, TState> iterate, Func<TState, TResult> resultSelector, Func<TState, TimeSpan> timeSelector, IScheduler scheduler)
+ {
+ _initialState = initialState;
+ _condition = condition;
+ _iterate = iterate;
+ _resultSelector = resultSelector;
+ _timeSelectorR = timeSelector;
+ _scheduler = scheduler;
+ }
+
+ protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ if (_timeSelectorA != null)
+ {
+ var sink = new α(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+ else if (_timeSelectorR != null)
+ {
+ var sink = new δ(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+ else
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+ }
+
+ class α : Sink<TResult>
+ {
+ private readonly Generate<TState, TResult> _parent;
+
+ public α(Generate<TState, TResult> parent, IObserver<TResult> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ private bool _first;
+ private bool _hasResult;
+ private TResult _result;
+
+ public IDisposable Run()
+ {
+ _first = true;
+ _hasResult = false;
+ _result = default(TResult);
+
+ return _parent._scheduler.Schedule(_parent._initialState, InvokeRec);
+ }
+
+ private IDisposable InvokeRec(IScheduler self, TState state)
+ {
+ 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._timeSelectorA(state);
+ }
+ }
+ catch (Exception exception)
+ {
+ base._observer.OnError(exception);
+ base.Dispose();
+ return Disposable.Empty;
+ }
+
+ if (!_hasResult)
+ {
+ base._observer.OnCompleted();
+ base.Dispose();
+ return Disposable.Empty;
+ }
+
+ return self.Schedule(state, time, InvokeRec);
+ }
+ }
+
+ class δ : Sink<TResult>
+ {
+ private readonly Generate<TState, TResult> _parent;
+
+ public δ(Generate<TState, TResult> parent, IObserver<TResult> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ private bool _first;
+ private bool _hasResult;
+ private TResult _result;
+
+ public IDisposable Run()
+ {
+ _first = true;
+ _hasResult = false;
+ _result = default(TResult);
+
+ return _parent._scheduler.Schedule(_parent._initialState, InvokeRec);
+ }
+
+ private IDisposable InvokeRec(IScheduler self, TState state)
+ {
+ 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);
+ time = _parent._timeSelectorR(state);
+ }
+ }
+ catch (Exception exception)
+ {
+ base._observer.OnError(exception);
+ base.Dispose();
+ return Disposable.Empty;
+ }
+
+ if (!_hasResult)
+ {
+ base._observer.OnCompleted();
+ base.Dispose();
+ return Disposable.Empty;
+ }
+
+ return self.Schedule(state, time, InvokeRec);
+ }
+ }
+
+ class _ : Sink<TResult>
+ {
+ private readonly Generate<TState, TResult> _parent;
+
+ public _(Generate<TState, TResult> parent, IObserver<TResult> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ private TState _state;
+ private bool _first;
+
+ public IDisposable Run()
+ {
+ _state = _parent._initialState;
+ _first = true;
+
+ var longRunning = _parent._scheduler.AsLongRunning();
+ if (longRunning != null)
+ {
+ return longRunning.ScheduleLongRunning(Loop);
+ }
+ else
+ {
+ return _parent._scheduler.Schedule(LoopRec);
+ }
+ }
+
+ private void Loop(ICancelable cancel)
+ {
+ 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();
+ }
+
+ 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.OnNext(result);
+ recurse();
+ }
+ else
+ {
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/GetEnumerator.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/GetEnumerator.cs
new file mode 100644
index 0000000..05bf20b
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/GetEnumerator.cs
@@ -0,0 +1,102 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF && !NO_CDS
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Reactive.Disposables;
+using System.Threading;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class GetEnumerator<TSource> : IEnumerator<TSource>, IObserver<TSource>
+ {
+ private readonly ConcurrentQueue<TSource> _queue;
+ private TSource _current;
+ private Exception _error;
+ private bool _done;
+ private bool _disposed;
+
+ private readonly SemaphoreSlim _gate;
+ private readonly SingleAssignmentDisposable _subscription;
+
+ public GetEnumerator()
+ {
+ _queue = new ConcurrentQueue<TSource>();
+ _gate = new SemaphoreSlim(0);
+ _subscription = new SingleAssignmentDisposable();
+ }
+
+ public IEnumerator<TSource> Run(IObservable<TSource> source)
+ {
+ //
+ // [OK] Use of unsafe Subscribe: non-pretentious exact mirror with the dual GetEnumerator method.
+ //
+ _subscription.Disposable = source.Subscribe/*Unsafe*/(this);
+ return this;
+ }
+
+ public void OnNext(TSource value)
+ {
+ _queue.Enqueue(value);
+ _gate.Release();
+ }
+
+ public void OnError(Exception error)
+ {
+ _error = error;
+ _subscription.Dispose();
+ _gate.Release();
+ }
+
+ public void OnCompleted()
+ {
+ _done = true;
+ _subscription.Dispose();
+ _gate.Release();
+ }
+
+ public bool MoveNext()
+ {
+ _gate.Wait();
+
+ if (_disposed)
+ throw new ObjectDisposedException("");
+
+ if (_queue.TryDequeue(out _current))
+ return true;
+
+ _error.ThrowIfNotNull();
+
+ Debug.Assert(_done);
+
+ _gate.Release(); // In the (rare) case the user calls MoveNext again we shouldn't block!
+ return false;
+ }
+
+ public TSource Current
+ {
+ get { return _current; }
+ }
+
+ object Collections.IEnumerator.Current
+ {
+ get { return _current; }
+ }
+
+ public void Dispose()
+ {
+ _subscription.Dispose();
+
+ _disposed = true;
+ _gate.Release();
+ }
+
+ public void Reset()
+ {
+ throw new NotSupportedException();
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/GroupBy.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/GroupBy.cs
new file mode 100644
index 0000000..1e64100
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/GroupBy.cs
@@ -0,0 +1,167 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reactive.Disposables;
+using System.Reactive.Subjects;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class GroupBy<TSource, TKey, TElement> : Producer<IGroupedObservable<TKey, TElement>>
+ {
+ private readonly IObservable<TSource> _source;
+ private readonly Func<TSource, TKey> _keySelector;
+ private readonly Func<TSource, TElement> _elementSelector;
+ private readonly IEqualityComparer<TKey> _comparer;
+
+ public GroupBy(IObservable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey> comparer)
+ {
+ _source = source;
+ _keySelector = keySelector;
+ _elementSelector = elementSelector;
+ _comparer = comparer;
+ }
+
+ private CompositeDisposable _groupDisposable;
+ private RefCountDisposable _refCountDisposable;
+
+ protected override IDisposable Run(IObserver<IGroupedObservable<TKey, TElement>> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ _groupDisposable = new CompositeDisposable();
+ _refCountDisposable = new RefCountDisposable(_groupDisposable);
+
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ _groupDisposable.Add(_source.SubscribeSafe(sink));
+
+ return _refCountDisposable;
+ }
+
+ class _ : Sink<IGroupedObservable<TKey, TElement>>, IObserver<TSource>
+ {
+ private readonly GroupBy<TSource, TKey, TElement> _parent;
+ private readonly Dictionary<TKey, ISubject<TElement>> _map;
+ private ISubject<TElement> _null;
+
+ public _(GroupBy<TSource, TKey, TElement> parent, IObserver<IGroupedObservable<TKey, TElement>> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ _map = new Dictionary<TKey, ISubject<TElement>>(_parent._comparer);
+ }
+
+ public void OnNext(TSource value)
+ {
+ var key = default(TKey);
+ try
+ {
+ key = _parent._keySelector(value);
+ }
+ catch (Exception exception)
+ {
+ Error(exception);
+ return;
+ }
+
+ var fireNewMapEntry = false;
+ var writer = default(ISubject<TElement>);
+ try
+ {
+ //
+ // Note: The box instruction in the IL will be erased by the JIT in case T is
+ // a value type. In fact, the whole if block will go away and we'll end
+ // up with nothing but the TryGetValue check below.
+ //
+ // // var fireNewMapEntry = false;
+ // C:\Projects\Rx\Rx\Experimental\Main\Source\Rx\System.Reactive.Linq\Reactive\Linq\Observable\GroupBy.cs @ 67:
+ // 000007fb`6d544b80 48c7452800000000 mov qword ptr [rbp+28h],0
+ //
+ // // var writer = default(ISubject<TElement>);
+ // C:\Projects\Rx\Rx\Experimental\Main\Source\Rx\System.Reactive.Linq\Reactive\Linq\Observable\GroupBy.cs @ 66:
+ // 000007fb`6d544b88 c6453400 mov byte ptr [rbp+34h],0
+ //
+ // // if (!_map.TryGetValue(key, out writer))
+ // C:\Projects\Rx\Rx\Experimental\Main\Source\Rx\System.Reactive.Linq\Reactive\Linq\Observable\GroupBy.cs @ 86:
+ // 000007fb`6d544b8c 488b4560 mov rax,qword ptr [rbp+60h]
+ // ...
+ //
+ if (key == null)
+ {
+ if (_null == null)
+ {
+ _null = new Subject<TElement>();
+ fireNewMapEntry = true;
+ }
+
+ writer = _null;
+ }
+ else
+ {
+ if (!_map.TryGetValue(key, out writer))
+ {
+ writer = new Subject<TElement>();
+ _map.Add(key, writer);
+ fireNewMapEntry = true;
+ }
+ }
+ }
+ catch (Exception exception)
+ {
+ Error(exception);
+ return;
+ }
+
+ if (fireNewMapEntry)
+ {
+ var group = new GroupedObservable<TKey, TElement>(key, writer, _parent._refCountDisposable);
+ _observer.OnNext(group);
+ }
+
+ var element = default(TElement);
+ try
+ {
+ element = _parent._elementSelector(value);
+ }
+ catch (Exception exception)
+ {
+ Error(exception);
+ return;
+ }
+
+ writer.OnNext(element);
+ }
+
+ public void OnError(Exception error)
+ {
+ Error(error);
+ }
+
+ public void OnCompleted()
+ {
+ if (_null != null)
+ _null.OnCompleted();
+
+ foreach (var w in _map.Values)
+ w.OnCompleted();
+
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+
+ private void Error(Exception exception)
+ {
+ if (_null != null)
+ _null.OnError(exception);
+
+ foreach (var w in _map.Values)
+ w.OnError(exception);
+
+ base._observer.OnError(exception);
+ base.Dispose();
+ }
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/GroupByUntil.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/GroupByUntil.cs
new file mode 100644
index 0000000..7d91f73
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/GroupByUntil.cs
@@ -0,0 +1,374 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+ #if !NO_PERF
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reactive.Disposables;
+using System.Reactive.Subjects;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class GroupByUntil<TSource, TKey, TElement, TDuration> : Producer<IGroupedObservable<TKey, TElement>>
+ {
+ private readonly IObservable<TSource> _source;
+ private readonly Func<TSource, TKey> _keySelector;
+ private readonly Func<TSource, TElement> _elementSelector;
+ private readonly Func<IGroupedObservable<TKey, TElement>, IObservable<TDuration>> _durationSelector;
+ private readonly IEqualityComparer<TKey> _comparer;
+
+ public GroupByUntil(IObservable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, Func<IGroupedObservable<TKey, TElement>, IObservable<TDuration>> durationSelector, IEqualityComparer<TKey> comparer)
+ {
+ _source = source;
+ _keySelector = keySelector;
+ _elementSelector = elementSelector;
+ _durationSelector = durationSelector;
+ _comparer = comparer;
+ }
+
+ private CompositeDisposable _groupDisposable;
+ private RefCountDisposable _refCountDisposable;
+
+ protected override IDisposable Run(IObserver<IGroupedObservable<TKey, TElement>> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ _groupDisposable = new CompositeDisposable();
+ _refCountDisposable = new RefCountDisposable(_groupDisposable);
+
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ _groupDisposable.Add(_source.SubscribeSafe(sink));
+
+ return _refCountDisposable;
+ }
+
+ class _ : Sink<IGroupedObservable<TKey, TElement>>, IObserver<TSource>
+ {
+ private readonly GroupByUntil<TSource, TKey, TElement, TDuration> _parent;
+ private readonly Map<TKey, ISubject<TElement>> _map;
+ private ISubject<TElement> _null;
+ private object _nullGate;
+
+ public _(GroupByUntil<TSource, TKey, TElement, TDuration> parent, IObserver<IGroupedObservable<TKey, TElement>> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ _map = new Map<TKey, ISubject<TElement>>(_parent._comparer);
+ _nullGate = new object();
+ }
+
+ public void OnNext(TSource value)
+ {
+ var key = default(TKey);
+ try
+ {
+ key = _parent._keySelector(value);
+ }
+ catch (Exception exception)
+ {
+ Error(exception);
+ return;
+ }
+
+ var fireNewMapEntry = false;
+ var writer = default(ISubject<TElement>);
+ try
+ {
+ //
+ // Note: The box instruction in the IL will be erased by the JIT in case T is
+ // a value type. In fact, the whole if block will go away and we'll end
+ // up with nothing but the GetOrAdd call below.
+ //
+ // See GroupBy for more information and confirmation of this fact using
+ // the SOS debugger extension.
+ //
+ if (key == null)
+ {
+ lock (_nullGate)
+ {
+ if (_null == null)
+ {
+ _null = new Subject<TElement>();
+ fireNewMapEntry = true;
+ }
+
+ writer = _null;
+ }
+ }
+ else
+ {
+ writer = _map.GetOrAdd(key, () => new Subject<TElement>(), out fireNewMapEntry);
+ }
+ }
+ catch (Exception exception)
+ {
+ Error(exception);
+ return;
+ }
+
+ if (fireNewMapEntry)
+ {
+ var group = new GroupedObservable<TKey, TElement>(key, writer, _parent._refCountDisposable);
+
+ var duration = default(IObservable<TDuration>);
+
+ var durationGroup = new GroupedObservable<TKey, TElement>(key, writer);
+ try
+ {
+ duration = _parent._durationSelector(durationGroup);
+ }
+ catch (Exception exception)
+ {
+ Error(exception);
+ return;
+ }
+
+ lock (base._observer)
+ base._observer.OnNext(group);
+
+ var md = new SingleAssignmentDisposable();
+ _parent._groupDisposable.Add(md);
+ md.Disposable = duration.SubscribeSafe(new δ(this, key, writer, md));
+ }
+
+ var element = default(TElement);
+ try
+ {
+ element = _parent._elementSelector(value);
+ }
+ catch (Exception exception)
+ {
+ Error(exception);
+ return;
+ }
+
+ //
+ // ISSUE: Rx v1.x shipped without proper handling of the case where the duration
+ // sequence fires concurrently with the OnNext code path here. In such a
+ // case, the subject can be completed before we get a chance to send out
+ // a new element. However, a resurrected group for the same key won't get
+ // to see the element either. To guard against this case, we'd have to
+ // check whether the OnNext call below lost the race, and resurrect a new
+ // group if needed. Unfortunately, this complicates matters when the
+ // duration selector triggers synchronously (e.g. Return or Empty), which
+ // causes the group to terminate immediately. We should not get stuck in
+ // this case, repeatedly trying to resurrect a group that always ends
+ // before we can send the element into it. Also, users may expect this
+ // base case to mean no elements will ever be produced, so sending the
+ // element into the group before starting the duration sequence may not
+ // be a good idea either. For the time being, we'll leave this as-is and
+ // revisit the behavior for vNext. Nonetheless, we'll add synchronization
+ // to ensure no concurrent calls to the subject are made.
+ //
+ lock (writer)
+ writer.OnNext(element);
+ }
+
+ class δ : IObserver<TDuration>
+ {
+ private readonly _ _parent;
+ private readonly TKey _key;
+ private readonly ISubject<TElement> _writer;
+ private readonly IDisposable _self;
+
+ public δ(_ parent, TKey key, ISubject<TElement> writer, IDisposable self)
+ {
+ _parent = parent;
+ _key = key;
+ _writer = writer;
+ _self = self;
+ }
+
+ public void OnNext(TDuration value)
+ {
+ OnCompleted();
+ }
+
+ public void OnError(Exception error)
+ {
+ _parent.Error(error);
+ _self.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ if (_key == null)
+ {
+ var @null = default(ISubject<TElement>);
+ lock (_parent._nullGate)
+ {
+ @null = _parent._null;
+ _parent._null = null;
+ }
+
+ lock (@null)
+ @null.OnCompleted();
+ }
+ else
+ {
+ if (_parent._map.Remove(_key))
+ {
+ lock (_writer)
+ _writer.OnCompleted();
+ }
+ }
+
+ _parent._parent._groupDisposable.Remove(_self);
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ Error(error);
+ }
+
+ public void OnCompleted()
+ {
+ //
+ // NOTE: A race with OnCompleted triggered by a duration selector is fine when
+ // using Subject<T>. It will transition into a terminal state, making one
+ // of the two calls a no-op by swapping in a DoneObserver<T>.
+ //
+ var @null = default(ISubject<TElement>);
+ lock (_nullGate)
+ @null = _null;
+
+ if (@null != null)
+ @null.OnCompleted();
+
+ foreach (var w in _map.Values)
+ w.OnCompleted();
+
+ lock (base._observer)
+ base._observer.OnCompleted();
+
+ base.Dispose();
+ }
+
+ private void Error(Exception exception)
+ {
+ //
+ // NOTE: A race with OnCompleted triggered by a duration selector is fine when
+ // using Subject<T>. It will transition into a terminal state, making one
+ // of the two calls a no-op by swapping in a DoneObserver<T>.
+ //
+ var @null = default(ISubject<TElement>);
+ lock (_nullGate)
+ @null = _null;
+
+ if (@null != null)
+ @null.OnError(exception);
+
+ foreach (var w in _map.Values)
+ w.OnError(exception);
+
+ lock (base._observer)
+ base._observer.OnError(exception);
+
+ base.Dispose();
+ }
+ }
+ }
+
+#if !NO_CDS
+ class Map<TKey, TValue>
+ {
+ private readonly System.Collections.Concurrent.ConcurrentDictionary<TKey, TValue> _map;
+
+ public Map(IEqualityComparer<TKey> comparer)
+ {
+ _map = new System.Collections.Concurrent.ConcurrentDictionary<TKey, TValue>(comparer);
+ }
+
+ public TValue GetOrAdd(TKey key, Func<TValue> valueFactory, out bool added)
+ {
+ added = false;
+
+ var value = default(TValue);
+ var newValue = default(TValue);
+ var hasNewValue = false;
+ while (true)
+ {
+ if (_map.TryGetValue(key, out value))
+ break;
+
+ if (!hasNewValue)
+ {
+ newValue = valueFactory();
+ hasNewValue = true;
+ }
+
+ if (_map.TryAdd(key, newValue))
+ {
+ added = true;
+ value = newValue;
+ break;
+ }
+ }
+
+ return value;
+ }
+
+ public IEnumerable<TValue> Values
+ {
+ get
+ {
+ return _map.Values.ToArray();
+ }
+ }
+
+ public bool Remove(TKey key)
+ {
+ var value = default(TValue);
+ return _map.TryRemove(key, out value);
+ }
+ }
+#else
+ class Map<TKey, TValue>
+ {
+ private readonly Dictionary<TKey, TValue> _map;
+
+ public Map(IEqualityComparer<TKey> comparer)
+ {
+ _map = new Dictionary<TKey, TValue>(comparer);
+ }
+
+ public TValue GetOrAdd(TKey key, Func<TValue> valueFactory, out bool added)
+ {
+ lock (_map)
+ {
+ added = false;
+
+ var value = default(TValue);
+ if (!_map.TryGetValue(key, out value))
+ {
+ value = valueFactory();
+ _map.Add(key, value);
+ added = true;
+ }
+
+ return value;
+ }
+ }
+
+ public IEnumerable<TValue> Values
+ {
+ get
+ {
+ lock (_map)
+ {
+ return _map.Values.ToArray();
+ }
+ }
+ }
+
+ public bool Remove(TKey key)
+ {
+ lock (_map)
+ {
+ return _map.Remove(key);
+ }
+ }
+ }
+#endif
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/GroupJoin.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/GroupJoin.cs
new file mode 100644
index 0000000..66e49be
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/GroupJoin.cs
@@ -0,0 +1,302 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+using System.Collections.Generic;
+using System.Reactive.Disposables;
+using System.Reactive.Subjects;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class GroupJoin<TLeft, TRight, TLeftDuration, TRightDuration, TResult> : Producer<TResult>
+ {
+ private readonly IObservable<TLeft> _left;
+ private readonly IObservable<TRight> _right;
+ private readonly Func<TLeft, IObservable<TLeftDuration>> _leftDurationSelector;
+ private readonly Func<TRight, IObservable<TRightDuration>> _rightDurationSelector;
+ private readonly Func<TLeft, IObservable<TRight>, TResult> _resultSelector;
+
+ public GroupJoin(IObservable<TLeft> left, IObservable<TRight> right, Func<TLeft, IObservable<TLeftDuration>> leftDurationSelector, Func<TRight, IObservable<TRightDuration>> rightDurationSelector, Func<TLeft, IObservable<TRight>, TResult> resultSelector)
+ {
+ _left = left;
+ _right = right;
+ _leftDurationSelector = leftDurationSelector;
+ _rightDurationSelector = rightDurationSelector;
+ _resultSelector = resultSelector;
+ }
+
+ protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+
+ class _ : Sink<TResult>
+ {
+ private readonly GroupJoin<TLeft, TRight, TLeftDuration, TRightDuration, TResult> _parent;
+
+ public _(GroupJoin<TLeft, TRight, TLeftDuration, TRightDuration, TResult> parent, IObserver<TResult> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ private object _gate;
+ private CompositeDisposable _group;
+ private RefCountDisposable _refCount;
+
+ private int _leftID;
+ private Dictionary<int, IObserver<TRight>> _leftMap;
+
+ private int _rightID;
+ private Dictionary<int, TRight> _rightMap;
+
+ public IDisposable Run()
+ {
+ _gate = new object();
+ _group = new CompositeDisposable();
+ _refCount = new RefCountDisposable(_group);
+
+ var leftSubscription = new SingleAssignmentDisposable();
+ _group.Add(leftSubscription);
+ _leftID = 0;
+ _leftMap = new Dictionary<int, IObserver<TRight>>();
+
+ var rightSubscription = new SingleAssignmentDisposable();
+ _group.Add(rightSubscription);
+ _rightID = 0;
+ _rightMap = new Dictionary<int, TRight>();
+
+ leftSubscription.Disposable = _parent._left.SubscribeSafe(new λ(this, leftSubscription));
+ rightSubscription.Disposable = _parent._right.SubscribeSafe(new ρ(this, rightSubscription));
+
+ return _refCount;
+ }
+
+ class λ : IObserver<TLeft>
+ {
+ private readonly _ _parent;
+ private readonly IDisposable _self;
+
+ public λ(_ parent, IDisposable self)
+ {
+ _parent = parent;
+ _self = self;
+ }
+
+ private void Expire(int id, IObserver<TRight> group, IDisposable resource)
+ {
+ lock (_parent._gate)
+ if (_parent._leftMap.Remove(id))
+ group.OnCompleted();
+
+ _parent._group.Remove(resource);
+ }
+
+ public void OnNext(TLeft value)
+ {
+ var s = new Subject<TRight>();
+ var id = 0;
+ lock (_parent._gate)
+ {
+ id = _parent._leftID++;
+ _parent._leftMap.Add(id, s);
+ }
+
+ var window = new WindowObservable<TRight>(s, _parent._refCount);
+
+ // BREAKING CHANGE v2 > v1.x - Order of evaluation or the _leftDurationSelector and _resultSelector now consistent with Join.
+ var md = new SingleAssignmentDisposable();
+ _parent._group.Add(md);
+
+ var duration = default(IObservable<TLeftDuration>);
+ try
+ {
+ duration = _parent._parent._leftDurationSelector(value);
+ }
+ catch (Exception exception)
+ {
+ OnError(exception);
+ return;
+ }
+
+ // BREAKING CHANGE v2 > v1.x - The duration sequence is subscribed to before the result sequence is evaluated.
+ md.Disposable = duration.SubscribeSafe(new δ(this, id, s, md));
+
+ var result = default(TResult);
+ try
+ {
+ result = _parent._parent._resultSelector(value, window);
+ }
+ catch (Exception exception)
+ {
+ OnError(exception);
+ return;
+ }
+
+ lock (_parent._gate)
+ {
+ _parent._observer.OnNext(result);
+
+ foreach (var rightValue in _parent._rightMap.Values)
+ {
+ s.OnNext(rightValue);
+ }
+ }
+ }
+
+ class δ : IObserver<TLeftDuration>
+ {
+ private readonly λ _parent;
+ private readonly int _id;
+ private readonly IObserver<TRight> _group;
+ private readonly IDisposable _self;
+
+ public δ(λ parent, int id, IObserver<TRight> group, IDisposable self)
+ {
+ _parent = parent;
+ _id = id;
+ _group = group;
+ _self = self;
+ }
+
+ public void OnNext(TLeftDuration value)
+ {
+ _parent.Expire(_id, _group, _self);
+ }
+
+ public void OnError(Exception error)
+ {
+ _parent.OnError(error);
+ }
+
+ public void OnCompleted()
+ {
+ _parent.Expire(_id, _group, _self);
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ lock (_parent._gate)
+ {
+ foreach (var o in _parent._leftMap.Values)
+ o.OnError(error);
+
+ _parent._observer.OnError(error);
+ _parent.Dispose();
+ }
+ }
+
+ public void OnCompleted()
+ {
+ lock (_parent._gate)
+ {
+ _parent._observer.OnCompleted();
+ _parent.Dispose();
+ }
+
+ _self.Dispose();
+ }
+ }
+
+ class ρ : IObserver<TRight>
+ {
+ private readonly _ _parent;
+ private readonly IDisposable _self;
+
+ public ρ(_ parent, IDisposable self)
+ {
+ _parent = parent;
+ _self = self;
+ }
+
+ private void Expire(int id, IDisposable resource)
+ {
+ lock (_parent._gate)
+ _parent._rightMap.Remove(id);
+
+ _parent._group.Remove(resource);
+ }
+
+ public void OnNext(TRight value)
+ {
+ var id = 0;
+ lock (_parent._gate)
+ {
+ id = _parent._rightID++;
+ _parent._rightMap.Add(id, value);
+ }
+
+ var md = new SingleAssignmentDisposable();
+ _parent._group.Add(md);
+
+ var duration = default(IObservable<TRightDuration>);
+ try
+ {
+ duration = _parent._parent._rightDurationSelector(value);
+ }
+ catch (Exception exception)
+ {
+ OnError(exception);
+ return;
+ }
+ md.Disposable = duration.SubscribeSafe(new δ(this, id, md));
+
+ lock (_parent._gate)
+ {
+ foreach (var o in _parent._leftMap.Values)
+ o.OnNext(value);
+ }
+ }
+
+ class δ : IObserver<TRightDuration>
+ {
+ private readonly ρ _parent;
+ private readonly int _id;
+ private readonly IDisposable _self;
+
+ public δ(ρ parent, int id, IDisposable self)
+ {
+ _parent = parent;
+ _id = id;
+ _self = self;
+ }
+
+ public void OnNext(TRightDuration value)
+ {
+ _parent.Expire(_id, _self);
+ }
+
+ public void OnError(Exception error)
+ {
+ _parent.OnError(error);
+ }
+
+ public void OnCompleted()
+ {
+ _parent.Expire(_id, _self);
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ lock (_parent._gate)
+ {
+ foreach (var o in _parent._leftMap.Values)
+ o.OnError(error);
+ _parent._observer.OnError(error);
+ _parent.Dispose();
+ }
+ }
+
+ public void OnCompleted()
+ {
+ _self.Dispose();
+ }
+ }
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/If.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/If.cs
new file mode 100644
index 0000000..8b1804a
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/If.cs
@@ -0,0 +1,81 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+using System.Collections.Generic;
+using System.Reactive.Disposables;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class If<TResult> : Producer<TResult>, IEvaluatableObservable<TResult>
+ {
+ private readonly Func<bool> _condition;
+ private readonly IObservable<TResult> _thenSource;
+ private readonly IObservable<TResult> _elseSource;
+
+ public If(Func<bool> condition, IObservable<TResult> thenSource, IObservable<TResult> elseSource)
+ {
+ _condition = condition;
+ _thenSource = thenSource;
+ _elseSource = elseSource;
+ }
+
+ public IObservable<TResult> Eval()
+ {
+ return _condition() ? _thenSource : _elseSource;
+ }
+
+ protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+
+ class _ : Sink<TResult>, IObserver<TResult>
+ {
+ private readonly If<TResult> _parent;
+
+ public _(If<TResult> parent, IObserver<TResult> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ public IDisposable Run()
+ {
+ var result = default(IObservable<TResult>);
+ try
+ {
+ result = _parent.Eval();
+ }
+ catch (Exception exception)
+ {
+ base._observer.OnError(exception);
+ base.Dispose();
+ return Disposable.Empty;
+ }
+
+ return result.SubscribeSafe(this);
+ }
+
+ public void OnNext(TResult value)
+ {
+ base._observer.OnNext(value);
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+}
+#endif
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/IgnoreElements.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/IgnoreElements.cs
new file mode 100644
index 0000000..65441bd
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/IgnoreElements.cs
@@ -0,0 +1,54 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class IgnoreElements<TSource> : Producer<TSource>
+ {
+ private readonly IObservable<TSource> _source;
+
+ public IgnoreElements(IObservable<TSource> source)
+ {
+ _source = source;
+ }
+
+ public IObservable<TSource> Ω()
+ {
+ return this;
+ }
+
+ protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+
+ class _ : Sink<TSource>, IObserver<TSource>
+ {
+ public _(IObserver<TSource> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ }
+
+ public void OnNext(TSource value)
+ {
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/IsEmpty.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/IsEmpty.cs
new file mode 100644
index 0000000..674c6f8
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/IsEmpty.cs
@@ -0,0 +1,53 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class IsEmpty<TSource> : Producer<bool>
+ {
+ private readonly IObservable<TSource> _source;
+
+ public IsEmpty(IObservable<TSource> source)
+ {
+ _source = source;
+ }
+
+ protected override IDisposable Run(IObserver<bool> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+
+ class _ : Sink<bool>, IObserver<TSource>
+ {
+ public _(IObserver<bool> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ }
+
+ public void OnNext(TSource value)
+ {
+ 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(true);
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Join.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Join.cs
new file mode 100644
index 0000000..13e6ad2
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Join.cs
@@ -0,0 +1,336 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+using System.Collections.Generic;
+using System.Reactive.Disposables;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class Join<TLeft, TRight, TLeftDuration, TRightDuration, TResult> : Producer<TResult>
+ {
+ private readonly IObservable<TLeft> _left;
+ private readonly IObservable<TRight> _right;
+ private readonly Func<TLeft, IObservable<TLeftDuration>> _leftDurationSelector;
+ private readonly Func<TRight, IObservable<TRightDuration>> _rightDurationSelector;
+ private readonly Func<TLeft, TRight, TResult> _resultSelector;
+
+ public Join(IObservable<TLeft> left, IObservable<TRight> right, Func<TLeft, IObservable<TLeftDuration>> leftDurationSelector, Func<TRight, IObservable<TRightDuration>> rightDurationSelector, Func<TLeft, TRight, TResult> resultSelector)
+ {
+ _left = left;
+ _right = right;
+ _leftDurationSelector = leftDurationSelector;
+ _rightDurationSelector = rightDurationSelector;
+ _resultSelector = resultSelector;
+ }
+
+ protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+
+ class _ : Sink<TResult>
+ {
+ private readonly Join<TLeft, TRight, TLeftDuration, TRightDuration, TResult> _parent;
+
+ public _(Join<TLeft, TRight, TLeftDuration, TRightDuration, TResult> parent, IObserver<TResult> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ private object _gate;
+ private CompositeDisposable _group;
+
+ private bool _leftDone;
+ private int _leftID;
+ private Dictionary<int, TLeft> _leftMap;
+
+ private bool _rightDone;
+ private int _rightID;
+ private Dictionary<int, TRight> _rightMap;
+
+ public IDisposable Run()
+ {
+ _gate = new object();
+ _group = new CompositeDisposable();
+
+ var leftSubscription = new SingleAssignmentDisposable();
+ _group.Add(leftSubscription);
+ _leftDone = false;
+ _leftID = 0;
+ _leftMap = new Dictionary<int, TLeft>();
+
+ var rightSubscription = new SingleAssignmentDisposable();
+ _group.Add(rightSubscription);
+ _rightDone = false;
+ _rightID = 0;
+ _rightMap = new Dictionary<int, TRight>();
+
+ leftSubscription.Disposable = _parent._left.SubscribeSafe(new λ(this, leftSubscription));
+ rightSubscription.Disposable = _parent._right.SubscribeSafe(new ρ(this, rightSubscription));
+
+ return _group;
+ }
+
+ class λ : IObserver<TLeft>
+ {
+ private readonly _ _parent;
+ private readonly IDisposable _self;
+
+ public λ(_ parent, IDisposable self)
+ {
+ _parent = parent;
+ _self = self;
+ }
+
+ private void Expire(int id, IDisposable resource)
+ {
+ lock (_parent._gate)
+ {
+ if (_parent._leftMap.Remove(id) && _parent._leftMap.Count == 0 && _parent._leftDone)
+ {
+ _parent._observer.OnCompleted();
+ _parent.Dispose();
+ }
+ }
+
+ _parent._group.Remove(resource);
+ }
+
+ public void OnNext(TLeft value)
+ {
+ var id = 0;
+ lock (_parent._gate)
+ {
+ id = _parent._leftID++;
+ _parent._leftMap.Add(id, value);
+ }
+
+ var md = new SingleAssignmentDisposable();
+ _parent._group.Add(md);
+
+ var duration = default(IObservable<TLeftDuration>);
+ try
+ {
+ duration = _parent._parent._leftDurationSelector(value);
+ }
+ catch (Exception exception)
+ {
+ _parent._observer.OnError(exception);
+ _parent.Dispose();
+ return;
+ }
+
+ md.Disposable = duration.SubscribeSafe(new δ(this, id, md));
+
+ lock (_parent._gate)
+ {
+ foreach (var rightValue in _parent._rightMap.Values)
+ {
+ var result = default(TResult);
+ try
+ {
+ result = _parent._parent._resultSelector(value, rightValue);
+ }
+ catch (Exception exception)
+ {
+ _parent._observer.OnError(exception);
+ _parent.Dispose();
+ return;
+ }
+
+ _parent._observer.OnNext(result);
+ }
+ }
+ }
+
+ class δ : IObserver<TLeftDuration>
+ {
+ private readonly λ _parent;
+ private readonly int _id;
+ private readonly IDisposable _self;
+
+ public δ(λ parent, int id, IDisposable self)
+ {
+ _parent = parent;
+ _id = id;
+ _self = self;
+ }
+
+ public void OnNext(TLeftDuration value)
+ {
+ _parent.Expire(_id, _self);
+ }
+
+ public void OnError(Exception error)
+ {
+ _parent.OnError(error);
+ }
+
+ public void OnCompleted()
+ {
+ _parent.Expire(_id, _self);
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ lock (_parent._gate)
+ {
+ _parent._observer.OnError(error);
+ _parent.Dispose();
+ }
+ }
+
+ public void OnCompleted()
+ {
+ lock (_parent._gate)
+ {
+ _parent._leftDone = true;
+ if (_parent._rightDone || _parent._leftMap.Count == 0)
+ {
+ _parent._observer.OnCompleted();
+ _parent.Dispose();
+ }
+ else
+ {
+ _self.Dispose();
+ }
+ }
+ }
+ }
+
+ class ρ : IObserver<TRight>
+ {
+ private readonly _ _parent;
+ private readonly IDisposable _self;
+
+ public ρ(_ parent, IDisposable self)
+ {
+ _parent = parent;
+ _self = self;
+ }
+
+ private void Expire(int id, IDisposable resource)
+ {
+ lock (_parent._gate)
+ {
+ if (_parent._rightMap.Remove(id) && _parent._rightMap.Count == 0 && _parent._rightDone)
+ {
+ _parent._observer.OnCompleted();
+ _parent.Dispose();
+ }
+ }
+
+ _parent._group.Remove(resource);
+ }
+
+ public void OnNext(TRight value)
+ {
+ var id = 0;
+ lock (_parent._gate)
+ {
+ id = _parent._rightID++;
+ _parent._rightMap.Add(id, value);
+ }
+
+ var md = new SingleAssignmentDisposable();
+ _parent._group.Add(md);
+
+ var duration = default(IObservable<TRightDuration>);
+ try
+ {
+ duration = _parent._parent._rightDurationSelector(value);
+ }
+ catch (Exception exception)
+ {
+ _parent._observer.OnError(exception);
+ _parent.Dispose();
+ return;
+ }
+
+ md.Disposable = duration.SubscribeSafe(new δ(this, id, md));
+
+ lock (_parent._gate)
+ {
+ foreach (var leftValue in _parent._leftMap.Values)
+ {
+ var result = default(TResult);
+ try
+ {
+ result = _parent._parent._resultSelector(leftValue, value);
+ }
+ catch (Exception exception)
+ {
+ _parent._observer.OnError(exception);
+ _parent.Dispose();
+ return;
+ }
+
+ _parent._observer.OnNext(result);
+ }
+ }
+ }
+
+ class δ : IObserver<TRightDuration>
+ {
+ private readonly ρ _parent;
+ private readonly int _id;
+ private readonly IDisposable _self;
+
+ public δ(ρ parent, int id, IDisposable self)
+ {
+ _parent = parent;
+ _id = id;
+ _self = self;
+ }
+
+ public void OnNext(TRightDuration value)
+ {
+ _parent.Expire(_id, _self);
+ }
+
+ public void OnError(Exception error)
+ {
+ _parent.OnError(error);
+ }
+
+ public void OnCompleted()
+ {
+ _parent.Expire(_id, _self);
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ lock (_parent._gate)
+ {
+ _parent._observer.OnError(error);
+ _parent.Dispose();
+ }
+ }
+
+ public void OnCompleted()
+ {
+ lock (_parent._gate)
+ {
+ _parent._rightDone = true;
+ if (_parent._leftDone || _parent._rightMap.Count == 0)
+ {
+ _parent._observer.OnCompleted();
+ _parent.Dispose();
+ }
+ else
+ {
+ _self.Dispose();
+ }
+ }
+ }
+ }
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/LastAsync.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/LastAsync.cs
new file mode 100644
index 0000000..1ecd930
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/LastAsync.cs
@@ -0,0 +1,140 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class LastAsync<TSource> : Producer<TSource>
+ {
+ private readonly IObservable<TSource> _source;
+ private readonly Func<TSource, bool> _predicate;
+ private readonly bool _throwOnEmpty;
+
+ public LastAsync(IObservable<TSource> source, Func<TSource, bool> predicate, bool throwOnEmpty)
+ {
+ _source = source;
+ _predicate = predicate;
+ _throwOnEmpty = throwOnEmpty;
+ }
+
+ protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ if (_predicate != null)
+ {
+ var sink = new π(this, observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+ else
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+ }
+
+ class _ : Sink<TSource>, IObserver<TSource>
+ {
+ private readonly LastAsync<TSource> _parent;
+ private TSource _value;
+ private bool _seenValue;
+
+ public _(LastAsync<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+
+ _value = default(TSource);
+ _seenValue = false;
+ }
+
+ public void OnNext(TSource value)
+ {
+ _value = value;
+ _seenValue = true;
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ if (!_seenValue && _parent._throwOnEmpty)
+ {
+ base._observer.OnError(new InvalidOperationException(Strings_Linq.NO_ELEMENTS));
+ }
+ else
+ {
+ base._observer.OnNext(_value);
+ base._observer.OnCompleted();
+ }
+
+ base.Dispose();
+ }
+ }
+
+ class π : Sink<TSource>, IObserver<TSource>
+ {
+ private readonly LastAsync<TSource> _parent;
+ private TSource _value;
+ private bool _seenValue;
+
+ public π(LastAsync<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+
+ _value = default(TSource);
+ _seenValue = false;
+ }
+
+ public void OnNext(TSource value)
+ {
+ var b = false;
+
+ try
+ {
+ b = _parent._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)
+ {
+ base._observer.OnError(new InvalidOperationException(Strings_Linq.NO_MATCHING_ELEMENTS));
+ }
+ else
+ {
+ base._observer.OnNext(_value);
+ base._observer.OnCompleted();
+ }
+
+ base.Dispose();
+ }
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Latest.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Latest.cs
new file mode 100644
index 0000000..2699797
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Latest.cs
@@ -0,0 +1,145 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+using System.Collections.Generic;
+using System.Reactive.Threading;
+using System.Threading;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class Latest<TSource> : PushToPullAdapter<TSource, TSource>
+ {
+ public Latest(IObservable<TSource> source)
+ : base(source)
+ {
+ }
+
+ protected override PushToPullSink<TSource, TSource> Run(IDisposable subscription)
+ {
+ return new _(subscription);
+ }
+
+ class _ : PushToPullSink<TSource, TSource>
+ {
+ private readonly object _gate;
+
+#if !NO_CDS
+ private readonly SemaphoreSlim _semaphore;
+#else
+ private readonly Semaphore _semaphore;
+#endif
+
+ public _(IDisposable subscription)
+ : base(subscription)
+ {
+ _gate = new object();
+
+#if !NO_CDS
+ _semaphore = new SemaphoreSlim(0, 1);
+#else
+ _semaphore = new Semaphore(0, 1);
+#endif
+ }
+
+ private bool _notificationAvailable;
+ private NotificationKind _kind;
+ private TSource _value;
+ private Exception _error;
+
+ public override void OnNext(TSource value)
+ {
+ var lackedValue = false;
+ lock (_gate)
+ {
+ lackedValue = !_notificationAvailable;
+ _notificationAvailable = true;
+ _kind = NotificationKind.OnNext;
+ _value = value;
+ }
+
+ if (lackedValue)
+ _semaphore.Release();
+ }
+
+ public override void OnError(Exception error)
+ {
+ base.Dispose();
+
+ var lackedValue = false;
+ lock (_gate)
+ {
+ lackedValue = !_notificationAvailable;
+ _notificationAvailable = true;
+ _kind = NotificationKind.OnError;
+ _error = error;
+ }
+
+ if (lackedValue)
+ _semaphore.Release();
+ }
+
+ public override void OnCompleted()
+ {
+ base.Dispose();
+
+ var lackedValue = false;
+ lock (_gate)
+ {
+ lackedValue = !_notificationAvailable;
+ _notificationAvailable = true;
+ _kind = NotificationKind.OnCompleted;
+ }
+
+ if (lackedValue)
+ _semaphore.Release();
+ }
+
+ public override bool TryMoveNext(out TSource current)
+ {
+ var kind = default(NotificationKind);
+ var value = default(TSource);
+ var error = default(Exception);
+
+#if !NO_CDS
+ _semaphore.Wait();
+#else
+ _semaphore.WaitOne();
+#endif
+
+ lock (_gate)
+ {
+ kind = _kind;
+
+ switch (kind)
+ {
+ case NotificationKind.OnNext:
+ value = _value;
+ break;
+ case NotificationKind.OnError:
+ error = _error;
+ break;
+ }
+
+ _notificationAvailable = false;
+ }
+
+ switch (kind)
+ {
+ case NotificationKind.OnNext:
+ current = _value;
+ return true;
+ case NotificationKind.OnError:
+ error.Throw();
+ break;
+ case NotificationKind.OnCompleted:
+ break;
+ }
+
+ current = default(TSource);
+ return false;
+ }
+ }
+ }
+}
+#endif
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/LongCount.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/LongCount.cs
new file mode 100644
index 0000000..0108e18
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/LongCount.cs
@@ -0,0 +1,124 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class LongCount<TSource> : Producer<long>
+ {
+ private readonly IObservable<TSource> _source;
+ private readonly Func<TSource, bool> _predicate;
+
+ public LongCount(IObservable<TSource> source)
+ {
+ _source = source;
+ }
+
+ public LongCount(IObservable<TSource> source, Func<TSource, bool> predicate)
+ {
+ _source = source;
+ _predicate = predicate;
+ }
+
+ protected override IDisposable Run(IObserver<long> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ if (_predicate == null)
+ {
+ var sink = new _(observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+ else
+ {
+ var sink = new π(this, observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+ }
+
+ class _ : Sink<long>, IObserver<TSource>
+ {
+ private long _count;
+
+ public _(IObserver<long> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _count = 0L;
+ }
+
+ public void OnNext(TSource value)
+ {
+ try
+ {
+ checked
+ {
+ _count++;
+ }
+ }
+ catch (Exception ex)
+ {
+ base._observer.OnError(ex);
+ 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();
+ }
+ }
+
+ class π : Sink<long>, IObserver<TSource>
+ {
+ private readonly LongCount<TSource> _parent;
+ private long _count;
+
+ public π(LongCount<TSource> parent, IObserver<long> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ _count = 0L;
+ }
+
+ public void OnNext(TSource value)
+ {
+ try
+ {
+ checked
+ {
+ if (_parent._predicate(value))
+ _count++;
+ }
+ }
+ catch (Exception ex)
+ {
+ base._observer.OnError(ex);
+ 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();
+ }
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Materialize.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Materialize.cs
new file mode 100644
index 0000000..102267d
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Materialize.cs
@@ -0,0 +1,57 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class Materialize<TSource> : Producer<Notification<TSource>>
+ {
+ private readonly IObservable<TSource> _source;
+
+ public Materialize(IObservable<TSource> source)
+ {
+ _source = source;
+ }
+
+ public IObservable<TSource> Dematerialize()
+ {
+ return _source.AsObservable();
+ }
+
+ protected override IDisposable Run(IObserver<Notification<TSource>> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+
+ class _ : Sink<Notification<TSource>>, IObserver<TSource>
+ {
+ public _(IObserver<Notification<TSource>> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ }
+
+ public void OnNext(TSource value)
+ {
+ base._observer.OnNext(Notification.CreateOnNext<TSource>(value));
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnNext(Notification.CreateOnError<TSource>(error));
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ base._observer.OnNext(Notification.CreateOnCompleted<TSource>());
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Max.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Max.cs
new file mode 100644
index 0000000..da339da
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Max.cs
@@ -0,0 +1,792 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+using System.Collections.Generic;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class Max<TSource> : Producer<TSource>
+ {
+ private readonly IObservable<TSource> _source;
+ private readonly IComparer<TSource> _comparer;
+
+ public Max(IObservable<TSource> source, IComparer<TSource> comparer)
+ {
+ _source = source;
+ _comparer = comparer;
+ }
+
+ protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ // 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);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+ else
+ {
+ var sink = new δ(this, observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+ }
+
+ class δ : Sink<TSource>, IObserver<TSource>
+ {
+ private readonly Max<TSource> _parent;
+ private bool _hasValue;
+ private TSource _lastValue;
+
+ public δ(Max<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+
+ _hasValue = false;
+ _lastValue = default(TSource);
+ }
+
+ public void OnNext(TSource value)
+ {
+ if (_hasValue)
+ {
+ var comparison = 0;
+
+ try
+ {
+ comparison = _parent._comparer.Compare(value, _lastValue);
+ }
+ catch (Exception ex)
+ {
+ base._observer.OnError(ex);
+ base.Dispose();
+ return;
+ }
+
+ if (comparison > 0)
+ {
+ _lastValue = value;
+ }
+ }
+ else
+ {
+ _hasValue = true;
+ _lastValue = value;
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ if (!_hasValue)
+ {
+ base._observer.OnError(new InvalidOperationException(Strings_Linq.NO_ELEMENTS));
+ }
+ else
+ {
+ base._observer.OnNext(_lastValue);
+ base._observer.OnCompleted();
+ }
+
+ base.Dispose();
+ }
+ }
+
+ class _ : Sink<TSource>, IObserver<TSource>
+ {
+ private readonly Max<TSource> _parent;
+ private TSource _lastValue;
+
+ public _(Max<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+
+ _lastValue = default(TSource);
+ }
+
+ public void OnNext(TSource value)
+ {
+ if (value != null)
+ {
+ if (_lastValue == null)
+ {
+ _lastValue = value;
+ }
+ else
+ {
+ var comparison = 0;
+
+ try
+ {
+ comparison = _parent._comparer.Compare(value, _lastValue);
+ }
+ catch (Exception ex)
+ {
+ base._observer.OnError(ex);
+ base.Dispose();
+ return;
+ }
+
+ if (comparison > 0)
+ {
+ _lastValue = value;
+ }
+ }
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ base._observer.OnNext(_lastValue);
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+
+ class MaxDouble : Producer<double>
+ {
+ private readonly IObservable<double> _source;
+
+ public MaxDouble(IObservable<double> source)
+ {
+ _source = source;
+ }
+
+ protected override IDisposable Run(IObserver<double> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+
+ class _ : Sink<double>, IObserver<double>
+ {
+ private bool _hasValue;
+ private double _lastValue;
+
+ public _(IObserver<double> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _hasValue = false;
+ _lastValue = default(double);
+ }
+
+ public void OnNext(double value)
+ {
+ if (_hasValue)
+ {
+ if (value > _lastValue || double.IsNaN(value))
+ {
+ _lastValue = value;
+ }
+ }
+ else
+ {
+ _lastValue = value;
+ _hasValue = true;
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ if (!_hasValue)
+ {
+ base._observer.OnError(new InvalidOperationException(Strings_Linq.NO_ELEMENTS));
+ }
+ else
+ {
+ base._observer.OnNext(_lastValue);
+ base._observer.OnCompleted();
+ }
+
+ base.Dispose();
+ }
+ }
+ }
+
+ class MaxSingle : Producer<float>
+ {
+ private readonly IObservable<float> _source;
+
+ public MaxSingle(IObservable<float> source)
+ {
+ _source = source;
+ }
+
+ protected override IDisposable Run(IObserver<float> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+
+ class _ : Sink<float>, IObserver<float>
+ {
+ private bool _hasValue;
+ private float _lastValue;
+
+ public _(IObserver<float> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _hasValue = false;
+ _lastValue = default(float);
+ }
+
+ public void OnNext(float value)
+ {
+ if (_hasValue)
+ {
+ if (value > _lastValue || float.IsNaN(value))
+ {
+ _lastValue = value;
+ }
+ }
+ else
+ {
+ _lastValue = value;
+ _hasValue = true;
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ if (!_hasValue)
+ {
+ base._observer.OnError(new InvalidOperationException(Strings_Linq.NO_ELEMENTS));
+ }
+ else
+ {
+ base._observer.OnNext(_lastValue);
+ base._observer.OnCompleted();
+ }
+
+ base.Dispose();
+ }
+ }
+ }
+
+ class MaxDecimal : Producer<decimal>
+ {
+ private readonly IObservable<decimal> _source;
+
+ public MaxDecimal(IObservable<decimal> source)
+ {
+ _source = source;
+ }
+
+ protected override IDisposable Run(IObserver<decimal> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+
+ class _ : Sink<decimal>, IObserver<decimal>
+ {
+ private bool _hasValue;
+ private decimal _lastValue;
+
+ public _(IObserver<decimal> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _hasValue = false;
+ _lastValue = default(decimal);
+ }
+
+ public void OnNext(decimal value)
+ {
+ if (_hasValue)
+ {
+ if (value > _lastValue)
+ {
+ _lastValue = value;
+ }
+ }
+ else
+ {
+ _lastValue = value;
+ _hasValue = true;
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ if (!_hasValue)
+ {
+ base._observer.OnError(new InvalidOperationException(Strings_Linq.NO_ELEMENTS));
+ }
+ else
+ {
+ base._observer.OnNext(_lastValue);
+ base._observer.OnCompleted();
+ }
+
+ base.Dispose();
+ }
+ }
+ }
+
+ class MaxInt32 : Producer<int>
+ {
+ private readonly IObservable<int> _source;
+
+ public MaxInt32(IObservable<int> source)
+ {
+ _source = source;
+ }
+
+ protected override IDisposable Run(IObserver<int> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+
+ class _ : Sink<int>, IObserver<int>
+ {
+ private bool _hasValue;
+ private int _lastValue;
+
+ public _(IObserver<int> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _hasValue = false;
+ _lastValue = default(int);
+ }
+
+ public void OnNext(int value)
+ {
+ if (_hasValue)
+ {
+ if (value > _lastValue)
+ {
+ _lastValue = value;
+ }
+ }
+ else
+ {
+ _lastValue = value;
+ _hasValue = true;
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ if (!_hasValue)
+ {
+ base._observer.OnError(new InvalidOperationException(Strings_Linq.NO_ELEMENTS));
+ }
+ else
+ {
+ base._observer.OnNext(_lastValue);
+ base._observer.OnCompleted();
+ }
+
+ base.Dispose();
+ }
+ }
+ }
+
+ class MaxInt64 : Producer<long>
+ {
+ private readonly IObservable<long> _source;
+
+ public MaxInt64(IObservable<long> source)
+ {
+ _source = source;
+ }
+
+ protected override IDisposable Run(IObserver<long> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+
+ class _ : Sink<long>, IObserver<long>
+ {
+ private bool _hasValue;
+ private long _lastValue;
+
+ public _(IObserver<long> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _hasValue = false;
+ _lastValue = default(long);
+ }
+
+ public void OnNext(long value)
+ {
+ if (_hasValue)
+ {
+ if (value > _lastValue)
+ {
+ _lastValue = value;
+ }
+ }
+ else
+ {
+ _lastValue = value;
+ _hasValue = true;
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ if (!_hasValue)
+ {
+ base._observer.OnError(new InvalidOperationException(Strings_Linq.NO_ELEMENTS));
+ }
+ else
+ {
+ base._observer.OnNext(_lastValue);
+ base._observer.OnCompleted();
+ }
+
+ base.Dispose();
+ }
+ }
+ }
+
+ class MaxDoubleNullable : Producer<double?>
+ {
+ private readonly IObservable<double?> _source;
+
+ public MaxDoubleNullable(IObservable<double?> source)
+ {
+ _source = source;
+ }
+
+ protected override IDisposable Run(IObserver<double?> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+
+ class _ : Sink<double?>, IObserver<double?>
+ {
+ private double? _lastValue;
+
+ public _(IObserver<double?> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _lastValue = default(double?);
+ }
+
+ public void OnNext(double? value)
+ {
+ if (!value.HasValue)
+ return;
+
+ if (_lastValue.HasValue)
+ {
+ if (value > _lastValue || double.IsNaN((double)value))
+ {
+ _lastValue = value;
+ }
+ }
+ else
+ {
+ _lastValue = value;
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ base._observer.OnNext(_lastValue);
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+
+ class MaxSingleNullable : Producer<float?>
+ {
+ private readonly IObservable<float?> _source;
+
+ public MaxSingleNullable(IObservable<float?> source)
+ {
+ _source = source;
+ }
+
+ protected override IDisposable Run(IObserver<float?> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+
+ class _ : Sink<float?>, IObserver<float?>
+ {
+ private float? _lastValue;
+
+ public _(IObserver<float?> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _lastValue = default(float?);
+ }
+
+ public void OnNext(float? value)
+ {
+ if (!value.HasValue)
+ return;
+
+ if (_lastValue.HasValue)
+ {
+ if (value > _lastValue || float.IsNaN((float)value))
+ {
+ _lastValue = value;
+ }
+ }
+ else
+ {
+ _lastValue = value;
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ base._observer.OnNext(_lastValue);
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+
+ class MaxDecimalNullable : Producer<decimal?>
+ {
+ private readonly IObservable<decimal?> _source;
+
+ public MaxDecimalNullable(IObservable<decimal?> source)
+ {
+ _source = source;
+ }
+
+ protected override IDisposable Run(IObserver<decimal?> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+
+ class _ : Sink<decimal?>, IObserver<decimal?>
+ {
+ private decimal? _lastValue;
+
+ public _(IObserver<decimal?> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _lastValue = default(decimal?);
+ }
+
+ public void OnNext(decimal? value)
+ {
+ if (!value.HasValue)
+ return;
+
+ if (_lastValue.HasValue)
+ {
+ if (value > _lastValue)
+ {
+ _lastValue = value;
+ }
+ }
+ else
+ {
+ _lastValue = value;
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ base._observer.OnNext(_lastValue);
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+
+ class MaxInt32Nullable : Producer<int?>
+ {
+ private readonly IObservable<int?> _source;
+
+ public MaxInt32Nullable(IObservable<int?> source)
+ {
+ _source = source;
+ }
+
+ protected override IDisposable Run(IObserver<int?> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+
+ class _ : Sink<int?>, IObserver<int?>
+ {
+ private int? _lastValue;
+
+ public _(IObserver<int?> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _lastValue = default(int?);
+ }
+
+ public void OnNext(int? value)
+ {
+ if (!value.HasValue)
+ return;
+
+ if (_lastValue.HasValue)
+ {
+ if (value > _lastValue)
+ {
+ _lastValue = value;
+ }
+ }
+ else
+ {
+ _lastValue = value;
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ base._observer.OnNext(_lastValue);
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+
+ class MaxInt64Nullable : Producer<long?>
+ {
+ private readonly IObservable<long?> _source;
+
+ public MaxInt64Nullable(IObservable<long?> source)
+ {
+ _source = source;
+ }
+
+ protected override IDisposable Run(IObserver<long?> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+
+ class _ : Sink<long?>, IObserver<long?>
+ {
+ private long? _lastValue;
+
+ public _(IObserver<long?> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _lastValue = default(long?);
+ }
+
+ public void OnNext(long? value)
+ {
+ if (!value.HasValue)
+ return;
+
+ if (_lastValue.HasValue)
+ {
+ if (value > _lastValue)
+ {
+ _lastValue = value;
+ }
+ }
+ else
+ {
+ _lastValue = value;
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ base._observer.OnNext(_lastValue);
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/MaxBy.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/MaxBy.cs
new file mode 100644
index 0000000..52a9a42
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/MaxBy.cs
@@ -0,0 +1,108 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+using System.Collections.Generic;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class MaxBy<TSource, TKey> : Producer<IList<TSource>>
+ {
+ private readonly IObservable<TSource> _source;
+ private readonly Func<TSource, TKey> _keySelector;
+ private readonly IComparer<TKey> _comparer;
+
+ public MaxBy(IObservable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey> comparer)
+ {
+ _source = source;
+ _keySelector = keySelector;
+ _comparer = comparer;
+ }
+
+ protected override IDisposable Run(IObserver<IList<TSource>> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+
+ class _ : Sink<IList<TSource>>, IObserver<TSource>
+ {
+ private readonly MaxBy<TSource, TKey> _parent;
+ private bool _hasValue;
+ private TKey _lastKey;
+ private List<TSource> _list;
+
+ public _(MaxBy<TSource, TKey> parent, IObserver<IList<TSource>> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+
+ _hasValue = false;
+ _lastKey = default(TKey);
+ _list = new List<TSource>();
+ }
+
+ public void OnNext(TSource value)
+ {
+ var key = default(TKey);
+ try
+ {
+ key = _parent._keySelector(value);
+ }
+ catch (Exception ex)
+ {
+ base._observer.OnError(ex);
+ base.Dispose();
+ return;
+ }
+
+ var comparison = 0;
+
+ if (!_hasValue)
+ {
+ _hasValue = true;
+ _lastKey = key;
+ }
+ else
+ {
+ try
+ {
+ comparison = _parent._comparer.Compare(key, _lastKey);
+ }
+ catch (Exception ex)
+ {
+ base._observer.OnError(ex);
+ base.Dispose();
+ return;
+ }
+ }
+
+ if (comparison > 0)
+ {
+ _lastKey = key;
+ _list.Clear();
+ }
+
+ if (comparison >= 0)
+ {
+ _list.Add(value);
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ base._observer.OnNext(_list);
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Merge.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Merge.cs
new file mode 100644
index 0000000..a27c3c3
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Merge.cs
@@ -0,0 +1,403 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+using System.Collections.Generic;
+using System.Reactive.Disposables;
+
+#if !NO_TPL
+using System.Threading;
+using System.Threading.Tasks;
+#endif
+
+namespace System.Reactive.Linq.Observαble
+{
+ class Merge<TSource> : Producer<TSource>
+ {
+ private readonly IObservable<IObservable<TSource>> _sources;
+ private readonly int _maxConcurrent;
+
+ public Merge(IObservable<IObservable<TSource>> sources)
+ {
+ _sources = sources;
+ }
+
+ public Merge(IObservable<IObservable<TSource>> sources, int maxConcurrent)
+ {
+ _sources = sources;
+ _maxConcurrent = maxConcurrent;
+ }
+
+#if !NO_TPL
+ private readonly IObservable<Task<TSource>> _sourcesT;
+
+ public Merge(IObservable<Task<TSource>> sources)
+ {
+ _sourcesT = sources;
+ }
+#endif
+
+ protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ if (_maxConcurrent > 0)
+ {
+ var sink = new μ(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+#if !NO_TPL
+ else if (_sourcesT != null)
+ {
+ var sink = new τ(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+#endif
+ else
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+ }
+
+ class _ : Sink<TSource>, IObserver<IObservable<TSource>>
+ {
+ private readonly Merge<TSource> _parent;
+
+ public _(Merge<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ private object _gate;
+ private bool _isStopped;
+ private CompositeDisposable _group;
+ private SingleAssignmentDisposable _sourceSubscription;
+
+ public IDisposable Run()
+ {
+ _gate = new object();
+ _isStopped = false;
+ _group = new CompositeDisposable();
+
+ _sourceSubscription = new SingleAssignmentDisposable();
+ _group.Add(_sourceSubscription);
+ _sourceSubscription.Disposable = _parent._sources.SubscribeSafe(this);
+
+ return _group;
+ }
+
+ public void OnNext(IObservable<TSource> value)
+ {
+ var innerSubscription = new SingleAssignmentDisposable();
+ _group.Add(innerSubscription);
+ innerSubscription.Disposable = value.SubscribeSafe(new ι(this, innerSubscription));
+ }
+
+ public void OnError(Exception error)
+ {
+ lock (_gate)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+ }
+
+ 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<T>.
+ //
+ lock (_gate)
+ {
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ else
+ {
+ _sourceSubscription.Dispose();
+ }
+ }
+
+ class ι : IObserver<TSource>
+ {
+ private readonly _ _parent;
+ private readonly IDisposable _self;
+
+ public ι(_ parent, IDisposable self)
+ {
+ _parent = parent;
+ _self = self;
+ }
+
+ public void OnNext(TSource 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<T>.
+ //
+ lock (_parent._gate)
+ {
+ _parent._observer.OnCompleted();
+ _parent.Dispose();
+ }
+ }
+ }
+ }
+ }
+
+ class μ : Sink<TSource>, IObserver<IObservable<TSource>>
+ {
+ private readonly Merge<TSource> _parent;
+
+ public μ(Merge<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ private object _gate;
+ private Queue<IObservable<TSource>> _q;
+ private bool _isStopped;
+ private SingleAssignmentDisposable _sourceSubscription;
+ private CompositeDisposable _group;
+ private int _activeCount = 0;
+
+ public IDisposable Run()
+ {
+ _gate = new object();
+ _q = new Queue<IObservable<TSource>>();
+ _isStopped = false;
+ _activeCount = 0;
+
+ _group = new CompositeDisposable();
+ _sourceSubscription = new SingleAssignmentDisposable();
+ _sourceSubscription.Disposable = _parent._sources.SubscribeSafe(this);
+ _group.Add(_sourceSubscription);
+
+ return _group;
+ }
+
+ public void OnNext(IObservable<TSource> value)
+ {
+ lock (_gate)
+ {
+ if (_activeCount < _parent._maxConcurrent)
+ {
+ _activeCount++;
+ Subscribe(value);
+ }
+ else
+ _q.Enqueue(value);
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ lock (_gate)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+ }
+
+ public void OnCompleted()
+ {
+ lock (_gate)
+ {
+ _isStopped = true;
+ if (_activeCount == 0)
+ {
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ else
+ {
+ _sourceSubscription.Dispose();
+ }
+ }
+ }
+
+ private void Subscribe(IObservable<TSource> innerSource)
+ {
+ var subscription = new SingleAssignmentDisposable();
+ _group.Add(subscription);
+ subscription.Disposable = innerSource.SubscribeSafe(new ι(this, subscription));
+ }
+
+ class ι : IObserver<TSource>
+ {
+ private readonly μ _parent;
+ private readonly IDisposable _self;
+
+ public ι(μ parent, IDisposable self)
+ {
+ _parent = parent;
+ _self = self;
+ }
+
+ public void OnNext(TSource 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);
+ 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();
+ }
+ }
+ }
+ }
+ }
+ }
+
+#if !NO_TPL
+#pragma warning disable 0420
+ class τ : Sink<TSource>, IObserver<Task<TSource>>
+ {
+ private readonly Merge<TSource> _parent;
+
+ public τ(Merge<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ private object _gate;
+ private volatile int _count;
+
+ public IDisposable Run()
+ {
+ _gate = new object();
+ _count = 1;
+
+ return _parent._sourcesT.SubscribeSafe(this);
+ }
+
+ public void OnNext(Task<TSource> value)
+ {
+ Interlocked.Increment(ref _count);
+ if (value.IsCompleted)
+ {
+ OnCompletedTask(value);
+ }
+ else
+ {
+ value.ContinueWith(OnCompletedTask);
+ }
+ }
+
+ private void OnCompletedTask(Task<TSource> task)
+ {
+ switch (task.Status)
+ {
+ case TaskStatus.RanToCompletion:
+ {
+ lock (_gate)
+ base._observer.OnNext(task.Result);
+
+ OnCompleted();
+ }
+ break;
+ case TaskStatus.Faulted:
+ {
+ lock (_gate)
+ {
+ base._observer.OnError(task.Exception.InnerException);
+ base.Dispose();
+ }
+ }
+ break;
+ case TaskStatus.Canceled:
+ {
+ 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();
+ }
+ }
+ }
+ }
+#pragma warning restore 0420
+#endif
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Min.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Min.cs
new file mode 100644
index 0000000..f7b6197
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Min.cs
@@ -0,0 +1,792 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+using System.Collections.Generic;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class Min<TSource> : Producer<TSource>
+ {
+ private readonly IObservable<TSource> _source;
+ private readonly IComparer<TSource> _comparer;
+
+ public Min(IObservable<TSource> source, IComparer<TSource> comparer)
+ {
+ _source = source;
+ _comparer = comparer;
+ }
+
+ protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ // 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);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+ else
+ {
+ var sink = new δ(this, observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+ }
+
+ class δ : Sink<TSource>, IObserver<TSource>
+ {
+ private readonly Min<TSource> _parent;
+ private bool _hasValue;
+ private TSource _lastValue;
+
+ public δ(Min<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+
+ _hasValue = false;
+ _lastValue = default(TSource);
+ }
+
+ public void OnNext(TSource value)
+ {
+ if (_hasValue)
+ {
+ var comparison = 0;
+
+ try
+ {
+ comparison = _parent._comparer.Compare(value, _lastValue);
+ }
+ catch (Exception ex)
+ {
+ base._observer.OnError(ex);
+ base.Dispose();
+ return;
+ }
+
+ if (comparison < 0)
+ {
+ _lastValue = value;
+ }
+ }
+ else
+ {
+ _hasValue = true;
+ _lastValue = value;
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ if (!_hasValue)
+ {
+ base._observer.OnError(new InvalidOperationException(Strings_Linq.NO_ELEMENTS));
+ }
+ else
+ {
+ base._observer.OnNext(_lastValue);
+ base._observer.OnCompleted();
+ }
+
+ base.Dispose();
+ }
+ }
+
+ class _ : Sink<TSource>, IObserver<TSource>
+ {
+ private readonly Min<TSource> _parent;
+ private TSource _lastValue;
+
+ public _(Min<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+
+ _lastValue = default(TSource);
+ }
+
+ public void OnNext(TSource value)
+ {
+ if (value != null)
+ {
+ if (_lastValue == null)
+ {
+ _lastValue = value;
+ }
+ else
+ {
+ var comparison = 0;
+
+ try
+ {
+ comparison = _parent._comparer.Compare(value, _lastValue);
+ }
+ catch (Exception ex)
+ {
+ base._observer.OnError(ex);
+ base.Dispose();
+ return;
+ }
+
+ if (comparison < 0)
+ {
+ _lastValue = value;
+ }
+ }
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ base._observer.OnNext(_lastValue);
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+
+ class MinDouble : Producer<double>
+ {
+ private readonly IObservable<double> _source;
+
+ public MinDouble(IObservable<double> source)
+ {
+ _source = source;
+ }
+
+ protected override IDisposable Run(IObserver<double> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+
+ class _ : Sink<double>, IObserver<double>
+ {
+ private bool _hasValue;
+ private double _lastValue;
+
+ public _(IObserver<double> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _hasValue = false;
+ _lastValue = default(double);
+ }
+
+ public void OnNext(double value)
+ {
+ if (_hasValue)
+ {
+ if (value < _lastValue || double.IsNaN(value))
+ {
+ _lastValue = value;
+ }
+ }
+ else
+ {
+ _lastValue = value;
+ _hasValue = true;
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ if (!_hasValue)
+ {
+ base._observer.OnError(new InvalidOperationException(Strings_Linq.NO_ELEMENTS));
+ }
+ else
+ {
+ base._observer.OnNext(_lastValue);
+ base._observer.OnCompleted();
+ }
+
+ base.Dispose();
+ }
+ }
+ }
+
+ class MinSingle : Producer<float>
+ {
+ private readonly IObservable<float> _source;
+
+ public MinSingle(IObservable<float> source)
+ {
+ _source = source;
+ }
+
+ protected override IDisposable Run(IObserver<float> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+
+ class _ : Sink<float>, IObserver<float>
+ {
+ private bool _hasValue;
+ private float _lastValue;
+
+ public _(IObserver<float> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _hasValue = false;
+ _lastValue = default(float);
+ }
+
+ public void OnNext(float value)
+ {
+ if (_hasValue)
+ {
+ if (value < _lastValue || float.IsNaN(value))
+ {
+ _lastValue = value;
+ }
+ }
+ else
+ {
+ _lastValue = value;
+ _hasValue = true;
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ if (!_hasValue)
+ {
+ base._observer.OnError(new InvalidOperationException(Strings_Linq.NO_ELEMENTS));
+ }
+ else
+ {
+ base._observer.OnNext(_lastValue);
+ base._observer.OnCompleted();
+ }
+
+ base.Dispose();
+ }
+ }
+ }
+
+ class MinDecimal : Producer<decimal>
+ {
+ private readonly IObservable<decimal> _source;
+
+ public MinDecimal(IObservable<decimal> source)
+ {
+ _source = source;
+ }
+
+ protected override IDisposable Run(IObserver<decimal> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+
+ class _ : Sink<decimal>, IObserver<decimal>
+ {
+ private bool _hasValue;
+ private decimal _lastValue;
+
+ public _(IObserver<decimal> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _hasValue = false;
+ _lastValue = default(decimal);
+ }
+
+ public void OnNext(decimal value)
+ {
+ if (_hasValue)
+ {
+ if (value < _lastValue)
+ {
+ _lastValue = value;
+ }
+ }
+ else
+ {
+ _lastValue = value;
+ _hasValue = true;
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ if (!_hasValue)
+ {
+ base._observer.OnError(new InvalidOperationException(Strings_Linq.NO_ELEMENTS));
+ }
+ else
+ {
+ base._observer.OnNext(_lastValue);
+ base._observer.OnCompleted();
+ }
+
+ base.Dispose();
+ }
+ }
+ }
+
+ class MinInt32 : Producer<int>
+ {
+ private readonly IObservable<int> _source;
+
+ public MinInt32(IObservable<int> source)
+ {
+ _source = source;
+ }
+
+ protected override IDisposable Run(IObserver<int> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+
+ class _ : Sink<int>, IObserver<int>
+ {
+ private bool _hasValue;
+ private int _lastValue;
+
+ public _(IObserver<int> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _hasValue = false;
+ _lastValue = default(int);
+ }
+
+ public void OnNext(int value)
+ {
+ if (_hasValue)
+ {
+ if (value < _lastValue)
+ {
+ _lastValue = value;
+ }
+ }
+ else
+ {
+ _lastValue = value;
+ _hasValue = true;
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ if (!_hasValue)
+ {
+ base._observer.OnError(new InvalidOperationException(Strings_Linq.NO_ELEMENTS));
+ }
+ else
+ {
+ base._observer.OnNext(_lastValue);
+ base._observer.OnCompleted();
+ }
+
+ base.Dispose();
+ }
+ }
+ }
+
+ class MinInt64 : Producer<long>
+ {
+ private readonly IObservable<long> _source;
+
+ public MinInt64(IObservable<long> source)
+ {
+ _source = source;
+ }
+
+ protected override IDisposable Run(IObserver<long> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+
+ class _ : Sink<long>, IObserver<long>
+ {
+ private bool _hasValue;
+ private long _lastValue;
+
+ public _(IObserver<long> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _hasValue = false;
+ _lastValue = default(long);
+ }
+
+ public void OnNext(long value)
+ {
+ if (_hasValue)
+ {
+ if (value < _lastValue)
+ {
+ _lastValue = value;
+ }
+ }
+ else
+ {
+ _lastValue = value;
+ _hasValue = true;
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ if (!_hasValue)
+ {
+ base._observer.OnError(new InvalidOperationException(Strings_Linq.NO_ELEMENTS));
+ }
+ else
+ {
+ base._observer.OnNext(_lastValue);
+ base._observer.OnCompleted();
+ }
+
+ base.Dispose();
+ }
+ }
+ }
+
+ class MinDoubleNullable : Producer<double?>
+ {
+ private readonly IObservable<double?> _source;
+
+ public MinDoubleNullable(IObservable<double?> source)
+ {
+ _source = source;
+ }
+
+ protected override IDisposable Run(IObserver<double?> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+
+ class _ : Sink<double?>, IObserver<double?>
+ {
+ private double? _lastValue;
+
+ public _(IObserver<double?> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _lastValue = default(double?);
+ }
+
+ public void OnNext(double? value)
+ {
+ if (!value.HasValue)
+ return;
+
+ if (_lastValue.HasValue)
+ {
+ if (value < _lastValue || double.IsNaN((double)value))
+ {
+ _lastValue = value;
+ }
+ }
+ else
+ {
+ _lastValue = value;
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ base._observer.OnNext(_lastValue);
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+
+ class MinSingleNullable : Producer<float?>
+ {
+ private readonly IObservable<float?> _source;
+
+ public MinSingleNullable(IObservable<float?> source)
+ {
+ _source = source;
+ }
+
+ protected override IDisposable Run(IObserver<float?> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+
+ class _ : Sink<float?>, IObserver<float?>
+ {
+ private float? _lastValue;
+
+ public _(IObserver<float?> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _lastValue = default(float?);
+ }
+
+ public void OnNext(float? value)
+ {
+ if (!value.HasValue)
+ return;
+
+ if (_lastValue.HasValue)
+ {
+ if (value < _lastValue || float.IsNaN((float)value))
+ {
+ _lastValue = value;
+ }
+ }
+ else
+ {
+ _lastValue = value;
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ base._observer.OnNext(_lastValue);
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+
+ class MinDecimalNullable : Producer<decimal?>
+ {
+ private readonly IObservable<decimal?> _source;
+
+ public MinDecimalNullable(IObservable<decimal?> source)
+ {
+ _source = source;
+ }
+
+ protected override IDisposable Run(IObserver<decimal?> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+
+ class _ : Sink<decimal?>, IObserver<decimal?>
+ {
+ private decimal? _lastValue;
+
+ public _(IObserver<decimal?> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _lastValue = default(decimal?);
+ }
+
+ public void OnNext(decimal? value)
+ {
+ if (!value.HasValue)
+ return;
+
+ if (_lastValue.HasValue)
+ {
+ if (value < _lastValue)
+ {
+ _lastValue = value;
+ }
+ }
+ else
+ {
+ _lastValue = value;
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ base._observer.OnNext(_lastValue);
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+
+ class MinInt32Nullable : Producer<int?>
+ {
+ private readonly IObservable<int?> _source;
+
+ public MinInt32Nullable(IObservable<int?> source)
+ {
+ _source = source;
+ }
+
+ protected override IDisposable Run(IObserver<int?> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+
+ class _ : Sink<int?>, IObserver<int?>
+ {
+ private int? _lastValue;
+
+ public _(IObserver<int?> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _lastValue = default(int?);
+ }
+
+ public void OnNext(int? value)
+ {
+ if (!value.HasValue)
+ return;
+
+ if (_lastValue.HasValue)
+ {
+ if (value < _lastValue)
+ {
+ _lastValue = value;
+ }
+ }
+ else
+ {
+ _lastValue = value;
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ base._observer.OnNext(_lastValue);
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+
+ class MinInt64Nullable : Producer<long?>
+ {
+ private readonly IObservable<long?> _source;
+
+ public MinInt64Nullable(IObservable<long?> source)
+ {
+ _source = source;
+ }
+
+ protected override IDisposable Run(IObserver<long?> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+
+ class _ : Sink<long?>, IObserver<long?>
+ {
+ private long? _lastValue;
+
+ public _(IObserver<long?> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _lastValue = default(long?);
+ }
+
+ public void OnNext(long? value)
+ {
+ if (!value.HasValue)
+ return;
+
+ if (_lastValue.HasValue)
+ {
+ if (value < _lastValue)
+ {
+ _lastValue = value;
+ }
+ }
+ else
+ {
+ _lastValue = value;
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ base._observer.OnNext(_lastValue);
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/MinBy.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/MinBy.cs
new file mode 100644
index 0000000..a32bf92
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/MinBy.cs
@@ -0,0 +1,108 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+using System.Collections.Generic;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class MinBy<TSource, TKey> : Producer<IList<TSource>>
+ {
+ private readonly IObservable<TSource> _source;
+ private readonly Func<TSource, TKey> _keySelector;
+ private readonly IComparer<TKey> _comparer;
+
+ public MinBy(IObservable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey> comparer)
+ {
+ _source = source;
+ _keySelector = keySelector;
+ _comparer = comparer;
+ }
+
+ protected override IDisposable Run(IObserver<IList<TSource>> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+
+ class _ : Sink<IList<TSource>>, IObserver<TSource>
+ {
+ private readonly MinBy<TSource, TKey> _parent;
+ private bool _hasValue;
+ private TKey _lastKey;
+ private List<TSource> _list;
+
+ public _(MinBy<TSource, TKey> parent, IObserver<IList<TSource>> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+
+ _hasValue = false;
+ _lastKey = default(TKey);
+ _list = new List<TSource>();
+ }
+
+ public void OnNext(TSource value)
+ {
+ var key = default(TKey);
+ try
+ {
+ key = _parent._keySelector(value);
+ }
+ catch (Exception ex)
+ {
+ base._observer.OnError(ex);
+ base.Dispose();
+ return;
+ }
+
+ var comparison = 0;
+
+ if (!_hasValue)
+ {
+ _hasValue = true;
+ _lastKey = key;
+ }
+ else
+ {
+ try
+ {
+ comparison = _parent._comparer.Compare(key, _lastKey);
+ }
+ catch (Exception ex)
+ {
+ base._observer.OnError(ex);
+ base.Dispose();
+ return;
+ }
+ }
+
+ if (comparison < 0)
+ {
+ _lastKey = key;
+ _list.Clear();
+ }
+
+ if (comparison <= 0)
+ {
+ _list.Add(value);
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ base._observer.OnNext(_list);
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/MostRecent.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/MostRecent.cs
new file mode 100644
index 0000000..937d811
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/MostRecent.cs
@@ -0,0 +1,85 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+using System.Collections.Generic;
+using System.Threading;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class MostRecent<TSource> : PushToPullAdapter<TSource, TSource>
+ {
+ private readonly TSource _initialValue;
+
+ public MostRecent(IObservable<TSource> source, TSource initialValue)
+ : base(source)
+ {
+ _initialValue = initialValue;
+ }
+
+ protected override PushToPullSink<TSource, TSource> Run(IDisposable subscription)
+ {
+ return new _(_initialValue, subscription);
+ }
+
+ class _ : PushToPullSink<TSource, TSource>
+ {
+ public _(TSource initialValue, IDisposable subscription)
+ : base(subscription)
+ {
+ _kind = NotificationKind.OnNext;
+ _value = initialValue;
+ }
+
+ private volatile NotificationKind _kind;
+ private TSource _value;
+ private Exception _error;
+
+ public override void OnNext(TSource value)
+ {
+ _value = value;
+ _kind = NotificationKind.OnNext; // Write last!
+ }
+
+ public override void OnError(Exception error)
+ {
+ base.Dispose();
+
+ _error = error;
+ _kind = NotificationKind.OnError; // Write last!
+ }
+
+ public override void OnCompleted()
+ {
+ base.Dispose();
+
+ _kind = NotificationKind.OnCompleted; // Write last!
+ }
+
+ public override bool TryMoveNext(out TSource current)
+ {
+ //
+ // Notice the _kind field is marked volatile and read before the other fields.
+ //
+ // In case of a concurrent change, we may read a stale OnNext value, which is
+ // fine because this push-to-pull adapter is about sampling.
+ //
+ switch (_kind)
+ {
+ case NotificationKind.OnNext:
+ current = _value;
+ return true;
+ case NotificationKind.OnError:
+ _error.Throw();
+ break;
+ case NotificationKind.OnCompleted:
+ break;
+ }
+
+ current = default(TSource);
+ return false;
+ }
+ }
+ }
+}
+#endif
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Multicast.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Multicast.cs
new file mode 100644
index 0000000..4a77300
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Multicast.cs
@@ -0,0 +1,82 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+using System.Reactive.Disposables;
+using System.Reactive.Subjects;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class Multicast<TSource, TIntermediate, TResult> : Producer<TResult>
+ {
+ private readonly IObservable<TSource> _source;
+ private readonly Func<ISubject<TSource, TIntermediate>> _subjectSelector;
+ private readonly Func<IObservable<TIntermediate>, IObservable<TResult>> _selector;
+
+ public Multicast(IObservable<TSource> source, Func<ISubject<TSource, TIntermediate>> subjectSelector, Func<IObservable<TIntermediate>, IObservable<TResult>> selector)
+ {
+ _source = source;
+ _subjectSelector = subjectSelector;
+ _selector = selector;
+ }
+
+ protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+
+ class _ : Sink<TResult>, IObserver<TResult>
+ {
+ private readonly Multicast<TSource, TIntermediate, TResult> _parent;
+
+ public _(Multicast<TSource, TIntermediate, TResult> parent, IObserver<TResult> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ public IDisposable Run()
+ {
+ var observable = default(IObservable<TResult>);
+ var connectable = default(IConnectableObservable<TIntermediate>);
+ try
+ {
+ var subject = _parent._subjectSelector();
+ connectable = new ConnectableObservable<TSource, TIntermediate>(_parent._source, subject);
+ observable = _parent._selector(connectable);
+ }
+ catch (Exception exception)
+ {
+ base._observer.OnError(exception);
+ base.Dispose();
+ return Disposable.Empty;
+ }
+
+ var subscription = observable.SubscribeSafe(this);
+ var connection = connectable.Connect();
+
+ return new CompositeDisposable(subscription, connection);
+ }
+
+ public void OnNext(TResult value)
+ {
+ base._observer.OnNext(value);
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+}
+#endif
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Never.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Never.cs
new file mode 100644
index 0000000..a9adc52
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Never.cs
@@ -0,0 +1,20 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+using System.Reactive.Disposables;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class Never<TResult> : IObservable<TResult>
+ {
+ public IDisposable Subscribe(IObserver<TResult> observer)
+ {
+ if (observer == null)
+ throw new ArgumentNullException("observer");
+
+ return Disposable.Empty;
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Next.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Next.cs
new file mode 100644
index 0000000..2d4ec45
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Next.cs
@@ -0,0 +1,156 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+using System.Collections.Generic;
+using System.Reactive.Threading;
+using System.Threading;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class Next<TSource> : PushToPullAdapter<TSource, TSource>
+ {
+ public Next(IObservable<TSource> source)
+ : base(source)
+ {
+ }
+
+ protected override PushToPullSink<TSource, TSource> Run(IDisposable subscription)
+ {
+ return new _(subscription);
+ }
+
+ class _ : PushToPullSink<TSource, TSource>
+ {
+ private readonly object _gate;
+
+#if !NO_CDS
+ private readonly SemaphoreSlim _semaphore;
+#else
+ private readonly Semaphore _semaphore;
+#endif
+
+ public _(IDisposable subscription)
+ : base(subscription)
+ {
+ _gate = new object();
+
+#if !NO_CDS
+ _semaphore = new SemaphoreSlim(0, 1);
+#else
+ _semaphore = new Semaphore(0, 1);
+#endif
+ }
+
+ private bool _waiting;
+ private NotificationKind _kind;
+ private TSource _value;
+ private Exception _error;
+
+ public override void OnNext(TSource value)
+ {
+ lock (_gate)
+ {
+ if (_waiting)
+ {
+ _value = value;
+ _kind = NotificationKind.OnNext;
+ _semaphore.Release();
+ }
+
+ _waiting = false;
+ }
+ }
+
+ public override void OnError(Exception error)
+ {
+ base.Dispose();
+
+ lock (_gate)
+ {
+ //
+ // BREAKING CHANGE v2 > v1.x - Next doesn't block indefinitely when it reaches the end.
+ //
+ _error = error;
+ _kind = NotificationKind.OnError;
+
+ if (_waiting)
+ _semaphore.Release();
+
+ _waiting = false;
+ }
+ }
+
+ public override void OnCompleted()
+ {
+ base.Dispose();
+
+ lock (_gate)
+ {
+ //
+ // BREAKING CHANGE v2 > v1.x - Next doesn't block indefinitely when it reaches the end.
+ //
+ _kind = NotificationKind.OnCompleted;
+
+ if (_waiting)
+ _semaphore.Release();
+
+ _waiting = false;
+ }
+ }
+
+ public override bool TryMoveNext(out TSource current)
+ {
+ var done = false;
+
+ lock (_gate)
+ {
+ _waiting = true;
+
+ //
+ // BREAKING CHANGE v2 > v1.x - Next doesn't block indefinitely when it reaches the end.
+ //
+ done = _kind != NotificationKind.OnNext;
+ }
+
+ if (!done)
+ {
+#if !NO_CDS
+ _semaphore.Wait();
+#else
+ _semaphore.WaitOne();
+#endif
+ }
+
+ //
+ // When we reach this point, we released the lock and got the next notification
+ // from the observer. We assume no concurrent calls to the TryMoveNext method
+ // are made (per general guidance on usage of IEnumerable<T>). If the observer
+ // enters the lock again, it should have quit it first, causing _waiting to be
+ // set to false, hence future accesses of the lock won't set the _kind, _value,
+ // and _error fields, until TryMoveNext is entered again and _waiting is reset
+ // to true. In conclusion, the fields are stable for read below.
+ //
+ // Notice we rely on memory barrier acquire/release behavior due to the use of
+ // the semaphore, not the lock (we're still under the lock when we release the
+ // semaphore in the On* methods!).
+ //
+ switch (_kind)
+ {
+ case NotificationKind.OnNext:
+ current = _value;
+ return true;
+ case NotificationKind.OnError:
+ _error.Throw();
+ break;
+ case NotificationKind.OnCompleted:
+ break;
+ }
+
+ current = default(TSource);
+ return false;
+ }
+ }
+ }
+}
+#endif
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/ObserveOn.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/ObserveOn.cs
new file mode 100644
index 0000000..d5d7428
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/ObserveOn.cs
@@ -0,0 +1,89 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+using System.Reactive.Concurrency;
+using System.Threading;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class ObserveOn<TSource> : Producer<TSource>
+ {
+ private readonly IObservable<TSource> _source;
+ private readonly IScheduler _scheduler;
+
+ public ObserveOn(IObservable<TSource> source, IScheduler scheduler)
+ {
+ _source = source;
+ _scheduler = scheduler;
+ }
+
+#if !NO_SYNCCTX
+ private readonly SynchronizationContext _context;
+
+ public ObserveOn(IObservable<TSource> source, SynchronizationContext context)
+ {
+ _source = source;
+ _context = context;
+ }
+#endif
+
+ protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+#if !NO_SYNCCTX
+ if (_context != null)
+ {
+ var sink = new ς(this, observer, cancel);
+ setSink(sink);
+ return _source.Subscribe(sink);
+ }
+ else
+#endif
+ {
+ var sink = new ObserveOnObserver<TSource>(_scheduler, observer, cancel);
+ setSink(sink);
+ return _source.Subscribe(sink);
+ }
+ }
+
+#if !NO_SYNCCTX
+ class ς : Sink<TSource>, IObserver<TSource>
+ {
+ private readonly ObserveOn<TSource> _parent;
+
+ public ς(ObserveOn<TSource> parent, IObserver<TSource> 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();
+ });
+ }
+ }
+#endif
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/OfType.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/OfType.cs
new file mode 100644
index 0000000..07e4515
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/OfType.cs
@@ -0,0 +1,53 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class OfType<TSource, TResult> : Producer<TResult>
+ {
+ private readonly IObservable<TSource> _source;
+
+ public OfType(IObservable<TSource> source)
+ {
+ _source = source;
+ }
+
+ protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+
+ class _ : Sink<TResult>, IObserver<TSource>
+ {
+ public _(IObserver<TResult> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ }
+
+ public void OnNext(TSource value)
+ {
+ if (value is TResult)
+ {
+ base._observer.OnNext((TResult)(object)value);
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/OnErrorResumeNext.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/OnErrorResumeNext.cs
new file mode 100644
index 0000000..26dfd34
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/OnErrorResumeNext.cs
@@ -0,0 +1,60 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+using System.Collections.Generic;
+using System.Reactive.Concurrency;
+using System.Reactive.Disposables;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class OnErrorResumeNext<TSource> : Producer<TSource>
+ {
+ private readonly IEnumerable<IObservable<TSource>> _sources;
+
+ public OnErrorResumeNext(IEnumerable<IObservable<TSource>> sources)
+ {
+ _sources = sources;
+ }
+
+ protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(observer, cancel);
+ setSink(sink);
+ return sink.Run(_sources);
+ }
+
+ class _ : TailRecursiveSink<TSource>
+ {
+ public _(IObserver<TSource> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ }
+
+ protected override IEnumerable<IObservable<TSource>> Extract(IObservable<TSource> source)
+ {
+ var oern = source as OnErrorResumeNext<TSource>;
+ if (oern != null)
+ return oern._sources;
+
+ return null;
+ }
+
+ public override void OnNext(TSource value)
+ {
+ base._observer.OnNext(value);
+ }
+
+ public override void OnError(Exception error)
+ {
+ _recurse();
+ }
+
+ public override void OnCompleted()
+ {
+ _recurse();
+ }
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/PushToPullAdapter.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/PushToPullAdapter.cs
new file mode 100644
index 0000000..916d12b
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/PushToPullAdapter.cs
@@ -0,0 +1,93 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Reactive.Disposables;
+
+namespace System.Reactive.Linq.Observαble
+{
+ abstract class PushToPullAdapter<TSource, TResult> : IEnumerable<TResult>
+ {
+ private readonly IObservable<TSource> _source;
+
+ public PushToPullAdapter(IObservable<TSource> source)
+ {
+ _source = source;
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return GetEnumerator();
+ }
+
+ public IEnumerator<TResult> GetEnumerator()
+ {
+ var d = new SingleAssignmentDisposable();
+ var res = Run(d);
+ d.Disposable = _source.SubscribeSafe(res);
+ return res;
+ }
+
+ protected abstract PushToPullSink<TSource, TResult> Run(IDisposable subscription);
+ }
+
+ abstract class PushToPullSink<TSource, TResult> : IObserver<TSource>, IEnumerator<TResult>, IDisposable
+ {
+ private readonly IDisposable _subscription;
+
+ public PushToPullSink(IDisposable subscription)
+ {
+ _subscription = subscription;
+ }
+
+ public abstract void OnNext(TSource value);
+ public abstract void OnError(Exception error);
+ public abstract void OnCompleted();
+
+ public abstract bool TryMoveNext(out TResult current);
+
+ private bool _done;
+
+ public bool MoveNext()
+ {
+ if (!_done)
+ {
+ var current = default(TResult);
+ if (TryMoveNext(out current))
+ {
+ Current = current;
+ return true;
+ }
+ else
+ {
+ _done = true;
+ _subscription.Dispose();
+ }
+ }
+
+ return false;
+ }
+
+ public TResult Current
+ {
+ get;
+ private set;
+ }
+
+ object IEnumerator.Current
+ {
+ get { return Current; }
+ }
+
+ public void Reset()
+ {
+ throw new NotSupportedException();
+ }
+
+ public void Dispose()
+ {
+ _subscription.Dispose();
+ }
+ }
+}
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Range.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Range.cs
new file mode 100644
index 0000000..c58d94c
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Range.cs
@@ -0,0 +1,83 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+using System.Reactive.Concurrency;
+using System.Reactive.Disposables;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class Range : Producer<int>
+ {
+ private readonly int _start;
+ private readonly int _count;
+ private readonly IScheduler _scheduler;
+
+ public Range(int start, int count, IScheduler scheduler)
+ {
+ _start = start;
+ _count = count;
+ _scheduler = scheduler;
+ }
+
+ protected override IDisposable Run(IObserver<int> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+
+ class _ : Sink<int>
+ {
+ private readonly Range _parent;
+
+ public _(Range parent, IObserver<int> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ public IDisposable Run()
+ {
+ var longRunning = _parent._scheduler.AsLongRunning();
+ if (longRunning != null)
+ {
+ return longRunning.ScheduleLongRunning(0, Loop);
+ }
+ else
+ {
+ return _parent._scheduler.Schedule(0, LoopRec);
+ }
+ }
+
+ private void Loop(int i, ICancelable cancel)
+ {
+ while (!cancel.IsDisposed && i < _parent._count)
+ {
+ base._observer.OnNext(_parent._start + i);
+ i++;
+ }
+
+ if (!cancel.IsDisposed)
+ base._observer.OnCompleted();
+
+ base.Dispose();
+ }
+
+ private void LoopRec(int i, Action<int> recurse)
+ {
+ if (i < _parent._count)
+ {
+ base._observer.OnNext(_parent._start + i);
+ recurse(i + 1);
+ }
+ else
+ {
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/RefCount.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/RefCount.cs
new file mode 100644
index 0000000..1762807
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/RefCount.cs
@@ -0,0 +1,88 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+using System.Reactive.Disposables;
+using System.Reactive.Subjects;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class RefCount<TSource> : Producer<TSource>
+ {
+ private readonly IConnectableObservable<TSource> _source;
+
+ private readonly object _gate;
+ private int _count;
+ private IDisposable _connectableSubscription;
+
+ public RefCount(IConnectableObservable<TSource> source)
+ {
+ _source = source;
+ _gate = new object();
+ _count = 0;
+ _connectableSubscription = default(IDisposable);
+ }
+
+ protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+
+ class _ : Sink<TSource>, IObserver<TSource>
+ {
+ private readonly RefCount<TSource> _parent;
+
+ public _(RefCount<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ public IDisposable Run()
+ {
+ var subscription = _parent._source.SubscribeSafe(this);
+
+ lock (_parent._gate)
+ {
+ if (++_parent._count == 1)
+ {
+ _parent._connectableSubscription = _parent._source.Connect();
+ }
+ }
+
+ return Disposable.Create(() =>
+ {
+ subscription.Dispose();
+
+ lock (_parent._gate)
+ {
+ if (--_parent._count == 0)
+ {
+ _parent._connectableSubscription.Dispose();
+ }
+ }
+ });
+ }
+
+ public void OnNext(TSource value)
+ {
+ base._observer.OnNext(value);
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+}
+#endif
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Repeat.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Repeat.cs
new file mode 100644
index 0000000..fab0607
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Repeat.cs
@@ -0,0 +1,127 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+using System.Reactive.Concurrency;
+using System.Reactive.Disposables;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class Repeat<TResult> : Producer<TResult>
+ {
+ private readonly TResult _value;
+ private readonly int? _repeatCount;
+ private readonly IScheduler _scheduler;
+
+ public Repeat(TResult value, int? repeatCount, IScheduler scheduler)
+ {
+ _value = value;
+ _repeatCount = repeatCount;
+ _scheduler = scheduler;
+ }
+
+ protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+
+ class _ : Sink<TResult>
+ {
+ private readonly Repeat<TResult> _parent;
+
+ public _(Repeat<TResult> parent, IObserver<TResult> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ public IDisposable Run()
+ {
+ var longRunning = _parent._scheduler.AsLongRunning();
+ if (longRunning != null)
+ {
+ return Run(longRunning);
+ }
+ else
+ {
+ return Run(_parent._scheduler);
+ }
+ }
+
+ private IDisposable Run(IScheduler scheduler)
+ {
+ if (_parent._repeatCount == null)
+ {
+ return scheduler.Schedule(LoopRecInf);
+ }
+ else
+ {
+ return scheduler.Schedule(_parent._repeatCount.Value, LoopRec);
+ }
+ }
+
+ private void LoopRecInf(Action recurse)
+ {
+ base._observer.OnNext(_parent._value);
+ recurse();
+ }
+
+ private void LoopRec(int n, Action<int> recurse)
+ {
+ if (n > 0)
+ {
+ base._observer.OnNext(_parent._value);
+ n--;
+ }
+
+ if (n == 0)
+ {
+ base._observer.OnCompleted();
+ base.Dispose();
+ return;
+ }
+
+ recurse(n);
+ }
+
+ private IDisposable Run(ISchedulerLongRunning scheduler)
+ {
+ if (_parent._repeatCount == null)
+ {
+ return scheduler.ScheduleLongRunning(LoopInf);
+ }
+ else
+ {
+ return scheduler.ScheduleLongRunning(_parent._repeatCount.Value, Loop);
+ }
+ }
+
+ 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)
+ {
+ base._observer.OnNext(value);
+ n--;
+ }
+
+ if (!cancel.IsDisposed)
+ base._observer.OnCompleted();
+
+ base.Dispose();
+ }
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Return.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Return.cs
new file mode 100644
index 0000000..cd9ad02
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Return.cs
@@ -0,0 +1,51 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+using System.Reactive.Concurrency;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class Return<TResult> : Producer<TResult>
+ {
+ private readonly TResult _value;
+ private readonly IScheduler _scheduler;
+
+ public Return(TResult value, IScheduler scheduler)
+ {
+ _value = value;
+ _scheduler = scheduler;
+ }
+
+ protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+
+ class _ : Sink<TResult>
+ {
+ private readonly Return<TResult> _parent;
+
+ public _(Return<TResult> parent, IObserver<TResult> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ public IDisposable Run()
+ {
+ return _parent._scheduler.Schedule(Invoke);
+ }
+
+ private void Invoke()
+ {
+ base._observer.OnNext(_parent._value);
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Sample.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Sample.cs
new file mode 100644
index 0000000..0d46c62
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Sample.cs
@@ -0,0 +1,243 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+using System.Reactive.Concurrency;
+using System.Reactive.Disposables;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class Sample<TSource, TSample> : Producer<TSource>
+ {
+ private readonly IObservable<TSource> _source;
+ private readonly IObservable<TSample> _sampler;
+
+ public Sample(IObservable<TSource> source, IObservable<TSample> sampler)
+ {
+ _source = source;
+ _sampler = sampler;
+ }
+
+ protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+
+ class _ : Sink<TSource>, IObserver<TSource>
+ {
+ private readonly Sample<TSource, TSample> _parent;
+
+ public _(Sample<TSource, TSample> parent, IObserver<TSource> 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()
+ {
+ _gate = new object();
+
+ var sourceSubscription = new SingleAssignmentDisposable();
+ _sourceSubscription = sourceSubscription;
+ sourceSubscription.Disposable = _parent._source.SubscribeSafe(this);
+
+ var samplerSubscription = _parent._sampler.SubscribeSafe(new σ(this));
+
+ return new CompositeDisposable(_sourceSubscription, samplerSubscription);
+ }
+
+ public void OnNext(TSource value)
+ {
+ lock (_gate)
+ {
+ _hasValue = true;
+ _value = value;
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ lock (_gate)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+ }
+
+ public void OnCompleted()
+ {
+ lock (_gate)
+ {
+ _atEnd = true;
+ _sourceSubscription.Dispose();
+ }
+ }
+
+ class σ : IObserver<TSample>
+ {
+ private readonly _ _parent;
+
+ public σ(_ parent)
+ {
+ _parent = parent;
+ }
+
+ public void OnNext(TSample value)
+ {
+ lock (_parent._gate)
+ {
+ if (_parent._hasValue)
+ {
+ _parent._hasValue = false;
+ _parent._observer.OnNext(_parent._value);
+ }
+
+ if (_parent._atEnd)
+ {
+ _parent._observer.OnCompleted();
+ _parent.Dispose();
+ }
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ // BREAKING CHANGE v2 > v1.x - This error used to be swallowed
+ lock (_parent._gate)
+ {
+ _parent._observer.OnError(error);
+ _parent.Dispose();
+ }
+ }
+
+ public void OnCompleted()
+ {
+ lock (_parent._gate)
+ {
+ if (_parent._hasValue)
+ {
+ _parent._hasValue = false;
+ _parent._observer.OnNext(_parent._value);
+ }
+
+ if (_parent._atEnd)
+ {
+ _parent._observer.OnCompleted();
+ _parent.Dispose();
+ }
+ }
+ }
+ }
+ }
+ }
+
+ class Sample<TSource> : Producer<TSource>
+ {
+ private readonly IObservable<TSource> _source;
+ private readonly TimeSpan _interval;
+ private readonly IScheduler _scheduler;
+
+ public Sample(IObservable<TSource> source, TimeSpan interval, IScheduler scheduler)
+ {
+ _source = source;
+ _interval = interval;
+ _scheduler = scheduler;
+ }
+
+ protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+
+ class _ : Sink<TSource>, IObserver<TSource>
+ {
+ private readonly Sample<TSource> _parent;
+
+ public _(Sample<TSource> parent, IObserver<TSource> 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()
+ {
+ _gate = new object();
+
+ var sourceSubscription = new SingleAssignmentDisposable();
+ _sourceSubscription = sourceSubscription;
+ sourceSubscription.Disposable = _parent._source.SubscribeSafe(this);
+
+ return new CompositeDisposable(
+ sourceSubscription,
+ _parent._scheduler.SchedulePeriodic(_parent._interval, Tick)
+ );
+ }
+
+ private void Tick()
+ {
+ lock (_gate)
+ {
+ if (_hasValue)
+ {
+ _hasValue = false;
+ base._observer.OnNext(_value);
+ }
+
+ if (_atEnd)
+ {
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+
+ public void OnNext(TSource value)
+ {
+ lock (_gate)
+ {
+ _hasValue = true;
+ _value = value;
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ lock (_gate)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+ }
+
+ public void OnCompleted()
+ {
+ lock (_gate)
+ {
+ _atEnd = true;
+ _sourceSubscription.Dispose();
+ }
+ }
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Scan.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Scan.cs
new file mode 100644
index 0000000..6c8f2fe
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Scan.cs
@@ -0,0 +1,146 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class Scan<TSource, TAccumulate> : Producer<TAccumulate>
+ {
+ private readonly IObservable<TSource> _source;
+ private readonly TAccumulate _seed;
+ private readonly Func<TAccumulate, TSource, TAccumulate> _accumulator;
+
+ public Scan(IObservable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> accumulator)
+ {
+ _source = source;
+ _seed = seed;
+ _accumulator = accumulator;
+ }
+
+ protected override IDisposable Run(IObserver<TAccumulate> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+
+ class _ : Sink<TAccumulate>, IObserver<TSource>
+ {
+ private readonly Scan<TSource, TAccumulate> _parent;
+ private TAccumulate _accumulation;
+ private bool _hasAccumulation;
+
+ public _(Scan<TSource, TAccumulate> parent, IObserver<TAccumulate> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ _accumulation = default(TAccumulate);
+ _hasAccumulation = false;
+ }
+
+ public void OnNext(TSource value)
+ {
+ try
+ {
+ if (_hasAccumulation)
+ _accumulation = _parent._accumulator(_accumulation, value);
+ else
+ {
+ _accumulation = _parent._accumulator(_parent._seed, value);
+ _hasAccumulation = true;
+ }
+ }
+ catch (Exception exception)
+ {
+ base._observer.OnError(exception);
+ base.Dispose();
+ return;
+ }
+
+ base._observer.OnNext(_accumulation);
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+
+ class Scan<TSource> : Producer<TSource>
+ {
+ private readonly IObservable<TSource> _source;
+ private readonly Func<TSource, TSource, TSource> _accumulator;
+
+ public Scan(IObservable<TSource> source, Func<TSource, TSource, TSource> accumulator)
+ {
+ _source = source;
+ _accumulator = accumulator;
+ }
+
+ protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+
+ class _ : Sink<TSource>, IObserver<TSource>
+ {
+ private readonly Scan<TSource> _parent;
+ private TSource _accumulation;
+ private bool _hasAccumulation;
+
+ public _(Scan<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ _accumulation = default(TSource);
+ _hasAccumulation = false;
+ }
+
+ public void OnNext(TSource value)
+ {
+ try
+ {
+ if (_hasAccumulation)
+ _accumulation = _parent._accumulator(_accumulation, value);
+ else
+ {
+ _accumulation = value;
+ _hasAccumulation = true;
+ }
+ }
+ catch (Exception exception)
+ {
+ base._observer.OnError(exception);
+ base.Dispose();
+ return;
+ }
+
+ base._observer.OnNext(_accumulation);
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Select.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Select.cs
new file mode 100644
index 0000000..e853210
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Select.cs
@@ -0,0 +1,138 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+
+namespace System.Reactive.Linq.Observαble
+{
+ abstract class Select<TResult> : Producer<TResult>
+ {
+ public abstract IObservable<TResult2> Ω<TResult2>(Func<TResult, TResult2> selector);
+ }
+
+ class Select<TSource, TResult> : Select<TResult>
+ {
+ private readonly IObservable<TSource> _source;
+ private readonly Func<TSource, TResult> _selector;
+ private readonly Func<TSource, int, TResult> _selectorI;
+
+ public Select(IObservable<TSource> source, Func<TSource, TResult> selector)
+ {
+ _source = source;
+ _selector = selector;
+ }
+
+ public Select(IObservable<TSource> source, Func<TSource, int, TResult> selector)
+ {
+ _source = source;
+ _selectorI = selector;
+ }
+
+ public override IObservable<TResult2> Ω<TResult2>(Func<TResult, TResult2> selector)
+ {
+ if (_selector != null)
+ return new Select<TSource, TResult2>(_source, x => selector(_selector(x)));
+ else
+ return new Select<TResult, TResult2>(this, selector);
+ }
+
+ protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ if (_selector != null)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+ else
+ {
+ var sink = new τ(this, observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+ }
+
+ class _ : Sink<TResult>, IObserver<TSource>
+ {
+ private readonly Select<TSource, TResult> _parent;
+
+ public _(Select<TSource, TResult> parent, IObserver<TResult> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ public void OnNext(TSource value)
+ {
+ var result = default(TResult);
+ try
+ {
+ result = _parent._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();
+ }
+
+ public void OnCompleted()
+ {
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+
+ class τ : Sink<TResult>, IObserver<TSource>
+ {
+ private readonly Select<TSource, TResult> _parent;
+ private int _index;
+
+ public τ(Select<TSource, TResult> parent, IObserver<TResult> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ _index = 0;
+ }
+
+ public void OnNext(TSource value)
+ {
+ var result = default(TResult);
+ try
+ {
+ result = _parent._selectorI(value, checked(_index++));
+ }
+ 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.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/SelectMany.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/SelectMany.cs
new file mode 100644
index 0000000..687a894
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/SelectMany.cs
@@ -0,0 +1,888 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+using System.Collections.Generic;
+using System.Reactive;
+using System.Reactive.Disposables;
+
+#if !NO_TPL
+using System.Threading;
+using System.Threading.Tasks;
+#endif
+
+namespace System.Reactive.Linq.Observαble
+{
+ class SelectMany<TSource, TCollection, TResult> : Producer<TResult>
+ {
+ private readonly IObservable<TSource> _source;
+ private readonly Func<TSource, IObservable<TCollection>> _collectionSelector;
+ private readonly Func<TSource, IEnumerable<TCollection>> _collectionSelectorE;
+ private readonly Func<TSource, TCollection, TResult> _resultSelector;
+
+ public SelectMany(IObservable<TSource> source, Func<TSource, IObservable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> resultSelector)
+ {
+ _source = source;
+ _collectionSelector = collectionSelector;
+ _resultSelector = resultSelector;
+ }
+
+ public SelectMany(IObservable<TSource> source, Func<TSource, IEnumerable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> resultSelector)
+ {
+ _source = source;
+ _collectionSelectorE = collectionSelector;
+ _resultSelector = resultSelector;
+ }
+
+#if !NO_TPL
+ private readonly Func<TSource, CancellationToken, Task<TCollection>> _collectionSelectorT;
+
+ public SelectMany(IObservable<TSource> source, Func<TSource, CancellationToken, Task<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> resultSelector)
+ {
+ _source = source;
+ _collectionSelectorT = collectionSelector;
+ _resultSelector = resultSelector;
+ }
+#endif
+
+ protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ if (_collectionSelector != null)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+#if !NO_TPL
+ else if (_collectionSelectorT != null)
+ {
+ var sink = new τ(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+#endif
+ else
+ {
+ var sink = new ε(this, observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+ }
+
+ class _ : Sink<TResult>, IObserver<TSource>
+ {
+ private readonly SelectMany<TSource, TCollection, TResult> _parent;
+
+ public _(SelectMany<TSource, TCollection, TResult> parent, IObserver<TResult> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ private object _gate;
+ private bool _isStopped;
+ private CompositeDisposable _group;
+ private SingleAssignmentDisposable _sourceSubscription;
+
+ public IDisposable Run()
+ {
+ _gate = new object();
+ _isStopped = false;
+ _group = new CompositeDisposable();
+
+ _sourceSubscription = new SingleAssignmentDisposable();
+ _group.Add(_sourceSubscription);
+ _sourceSubscription.Disposable = _parent._source.SubscribeSafe(this);
+
+ return _group;
+ }
+
+ public void OnNext(TSource value)
+ {
+ var collection = default(IObservable<TCollection>);
+
+ try
+ {
+ collection = _parent._collectionSelector(value);
+ }
+ catch (Exception ex)
+ {
+ lock (_gate)
+ {
+ base._observer.OnError(ex);
+ base.Dispose();
+ }
+ return;
+ }
+
+ var innerSubscription = new SingleAssignmentDisposable();
+ _group.Add(innerSubscription);
+ innerSubscription.Disposable = collection.SubscribeSafe(new ι(this, value, innerSubscription));
+ }
+
+ public void OnError(Exception error)
+ {
+ lock (_gate)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+ }
+
+ 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<T>.
+ //
+ lock (_gate)
+ {
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ else
+ {
+ _sourceSubscription.Dispose();
+ }
+ }
+
+ class ι : IObserver<TCollection>
+ {
+ private readonly _ _parent;
+ private readonly TSource _value;
+ private readonly IDisposable _self;
+
+ public ι(_ parent, TSource value, IDisposable self)
+ {
+ _parent = parent;
+ _value = value;
+ _self = self;
+ }
+
+ public void OnNext(TCollection value)
+ {
+ var res = default(TResult);
+
+ try
+ {
+ res = _parent._parent._resultSelector(_value, value);
+ }
+ catch (Exception ex)
+ {
+ lock (_parent._gate)
+ {
+ _parent._observer.OnError(ex);
+ _parent.Dispose();
+ }
+ return;
+ }
+
+ lock (_parent._gate)
+ _parent._observer.OnNext(res);
+ }
+
+ 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<T>.
+ //
+ lock (_parent._gate)
+ {
+ _parent._observer.OnCompleted();
+ _parent.Dispose();
+ }
+ }
+ }
+ }
+ }
+
+ class ε : Sink<TResult>, IObserver<TSource>
+ {
+ private readonly SelectMany<TSource, TCollection, TResult> _parent;
+
+ public ε(SelectMany<TSource, TCollection, TResult> parent, IObserver<TResult> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ public void OnNext(TSource value)
+ {
+ var xs = default(IEnumerable<TCollection>);
+ try
+ {
+ xs = _parent._collectionSelectorE(value);
+ }
+ catch (Exception exception)
+ {
+ base._observer.OnError(exception);
+ base.Dispose();
+ return;
+ }
+
+ var e = default(IEnumerator<TCollection>);
+ 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);
+
+ try
+ {
+ hasNext = e.MoveNext();
+ if (hasNext)
+ current = _parent._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();
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+
+#if !NO_TPL
+#pragma warning disable 0420
+ class τ : Sink<TResult>, IObserver<TSource>
+ {
+ private readonly SelectMany<TSource, TCollection, TResult> _parent;
+
+ public τ(SelectMany<TSource, TCollection, TResult> parent, IObserver<TResult> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ private object _gate;
+ private CancellationDisposable _cancel;
+ private volatile int _count;
+
+ public IDisposable Run()
+ {
+ _gate = new object();
+ _cancel = new CancellationDisposable();
+ _count = 1;
+
+ return new CompositeDisposable(_parent._source.SubscribeSafe(this), _cancel);
+ }
+
+ public void OnNext(TSource value)
+ {
+ var task = default(Task<TCollection>);
+ try
+ {
+ Interlocked.Increment(ref _count);
+ task = _parent._collectionSelectorT(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);
+ }
+ }
+
+ private void AttachContinuation(TSource value, Task<TCollection> task)
+ {
+ //
+ // Separate method to avoid closure in synchronous completion case.
+ //
+ task.ContinueWith(t => OnCompletedTask(value, t));
+ }
+
+ private void OnCompletedTask(TSource value, Task<TCollection> task)
+ {
+ switch (task.Status)
+ {
+ 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();
+ }
+
+ 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();
+ }
+ }
+ }
+ }
+#pragma warning restore 0420
+#endif
+ }
+
+ class SelectMany<TSource, TResult> : Producer<TResult>
+ {
+ private readonly IObservable<TSource> _source;
+ private readonly Func<TSource, IObservable<TResult>> _selector;
+ private readonly Func<Exception, IObservable<TResult>> _selectorOnError;
+ private readonly Func<IObservable<TResult>> _selectorOnCompleted;
+ private readonly Func<TSource, IEnumerable<TResult>> _selectorE;
+
+ public SelectMany(IObservable<TSource> source, Func<TSource, IObservable<TResult>> selector)
+ {
+ _source = source;
+ _selector = selector;
+ }
+
+ public SelectMany(IObservable<TSource> source, Func<TSource, IObservable<TResult>> selector, Func<Exception, IObservable<TResult>> selectorOnError, Func<IObservable<TResult>> selectorOnCompleted)
+ {
+ _source = source;
+ _selector = selector;
+ _selectorOnError = selectorOnError;
+ _selectorOnCompleted = selectorOnCompleted;
+ }
+
+ public SelectMany(IObservable<TSource> source, Func<TSource, IEnumerable<TResult>> selector)
+ {
+ _source = source;
+ _selectorE = selector;
+ }
+
+#if !NO_TPL
+ private readonly Func<TSource, CancellationToken, Task<TResult>> _selectorT;
+
+ public SelectMany(IObservable<TSource> source, Func<TSource, CancellationToken, Task<TResult>> selector)
+ {
+ _source = source;
+ _selectorT = selector;
+ }
+#endif
+
+ protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ if (_selector != null)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+#if !NO_TPL
+ else if (_selectorT != null)
+ {
+ var sink = new τ(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+#endif
+ else
+ {
+ var sink = new ε(this, observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+ }
+
+ class _ : Sink<TResult>, IObserver<TSource>
+ {
+ private readonly SelectMany<TSource, TResult> _parent;
+
+ public _(SelectMany<TSource, TResult> parent, IObserver<TResult> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ private object _gate;
+ private bool _isStopped;
+ private CompositeDisposable _group;
+ private SingleAssignmentDisposable _sourceSubscription;
+
+ public IDisposable Run()
+ {
+ _gate = new object();
+ _isStopped = false;
+ _group = new CompositeDisposable();
+
+ _sourceSubscription = new SingleAssignmentDisposable();
+ _group.Add(_sourceSubscription);
+ _sourceSubscription.Disposable = _parent._source.SubscribeSafe(this);
+
+ return _group;
+ }
+
+ public void OnNext(TSource value)
+ {
+ var inner = default(IObservable<TResult>);
+
+ try
+ {
+ inner = _parent._selector(value);
+ }
+ catch (Exception ex)
+ {
+ lock (_gate)
+ {
+ base._observer.OnError(ex);
+ base.Dispose();
+ }
+ return;
+ }
+
+ SubscribeInner(inner);
+ }
+
+ public void OnError(Exception error)
+ {
+ if (_parent._selectorOnError != null)
+ {
+ var inner = default(IObservable<TResult>);
+
+ try
+ {
+ inner = _parent._selectorOnError(error);
+ }
+ catch (Exception ex)
+ {
+ lock (_gate)
+ {
+ base._observer.OnError(ex);
+ base.Dispose();
+ }
+ return;
+ }
+
+ SubscribeInner(inner);
+
+ Final();
+ }
+ else
+ {
+ lock (_gate)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+ }
+ }
+
+ public void OnCompleted()
+ {
+ if (_parent._selectorOnCompleted != null)
+ {
+ var inner = default(IObservable<TResult>);
+
+ try
+ {
+ inner = _parent._selectorOnCompleted();
+ }
+ catch (Exception ex)
+ {
+ lock (_gate)
+ {
+ base._observer.OnError(ex);
+ base.Dispose();
+ }
+ return;
+ }
+
+ SubscribeInner(inner);
+ }
+
+ Final();
+ }
+
+ private 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<T>.
+ //
+ lock (_gate)
+ {
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ else
+ {
+ _sourceSubscription.Dispose();
+ }
+ }
+
+ private void SubscribeInner(IObservable<TResult> inner)
+ {
+ var innerSubscription = new SingleAssignmentDisposable();
+ _group.Add(innerSubscription);
+ innerSubscription.Disposable = inner.SubscribeSafe(new ι(this, innerSubscription));
+ }
+
+ class ι : IObserver<TResult>
+ {
+ private readonly _ _parent;
+ private readonly IDisposable _self;
+
+ public ι(_ parent, IDisposable self)
+ {
+ _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<T>.
+ //
+ lock (_parent._gate)
+ {
+ _parent._observer.OnCompleted();
+ _parent.Dispose();
+ }
+ }
+ }
+ }
+ }
+
+ class ε : Sink<TResult>, IObserver<TSource>
+ {
+ private readonly SelectMany<TSource, TResult> _parent;
+
+ public ε(SelectMany<TSource, TResult> parent, IObserver<TResult> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ public void OnNext(TSource value)
+ {
+ var xs = default(IEnumerable<TResult>);
+ try
+ {
+ xs = _parent._selectorE(value);
+ }
+ catch (Exception exception)
+ {
+ base._observer.OnError(exception);
+ base.Dispose();
+ return;
+ }
+
+ var e = default(IEnumerator<TResult>);
+ 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);
+
+ try
+ {
+ hasNext = e.MoveNext();
+ if (hasNext)
+ current = e.Current;
+ }
+ catch (Exception exception)
+ {
+ base._observer.OnError(exception);
+ base.Dispose();
+ return;
+ }
+
+ 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();
+ }
+ }
+
+#if !NO_TPL
+#pragma warning disable 0420
+ class τ : Sink<TResult>, IObserver<TSource>
+ {
+ private readonly SelectMany<TSource, TResult> _parent;
+
+ public τ(SelectMany<TSource, TResult> parent, IObserver<TResult> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ private object _gate;
+ private CancellationDisposable _cancel;
+ private volatile int _count;
+
+ public IDisposable Run()
+ {
+ _gate = new object();
+ _cancel = new CancellationDisposable();
+ _count = 1;
+
+ return new CompositeDisposable(_parent._source.SubscribeSafe(this), _cancel);
+ }
+
+ public void OnNext(TSource value)
+ {
+ var task = default(Task<TResult>);
+ try
+ {
+ Interlocked.Increment(ref _count);
+ task = _parent._selectorT(value, _cancel.Token);
+ }
+ catch (Exception ex)
+ {
+ lock (_gate)
+ {
+ base._observer.OnError(ex);
+ base.Dispose();
+ }
+
+ return;
+ }
+
+ if (task.IsCompleted)
+ {
+ OnCompletedTask(task);
+ }
+ else
+ {
+ task.ContinueWith(OnCompletedTask);
+ }
+ }
+
+ private void OnCompletedTask(Task<TResult> task)
+ {
+ switch (task.Status)
+ {
+ case TaskStatus.RanToCompletion:
+ {
+ lock (_gate)
+ base._observer.OnNext(task.Result);
+
+ 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();
+ }
+ }
+ }
+ }
+#pragma warning restore 0420
+#endif
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/SequenceEqual.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/SequenceEqual.cs
new file mode 100644
index 0000000..4661f82
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/SequenceEqual.cs
@@ -0,0 +1,322 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+using System.Collections.Generic;
+using System.Reactive.Disposables;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class SequenceEqual<TSource> : Producer<bool>
+ {
+ private readonly IObservable<TSource> _first;
+ private readonly IObservable<TSource> _second;
+ private readonly IEnumerable<TSource> _secondE;
+ private readonly IEqualityComparer<TSource> _comparer;
+
+ public SequenceEqual(IObservable<TSource> first, IObservable<TSource> second, IEqualityComparer<TSource> comparer)
+ {
+ _first = first;
+ _second = second;
+ _comparer = comparer;
+ }
+
+ public SequenceEqual(IObservable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
+ {
+ _first = first;
+ _secondE = second;
+ _comparer = comparer;
+ }
+
+ protected override IDisposable Run(IObserver<bool> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ if (_second != null)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+ else
+ {
+ var sink = new ε(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+ }
+
+ class _ : Sink<bool>
+ {
+ private readonly SequenceEqual<TSource> _parent;
+
+ public _(SequenceEqual<TSource> parent, IObserver<bool> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ private object _gate;
+ private bool _donel;
+ private bool _doner;
+ private Queue<TSource> _ql;
+ private Queue<TSource> _qr;
+
+ public IDisposable Run()
+ {
+ _gate = new object();
+ _donel = false;
+ _doner = false;
+ _ql = new Queue<TSource>();
+ _qr = new Queue<TSource>();
+
+ return new CompositeDisposable
+ {
+ _parent._first.SubscribeSafe(new F(this)),
+ _parent._second.SubscribeSafe(new S(this))
+ };
+ }
+
+ class F : IObserver<TSource>
+ {
+ private readonly _ _parent;
+
+ public F(_ parent)
+ {
+ _parent = parent;
+ }
+
+ public void OnNext(TSource value)
+ {
+ lock (_parent._gate)
+ {
+ if (_parent._qr.Count > 0)
+ {
+ var equal = false;
+ var v = _parent._qr.Dequeue();
+ try
+ {
+ equal = _parent._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();
+ }
+ }
+ else if (_parent._doner)
+ {
+ _parent._observer.OnNext(false);
+ _parent._observer.OnCompleted();
+ _parent.Dispose();
+ }
+ else
+ _parent._ql.Enqueue(value);
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ _parent._observer.OnError(error);
+ _parent.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ lock (_parent._gate)
+ {
+ _parent._donel = true;
+ if (_parent._ql.Count == 0)
+ {
+ 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<TSource>
+ {
+ private readonly _ _parent;
+
+ public S(_ parent)
+ {
+ _parent = parent;
+ }
+
+ public void OnNext(TSource value)
+ {
+ lock (_parent._gate)
+ {
+ if (_parent._ql.Count > 0)
+ {
+ var equal = false;
+ var v = _parent._ql.Dequeue();
+ try
+ {
+ equal = _parent._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();
+ }
+ }
+ else if (_parent._donel)
+ {
+ _parent._observer.OnNext(false);
+ _parent._observer.OnCompleted();
+ _parent.Dispose();
+ }
+ else
+ _parent._qr.Enqueue(value);
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ _parent._observer.OnError(error);
+ _parent.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ lock (_parent._gate)
+ {
+ _parent._doner = true;
+ if (_parent._qr.Count == 0)
+ {
+ 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();
+ }
+ }
+ }
+ }
+ }
+ }
+
+ class ε : Sink<bool>, IObserver<TSource>
+ {
+ private readonly SequenceEqual<TSource> _parent;
+
+ public ε(SequenceEqual<TSource> parent, IObserver<bool> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ private IEnumerator<TSource> _enumerator;
+
+ public IDisposable Run()
+ {
+ //
+ // 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)
+ {
+ base._observer.OnError(exception);
+ base.Dispose();
+ return Disposable.Empty;
+ }
+
+ return new CompositeDisposable(
+ _parent._first.SubscribeSafe(this),
+ _enumerator
+ );
+ }
+
+ public void OnNext(TSource value)
+ {
+ var equal = false;
+
+ try
+ {
+ if (_enumerator.MoveNext())
+ {
+ var current = _enumerator.Current;
+ equal = _parent._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();
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ var hasNext = false;
+
+ try
+ {
+ hasNext = _enumerator.MoveNext();
+ }
+ catch (Exception exception)
+ {
+ base._observer.OnError(exception);
+ base.Dispose();
+ return;
+ }
+
+ base._observer.OnNext(!hasNext);
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/SingleAsync.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/SingleAsync.cs
new file mode 100644
index 0000000..19c07e5
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/SingleAsync.cs
@@ -0,0 +1,154 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class SingleAsync<TSource> : Producer<TSource>
+ {
+ private readonly IObservable<TSource> _source;
+ private readonly Func<TSource, bool> _predicate;
+ private readonly bool _throwOnEmpty;
+
+ public SingleAsync(IObservable<TSource> source, Func<TSource, bool> predicate, bool throwOnEmpty)
+ {
+ _source = source;
+ _predicate = predicate;
+ _throwOnEmpty = throwOnEmpty;
+ }
+
+ protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ if (_predicate != null)
+ {
+ var sink = new π(this, observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+ else
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+ }
+
+ class _ : Sink<TSource>, IObserver<TSource>
+ {
+ private readonly SingleAsync<TSource> _parent;
+ private TSource _value;
+ private bool _seenValue;
+
+ public _(SingleAsync<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+
+ _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()
+ {
+ if (!_seenValue && _parent._throwOnEmpty)
+ {
+ base._observer.OnError(new InvalidOperationException(Strings_Linq.NO_ELEMENTS));
+ }
+ else
+ {
+ base._observer.OnNext(_value);
+ base._observer.OnCompleted();
+ }
+
+ base.Dispose();
+ }
+ }
+
+ class π : Sink<TSource>, IObserver<TSource>
+ {
+ private readonly SingleAsync<TSource> _parent;
+ private TSource _value;
+ private bool _seenValue;
+
+ public π(SingleAsync<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+
+ _value = default(TSource);
+ _seenValue = false;
+ }
+
+ public void OnNext(TSource value)
+ {
+ var b = false;
+
+ try
+ {
+ b = _parent._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()
+ {
+ if (!_seenValue && _parent._throwOnEmpty)
+ {
+ base._observer.OnError(new InvalidOperationException(Strings_Linq.NO_MATCHING_ELEMENTS));
+ }
+ else
+ {
+ base._observer.OnNext(_value);
+ base._observer.OnCompleted();
+ }
+
+ base.Dispose();
+ }
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Skip.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Skip.cs
new file mode 100644
index 0000000..a092d99
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Skip.cs
@@ -0,0 +1,151 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+using System.Reactive.Concurrency;
+using System.Reactive.Disposables;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class Skip<TSource> : Producer<TSource>
+ {
+ private readonly IObservable<TSource> _source;
+ private readonly int _count;
+ private readonly TimeSpan _duration;
+ internal readonly IScheduler _scheduler;
+
+ public Skip(IObservable<TSource> source, int count)
+ {
+ _source = source;
+ _count = count;
+ }
+
+ public Skip(IObservable<TSource> source, TimeSpan duration, IScheduler scheduler)
+ {
+ _source = source;
+ _duration = duration;
+ _scheduler = scheduler;
+ }
+
+ public IObservable<TSource> Ω(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<TSource>(_source, _count + count);
+ }
+
+ public IObservable<TSource> Ω(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<TSource>(_source, duration, _scheduler);
+ }
+
+ protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ if (_scheduler == null)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+ else
+ {
+ var sink = new τ(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+ }
+
+ class _ : Sink<TSource>, IObserver<TSource>
+ {
+ private readonly Skip<TSource> _parent;
+ private int _remaining;
+
+ public _(Skip<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ _remaining = _parent._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 τ : Sink<TSource>, IObserver<TSource>
+ {
+ private readonly Skip<TSource> _parent;
+ private volatile bool _open;
+
+ public τ(Skip<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ public IDisposable Run()
+ {
+ var t = _parent._scheduler.Schedule(_parent._duration, Tick);
+ var d = _parent._source.SubscribeSafe(this);
+ return new CompositeDisposable(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();
+ }
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/SkipLast.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/SkipLast.cs
new file mode 100644
index 0000000..596f183
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/SkipLast.cs
@@ -0,0 +1,125 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+using System.Collections.Generic;
+using System.Reactive.Concurrency;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class SkipLast<TSource> : Producer<TSource>
+ {
+ private readonly IObservable<TSource> _source;
+ private readonly int _count;
+ private readonly TimeSpan _duration;
+ private readonly IScheduler _scheduler;
+
+ public SkipLast(IObservable<TSource> source, int count)
+ {
+ _source = source;
+ _count = count;
+ }
+
+ public SkipLast(IObservable<TSource> source, TimeSpan duration, IScheduler scheduler)
+ {
+ _source = source;
+ _duration = duration;
+ _scheduler = scheduler;
+ }
+
+ protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ if (_scheduler == null)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+ else
+ {
+ var sink = new τ(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+ }
+
+ class _ : Sink<TSource>, IObserver<TSource>
+ {
+ private readonly SkipLast<TSource> _parent;
+ private Queue<TSource> _queue;
+
+ public _(SkipLast<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ _queue = new Queue<TSource>();
+ }
+
+ public void OnNext(TSource value)
+ {
+ _queue.Enqueue(value);
+ if (_queue.Count > _parent._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 τ : Sink<TSource>, IObserver<TSource>
+ {
+ private readonly SkipLast<TSource> _parent;
+ private Queue<System.Reactive.TimeInterval<TSource>> _queue;
+
+ public τ(SkipLast<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ _queue = new Queue<System.Reactive.TimeInterval<TSource>>();
+ }
+
+ private IStopwatch _watch;
+
+ public IDisposable Run()
+ {
+ _watch = _parent._scheduler.StartStopwatch();
+
+ return _parent._source.SubscribeSafe(this);
+ }
+
+ public void OnNext(TSource value)
+ {
+ var now = _watch.Elapsed;
+ _queue.Enqueue(new System.Reactive.TimeInterval<TSource>(value, now));
+ while (_queue.Count > 0 && now - _queue.Peek().Interval >= _parent._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 >= _parent._duration)
+ base._observer.OnNext(_queue.Dequeue().Value);
+
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/SkipUntil.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/SkipUntil.cs
new file mode 100644
index 0000000..8d4c7a9
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/SkipUntil.cs
@@ -0,0 +1,210 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+using System.Reactive.Concurrency;
+using System.Reactive.Disposables;
+using System.Threading;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class SkipUntil<TSource, TOther> : Producer<TSource>
+ {
+ private readonly IObservable<TSource> _source;
+ private readonly IObservable<TOther> _other;
+
+ public SkipUntil(IObservable<TSource> source, IObservable<TOther> other)
+ {
+ _source = source;
+ _other = other;
+ }
+
+ protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+
+ class _ : Sink<TSource>
+ {
+ private readonly SkipUntil<TSource, TOther> _parent;
+
+ public _(SkipUntil<TSource, TOther> parent, IObserver<TSource> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ public IDisposable Run()
+ {
+ var sourceObserver = new T(this);
+ var otherObserver = new O(this, sourceObserver);
+
+ var sourceSubscription = _parent._source.SubscribeSafe(sourceObserver);
+ var otherSubscription = _parent._other.SubscribeSafe(otherObserver);
+
+ sourceObserver.Disposable = sourceSubscription;
+ otherObserver.Disposable = otherSubscription;
+
+ return new CompositeDisposable(
+ sourceSubscription,
+ otherSubscription
+ );
+ }
+
+ class T : IObserver<TSource>
+ {
+ private readonly _ _parent;
+ public volatile IObserver<TSource> _observer;
+ private readonly SingleAssignmentDisposable _subscription;
+
+ public T(_ parent)
+ {
+ _parent = parent;
+ _observer = NopObserver<TSource>.Instance;
+ _subscription = new SingleAssignmentDisposable();
+ }
+
+ public IDisposable Disposable
+ {
+ set { _subscription.Disposable = value; }
+ }
+
+ public void OnNext(TSource value)
+ {
+ _observer.OnNext(value);
+ }
+
+ public void OnError(Exception error)
+ {
+ _parent._observer.OnError(error);
+ _parent.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ _observer.OnCompleted();
+ _subscription.Dispose(); // We can't cancel the other stream yet, it may be on its way to dispatch an OnError message and we don't want to have a race.
+ }
+ }
+
+ class O : IObserver<TOther>
+ {
+ private readonly _ _parent;
+ private readonly T _sourceObserver;
+ private readonly SingleAssignmentDisposable _subscription;
+
+ public O(_ parent, T sourceObserver)
+ {
+ _parent = parent;
+ _sourceObserver = sourceObserver;
+ _subscription = new SingleAssignmentDisposable();
+ }
+
+ public IDisposable Disposable
+ {
+ set { _subscription.Disposable = value; }
+ }
+
+ public void OnNext(TOther value)
+ {
+ _sourceObserver._observer = _parent._observer;
+ _subscription.Dispose();
+ }
+
+ public void OnError(Exception error)
+ {
+ _parent._observer.OnError(error);
+ _parent.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ _subscription.Dispose();
+ }
+ }
+ }
+ }
+
+ class SkipUntil<TSource> : Producer<TSource>
+ {
+ private readonly IObservable<TSource> _source;
+ private readonly DateTimeOffset _startTime;
+ internal readonly IScheduler _scheduler;
+
+ public SkipUntil(IObservable<TSource> source, DateTimeOffset startTime, IScheduler scheduler)
+ {
+ _source = source;
+ _startTime = startTime;
+ _scheduler = scheduler;
+ }
+
+ public IObservable<TSource> Ω(DateTimeOffset startTime)
+ {
+ //
+ // 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.SU(5AM) xxxxxxxxxxxxxxxx-o--| xs.SU(3AM) xxxxxxxxxx-o--o--o--|
+ // xs.SU(5AM).SU(3AM) xxxxxxxxx--------o--| xs.SU(3AM).SU(5AM) xxxxxxxxxxxxxxxx-o--|
+ //
+ if (startTime <= _startTime)
+ return this;
+ else
+ return new SkipUntil<TSource>(_source, startTime, _scheduler);
+ }
+
+ protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+
+ class _ : Sink<TSource>, IObserver<TSource>
+ {
+ private readonly SkipUntil<TSource> _parent;
+ private volatile bool _open;
+
+ public _(SkipUntil<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ public IDisposable Run()
+ {
+ var t = _parent._scheduler.Schedule(_parent._startTime, Tick);
+ var d = _parent._source.SubscribeSafe(this);
+ return new CompositeDisposable(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();
+ }
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/SkipWhile.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/SkipWhile.cs
new file mode 100644
index 0000000..e6e379d
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/SkipWhile.cs
@@ -0,0 +1,139 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class SkipWhile<TSource> : Producer<TSource>
+ {
+ private readonly IObservable<TSource> _source;
+ private readonly Func<TSource, bool> _predicate;
+ private readonly Func<TSource, int, bool> _predicateI;
+
+ public SkipWhile(IObservable<TSource> source, Func<TSource, bool> predicate)
+ {
+ _source = source;
+ _predicate = predicate;
+ }
+
+ public SkipWhile(IObservable<TSource> source, Func<TSource, int, bool> predicate)
+ {
+ _source = source;
+ _predicateI = predicate;
+ }
+
+ protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ if (_predicate != null)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+ else
+ {
+ var sink = new τ(this, observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+ }
+
+ class _ : Sink<TSource>, IObserver<TSource>
+ {
+ private readonly SkipWhile<TSource> _parent;
+ private bool _running;
+
+ public _(SkipWhile<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ _running = false;
+ }
+
+ public void OnNext(TSource value)
+ {
+ if (!_running)
+ {
+ try
+ {
+ _running = !_parent._predicate(value);
+ }
+ catch (Exception exception)
+ {
+ base._observer.OnError(exception);
+ base.Dispose();
+ return;
+ }
+ }
+
+ if (_running)
+ {
+ base._observer.OnNext(value);
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+
+ class τ : Sink<TSource>, IObserver<TSource>
+ {
+ private readonly SkipWhile<TSource> _parent;
+ private bool _running;
+ private int _index;
+
+ public τ(SkipWhile<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ _running = false;
+ _index = 0;
+ }
+
+ public void OnNext(TSource value)
+ {
+ if (!_running)
+ {
+ try
+ {
+ _running = !_parent._predicateI(value, checked(_index++));
+ }
+ catch (Exception exception)
+ {
+ base._observer.OnError(exception);
+ base.Dispose();
+ return;
+ }
+ }
+
+ if (_running)
+ {
+ base._observer.OnNext(value);
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Sum.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Sum.cs
new file mode 100644
index 0000000..6d51153
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Sum.cs
@@ -0,0 +1,517 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class SumDouble : Producer<double>
+ {
+ private readonly IObservable<double> _source;
+
+ public SumDouble(IObservable<double> source)
+ {
+ _source = source;
+ }
+
+ protected override IDisposable Run(IObserver<double> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+
+ class _ : Sink<double>, IObserver<double>
+ {
+ private double _sum;
+
+ public _(IObserver<double> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _sum = 0.0;
+ }
+
+ public void OnNext(double value)
+ {
+ _sum += value;
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ base._observer.OnNext(_sum);
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+
+ class SumSingle : Producer<float>
+ {
+ private readonly IObservable<float> _source;
+
+ public SumSingle(IObservable<float> source)
+ {
+ _source = source;
+ }
+
+ protected override IDisposable Run(IObserver<float> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+
+ class _ : Sink<float>, IObserver<float>
+ {
+ private double _sum; // This is what LINQ to Objects does!
+
+ public _(IObserver<float> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _sum = 0.0; // This is what LINQ to Objects does!
+ }
+
+ public void OnNext(float value)
+ {
+ _sum += value; // This is what LINQ to Objects does!
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ base._observer.OnNext((float)_sum); // This is what LINQ to Objects does!
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+
+ class SumDecimal : Producer<decimal>
+ {
+ private readonly IObservable<decimal> _source;
+
+ public SumDecimal(IObservable<decimal> source)
+ {
+ _source = source;
+ }
+
+ protected override IDisposable Run(IObserver<decimal> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+
+ class _ : Sink<decimal>, IObserver<decimal>
+ {
+ private decimal _sum;
+
+ public _(IObserver<decimal> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _sum = 0M;
+ }
+
+ public void OnNext(decimal value)
+ {
+ _sum += value;
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ base._observer.OnNext(_sum);
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+
+ class SumInt32 : Producer<int>
+ {
+ private readonly IObservable<int> _source;
+
+ public SumInt32(IObservable<int> source)
+ {
+ _source = source;
+ }
+
+ protected override IDisposable Run(IObserver<int> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+
+ class _ : Sink<int>, IObserver<int>
+ {
+ private int _sum;
+
+ public _(IObserver<int> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _sum = 0;
+ }
+
+ public void OnNext(int value)
+ {
+ try
+ {
+ checked
+ {
+ _sum += value;
+ }
+ }
+ catch (Exception exception)
+ {
+ base._observer.OnError(exception);
+ base.Dispose();
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ base._observer.OnNext(_sum);
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+
+ class SumInt64 : Producer<long>
+ {
+ private readonly IObservable<long> _source;
+
+ public SumInt64(IObservable<long> source)
+ {
+ _source = source;
+ }
+
+ protected override IDisposable Run(IObserver<long> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+
+ class _ : Sink<long>, IObserver<long>
+ {
+ private long _sum;
+
+ public _(IObserver<long> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _sum = 0L;
+ }
+
+ public void OnNext(long value)
+ {
+ try
+ {
+ checked
+ {
+ _sum += value;
+ }
+ }
+ catch (Exception exception)
+ {
+ base._observer.OnError(exception);
+ base.Dispose();
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ base._observer.OnNext(_sum);
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+
+ class SumDoubleNullable : Producer<double?>
+ {
+ private readonly IObservable<double?> _source;
+
+ public SumDoubleNullable(IObservable<double?> source)
+ {
+ _source = source;
+ }
+
+ protected override IDisposable Run(IObserver<double?> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+
+ class _ : Sink<double?>, IObserver<double?>
+ {
+ private double _sum;
+
+ public _(IObserver<double?> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _sum = 0.0;
+ }
+
+ public void OnNext(double? value)
+ {
+ if (value != null)
+ _sum += value.Value;
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ base._observer.OnNext(_sum);
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+
+ class SumSingleNullable : Producer<float?>
+ {
+ private readonly IObservable<float?> _source;
+
+ public SumSingleNullable(IObservable<float?> source)
+ {
+ _source = source;
+ }
+
+ protected override IDisposable Run(IObserver<float?> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+
+ class _ : Sink<float?>, IObserver<float?>
+ {
+ private double _sum; // This is what LINQ to Objects does!
+
+ public _(IObserver<float?> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _sum = 0.0; // This is what LINQ to Objects does!
+ }
+
+ public void OnNext(float? value)
+ {
+ if (value != null)
+ _sum += value.Value; // This is what LINQ to Objects does!
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ base._observer.OnNext((float)_sum); // This is what LINQ to Objects does!
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+
+ class SumDecimalNullable : Producer<decimal?>
+ {
+ private readonly IObservable<decimal?> _source;
+
+ public SumDecimalNullable(IObservable<decimal?> source)
+ {
+ _source = source;
+ }
+
+ protected override IDisposable Run(IObserver<decimal?> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+
+ class _ : Sink<decimal?>, IObserver<decimal?>
+ {
+ private decimal _sum;
+
+ public _(IObserver<decimal?> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _sum = 0M;
+ }
+
+ public void OnNext(decimal? value)
+ {
+ if (value != null)
+ _sum += value.Value;
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ base._observer.OnNext(_sum);
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+
+ class SumInt32Nullable : Producer<int?>
+ {
+ private readonly IObservable<int?> _source;
+
+ public SumInt32Nullable(IObservable<int?> source)
+ {
+ _source = source;
+ }
+
+ protected override IDisposable Run(IObserver<int?> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+
+ class _ : Sink<int?>, IObserver<int?>
+ {
+ private int _sum;
+
+ public _(IObserver<int?> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _sum = 0;
+ }
+
+ public void OnNext(int? value)
+ {
+ try
+ {
+ checked
+ {
+ if (value != null)
+ _sum += value.Value;
+ }
+ }
+ catch (Exception exception)
+ {
+ base._observer.OnError(exception);
+ base.Dispose();
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ base._observer.OnNext(_sum);
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+
+ class SumInt64Nullable : Producer<long?>
+ {
+ private readonly IObservable<long?> _source;
+
+ public SumInt64Nullable(IObservable<long?> source)
+ {
+ _source = source;
+ }
+
+ protected override IDisposable Run(IObserver<long?> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+
+ class _ : Sink<long?>, IObserver<long?>
+ {
+ private long _sum;
+
+ public _(IObserver<long?> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _sum = 0L;
+ }
+
+ public void OnNext(long? value)
+ {
+ try
+ {
+ checked
+ {
+ if (value != null)
+ _sum += value.Value;
+ }
+ }
+ catch (Exception exception)
+ {
+ base._observer.OnError(exception);
+ base.Dispose();
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ base._observer.OnNext(_sum);
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Switch.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Switch.cs
new file mode 100644
index 0000000..794b0d4
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Switch.cs
@@ -0,0 +1,152 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+using System.Reactive.Disposables;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class Switch<TSource> : Producer<TSource>
+ {
+ private readonly IObservable<IObservable<TSource>> _sources;
+
+ public Switch(IObservable<IObservable<TSource>> sources)
+ {
+ _sources = sources;
+ }
+
+ protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+
+ class _ : Sink<TSource>, IObserver<IObservable<TSource>>
+ {
+ private readonly Switch<TSource> _parent;
+
+ public _(Switch<TSource> parent, IObserver<TSource> 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()
+ {
+ _gate = new object();
+ _innerSubscription = new SerialDisposable();
+ _isStopped = false;
+ _latest = 0UL;
+ _hasLatest = false;
+
+ var subscription = new SingleAssignmentDisposable();
+ _subscription = subscription;
+ subscription.Disposable = _parent._sources.SubscribeSafe(this);
+
+ return new CompositeDisposable(_subscription, _innerSubscription);
+ }
+
+ public void OnNext(IObservable<TSource> value)
+ {
+ var id = default(ulong);
+ lock (_gate)
+ {
+ id = unchecked(++_latest);
+ _hasLatest = true;
+ }
+
+ var d = new SingleAssignmentDisposable();
+ _innerSubscription.Disposable = d;
+ d.Disposable = value.SubscribeSafe(new ι(this, id, d));
+ }
+
+ public void OnError(Exception error)
+ {
+ lock (_gate)
+ base._observer.OnError(error);
+
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ lock (_gate)
+ {
+ _subscription.Dispose();
+
+ _isStopped = true;
+ if (!_hasLatest)
+ {
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+
+ class ι : IObserver<TSource>
+ {
+ private readonly _ _parent;
+ private readonly ulong _id;
+ private readonly IDisposable _self;
+
+ public ι(_ parent, ulong id, IDisposable self)
+ {
+ _parent = parent;
+ _id = id;
+ _self = self;
+ }
+
+ public void OnNext(TSource value)
+ {
+ lock (_parent._gate)
+ {
+ if (_parent._latest == _id)
+ _parent._observer.OnNext(value);
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ lock (_parent._gate)
+ {
+ _self.Dispose();
+
+ if (_parent._latest == _id)
+ {
+ _parent._observer.OnError(error);
+ _parent.Dispose();
+ }
+ }
+ }
+
+ public void OnCompleted()
+ {
+ lock (_parent._gate)
+ {
+ _self.Dispose();
+
+ if (_parent._latest == _id)
+ {
+ _parent._hasLatest = false;
+
+ if (_parent._isStopped)
+ {
+ _parent._observer.OnCompleted();
+ _parent.Dispose();
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Synchronize.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Synchronize.cs
new file mode 100644
index 0000000..36985e9
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Synchronize.cs
@@ -0,0 +1,71 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class Synchronize<TSource> : Producer<TSource>
+ {
+ private readonly IObservable<TSource> _source;
+ private readonly object _gate;
+
+ public Synchronize(IObservable<TSource> source, object gate)
+ {
+ _source = source;
+ _gate = gate;
+ }
+
+ public Synchronize(IObservable<TSource> source)
+ {
+ _source = source;
+ }
+
+ protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return _source.Subscribe(sink);
+ }
+
+ class _ : Sink<TSource>, IObserver<TSource>
+ {
+ private readonly Synchronize<TSource> _parent;
+ private object _gate;
+
+ public _(Synchronize<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ _gate = _parent._gate ?? new object();
+ }
+
+ public void OnNext(TSource value)
+ {
+ 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();
+ }
+ }
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Take.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Take.cs
new file mode 100644
index 0000000..738e7c0
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Take.cs
@@ -0,0 +1,176 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+using System.Reactive.Concurrency;
+using System.Reactive.Disposables;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class Take<TSource> : Producer<TSource>
+ {
+ private readonly IObservable<TSource> _source;
+ private readonly int _count;
+ private readonly TimeSpan _duration;
+ internal readonly IScheduler _scheduler;
+
+ public Take(IObservable<TSource> source, int count)
+ {
+ _source = source;
+ _count = count;
+ }
+
+ public Take(IObservable<TSource> source, TimeSpan duration, IScheduler scheduler)
+ {
+ _source = source;
+ _duration = duration;
+ _scheduler = scheduler;
+ }
+
+ public IObservable<TSource> Ω(int count)
+ {
+ //
+ // 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<TSource>(_source, count);
+ }
+
+ public IObservable<TSource> Ω(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<TSource>(_source, duration, _scheduler);
+ }
+
+ protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ if (_scheduler == null)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+ else
+ {
+ var sink = new τ(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+ }
+
+ class _ : Sink<TSource>, IObserver<TSource>
+ {
+ private readonly Take<TSource> _parent;
+ private int _remaining;
+
+ public _(Take<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ _remaining = _parent._count;
+ }
+
+ public void OnNext(TSource value)
+ {
+ if (_remaining > 0)
+ {
+ --_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 OnCompleted()
+ {
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+
+ class τ : Sink<TSource>, IObserver<TSource>
+ {
+ private readonly Take<TSource> _parent;
+
+ public τ(Take<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ private object _gate;
+
+ public IDisposable Run()
+ {
+ _gate = new object();
+
+ var t = _parent._scheduler.Schedule(_parent._duration, Tick);
+ var d = _parent._source.SubscribeSafe(this);
+ return new CompositeDisposable(t, d);
+ }
+
+ private void Tick()
+ {
+ lock (_gate)
+ {
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+
+ public void OnNext(TSource value)
+ {
+ 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();
+ }
+ }
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/TakeLast.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/TakeLast.cs
new file mode 100644
index 0000000..98bf40e
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/TakeLast.cs
@@ -0,0 +1,230 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+using System.Collections.Generic;
+using System.Reactive.Concurrency;
+using System.Reactive.Disposables;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class TakeLast<TSource> : Producer<TSource>
+ {
+ private readonly IObservable<TSource> _source;
+ private readonly int _count;
+ private readonly TimeSpan _duration;
+ private readonly IScheduler _scheduler;
+ private readonly IScheduler _loopScheduler;
+
+ public TakeLast(IObservable<TSource> source, int count, IScheduler loopScheduler)
+ {
+ _source = source;
+ _count = count;
+ _loopScheduler = loopScheduler;
+ }
+
+ public TakeLast(IObservable<TSource> source, TimeSpan duration, IScheduler scheduler, IScheduler loopScheduler)
+ {
+ _source = source;
+ _duration = duration;
+ _scheduler = scheduler;
+ _loopScheduler = loopScheduler;
+ }
+
+ protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ if (_scheduler == null)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+ else
+ {
+ var sink = new τ(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+ }
+
+ class _ : Sink<TSource>, IObserver<TSource>
+ {
+ private readonly TakeLast<TSource> _parent;
+ private Queue<TSource> _queue;
+
+ public _(TakeLast<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ _queue = new Queue<TSource>();
+ }
+
+ private SingleAssignmentDisposable _subscription;
+ private SingleAssignmentDisposable _loop;
+
+ public IDisposable Run()
+ {
+ _subscription = new SingleAssignmentDisposable();
+ _loop = new SingleAssignmentDisposable();
+
+ _subscription.Disposable = _parent._source.SubscribeSafe(this);
+
+ return new CompositeDisposable(_subscription, _loop);
+ }
+
+ 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();
+ }
+
+ 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);
+ }
+
+ private void LoopRec(Action recurse)
+ {
+ if (_queue.Count > 0)
+ {
+ base._observer.OnNext(_queue.Dequeue());
+ recurse();
+ }
+ else
+ {
+ base._observer.OnCompleted();
+ 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 τ : Sink<TSource>, IObserver<TSource>
+ {
+ private readonly TakeLast<TSource> _parent;
+ private Queue<System.Reactive.TimeInterval<TSource>> _queue;
+
+ public τ(TakeLast<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ _queue = new Queue<System.Reactive.TimeInterval<TSource>>();
+ }
+
+ private SingleAssignmentDisposable _subscription;
+ private SingleAssignmentDisposable _loop;
+ private IStopwatch _watch;
+
+ public IDisposable Run()
+ {
+ _subscription = new SingleAssignmentDisposable();
+ _loop = new SingleAssignmentDisposable();
+
+ _watch = _parent._scheduler.StartStopwatch();
+ _subscription.Disposable = _parent._source.SubscribeSafe(this);
+
+ return new CompositeDisposable(_subscription, _loop);
+ }
+
+ public void OnNext(TSource value)
+ {
+ var now = _watch.Elapsed;
+ _queue.Enqueue(new System.Reactive.TimeInterval<TSource>(value, now));
+ Trim(now);
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ 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);
+ }
+
+ private void LoopRec(Action recurse)
+ {
+ if (_queue.Count > 0)
+ {
+ base._observer.OnNext(_queue.Dequeue().Value);
+ recurse();
+ }
+ else
+ {
+ base._observer.OnCompleted();
+ 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().Value);
+
+ n--;
+ }
+
+ base.Dispose();
+ }
+
+ private void Trim(TimeSpan now)
+ {
+ while (_queue.Count > 0 && now - _queue.Peek().Interval >= _parent._duration)
+ _queue.Dequeue();
+ }
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/TakeLastBuffer.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/TakeLastBuffer.cs
new file mode 100644
index 0000000..71b36b0
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/TakeLastBuffer.cs
@@ -0,0 +1,141 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reactive.Concurrency;
+using System.Reactive.Disposables;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class TakeLastBuffer<TSource> : Producer<IList<TSource>>
+ {
+ private readonly IObservable<TSource> _source;
+ private readonly int _count;
+ private readonly TimeSpan _duration;
+ private readonly IScheduler _scheduler;
+
+ public TakeLastBuffer(IObservable<TSource> source, int count)
+ {
+ _source = source;
+ _count = count;
+ }
+
+ public TakeLastBuffer(IObservable<TSource> source, TimeSpan duration, IScheduler scheduler)
+ {
+ _source = source;
+ _duration = duration;
+ _scheduler = scheduler;
+ }
+
+ protected override IDisposable Run(IObserver<IList<TSource>> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ if (_scheduler == null)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+ else
+ {
+ var sink = new τ(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+ }
+
+ class _ : Sink<IList<TSource>>, IObserver<TSource>
+ {
+ private readonly TakeLastBuffer<TSource> _parent;
+ private Queue<TSource> _queue;
+
+ public _(TakeLastBuffer<TSource> parent, IObserver<IList<TSource>> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ _queue = new Queue<TSource>();
+ }
+
+ 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();
+ }
+
+ public void OnCompleted()
+ {
+ var res = new List<TSource>(_queue.Count);
+ while (_queue.Count > 0)
+ res.Add(_queue.Dequeue());
+
+ base._observer.OnNext(res);
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+
+ class τ : Sink<IList<TSource>>, IObserver<TSource>
+ {
+ private readonly TakeLastBuffer<TSource> _parent;
+ private Queue<System.Reactive.TimeInterval<TSource>> _queue;
+
+ public τ(TakeLastBuffer<TSource> parent, IObserver<IList<TSource>> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ _queue = new Queue<System.Reactive.TimeInterval<TSource>>();
+ }
+
+ private IStopwatch _watch;
+
+ public IDisposable Run()
+ {
+ _watch = _parent._scheduler.StartStopwatch();
+
+ return _parent._source.SubscribeSafe(this);
+ }
+
+ public void OnNext(TSource value)
+ {
+ var now = _watch.Elapsed;
+ _queue.Enqueue(new System.Reactive.TimeInterval<TSource>(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<TSource>(_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 >= _parent._duration)
+ _queue.Dequeue();
+ }
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/TakeUntil.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/TakeUntil.cs
new file mode 100644
index 0000000..eccc222
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/TakeUntil.cs
@@ -0,0 +1,258 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+using System.Reactive.Concurrency;
+using System.Reactive.Disposables;
+using System.Threading;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class TakeUntil<TSource, TOther> : Producer<TSource>
+ {
+ private readonly IObservable<TSource> _source;
+ private readonly IObservable<TOther> _other;
+
+ public TakeUntil(IObservable<TSource> source, IObservable<TOther> other)
+ {
+ _source = source;
+ _other = other;
+ }
+
+ protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+
+ class _ : Sink<TSource>
+ {
+ private readonly TakeUntil<TSource, TOther> _parent;
+
+ public _(TakeUntil<TSource, TOther> parent, IObserver<TSource> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ public IDisposable Run()
+ {
+ var sourceObserver = new T(this);
+ var otherObserver = new O(this, sourceObserver);
+
+ // COMPAT - Order of Subscribe calls per v1.0.10621
+ var otherSubscription = _parent._other.SubscribeSafe(otherObserver);
+ otherObserver.Disposable = otherSubscription;
+
+ var sourceSubscription = _parent._source.SubscribeSafe(sourceObserver);
+
+ return new CompositeDisposable(
+ otherSubscription,
+ sourceSubscription
+ );
+ }
+
+ /*
+ * We tried a more fine-grained synchronization scheme to make TakeUntil more efficient, but
+ * this requires several CAS instructions, which quickly add up to being non-beneficial.
+ *
+ * Notice an approach where the "other" channel performs an Interlocked.Exchange operation on
+ * the _parent._observer field to substitute it with a NopObserver<TSource> doesn't work,
+ * because the "other" channel still need 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.
+ *
+ * Fixing this issue requires an ownership transfer mechanism for channels to get exclusive
+ * 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<TSource>
+ {
+ private readonly _ _parent;
+ public volatile bool _open;
+
+ public T(_ parent)
+ {
+ _parent = parent;
+ _open = false;
+ }
+
+ public void OnNext(TSource value)
+ {
+ if (_open)
+ {
+ _parent._observer.OnNext(value);
+ }
+ else
+ {
+ lock (_parent)
+ {
+ _parent._observer.OnNext(value);
+ }
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ lock (_parent)
+ {
+ _parent._observer.OnError(error);
+ _parent.Dispose();
+ }
+ }
+
+ public void OnCompleted()
+ {
+ lock (_parent)
+ {
+ _parent._observer.OnCompleted();
+ _parent.Dispose();
+ }
+ }
+ }
+
+ class O : IObserver<TOther>
+ {
+ private readonly _ _parent;
+ private readonly T _sourceObserver;
+ private readonly SingleAssignmentDisposable _subscription;
+
+ public O(_ parent, T sourceObserver)
+ {
+ _parent = parent;
+ _sourceObserver = sourceObserver;
+ _subscription = new SingleAssignmentDisposable();
+ }
+
+ public IDisposable Disposable
+ {
+ set { _subscription.Disposable = value; }
+ }
+
+ public void OnNext(TOther value)
+ {
+ lock (_parent)
+ {
+ _parent._observer.OnCompleted();
+ _parent.Dispose();
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ lock (_parent)
+ {
+ _parent._observer.OnError(error);
+ _parent.Dispose();
+ }
+ }
+
+ public void OnCompleted()
+ {
+ lock (_parent)
+ {
+ _sourceObserver._open = true;
+ _subscription.Dispose();
+ }
+ }
+ }
+ }
+ }
+
+ class TakeUntil<TSource> : Producer<TSource>
+ {
+ private readonly IObservable<TSource> _source;
+ private readonly DateTimeOffset _endTime;
+ internal readonly IScheduler _scheduler;
+
+ public TakeUntil(IObservable<TSource> source, DateTimeOffset endTime, IScheduler scheduler)
+ {
+ _source = source;
+ _endTime = endTime;
+ _scheduler = scheduler;
+ }
+
+ public IObservable<TSource> Ω(DateTimeOffset endTime)
+ {
+ //
+ // 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.TU(5AM) --o--o--o--o--o| xs.TU(3AM) --o--o--o|
+ // xs.TU(5AM).TU(3AM) --o--o--o| xs.TU(3AM).TU(5AM) --o--o--o|
+ //
+ if (_endTime <= endTime)
+ return this;
+ else
+ return new TakeUntil<TSource>(_source, endTime, _scheduler);
+ }
+
+ protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+
+ class _ : Sink<TSource>, IObserver<TSource>
+ {
+ private readonly TakeUntil<TSource> _parent;
+
+ public _(TakeUntil<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ private object _gate;
+
+ public IDisposable Run()
+ {
+ _gate = new object();
+
+ var t = _parent._scheduler.Schedule(_parent._endTime, Tick);
+ var d = _parent._source.SubscribeSafe(this);
+ return new CompositeDisposable(t, d);
+ }
+
+ private void Tick()
+ {
+ lock (_gate)
+ {
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+
+ public void OnNext(TSource value)
+ {
+ 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();
+ }
+ }
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/TakeWhile.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/TakeWhile.cs
new file mode 100644
index 0000000..30f63ca
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/TakeWhile.cs
@@ -0,0 +1,149 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class TakeWhile<TSource> : Producer<TSource>
+ {
+ private readonly IObservable<TSource> _source;
+ private readonly Func<TSource, bool> _predicate;
+ private readonly Func<TSource, int, bool> _predicateI;
+
+ public TakeWhile(IObservable<TSource> source, Func<TSource, bool> predicate)
+ {
+ _source = source;
+ _predicate = predicate;
+ }
+
+ public TakeWhile(IObservable<TSource> source, Func<TSource, int, bool> predicate)
+ {
+ _source = source;
+ _predicateI = predicate;
+ }
+
+ protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ if (_predicate != null)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+ else
+ {
+ var sink = new τ(this, observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+ }
+
+ class _ : Sink<TSource>, IObserver<TSource>
+ {
+ private readonly TakeWhile<TSource> _parent;
+ private bool _running;
+
+ public _(TakeWhile<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ _running = true;
+ }
+
+ public void OnNext(TSource value)
+ {
+ if (_running)
+ {
+ try
+ {
+ _running = _parent._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 OnCompleted()
+ {
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+
+ class τ : Sink<TSource>, IObserver<TSource>
+ {
+ private readonly TakeWhile<TSource> _parent;
+ private bool _running;
+ private int _index;
+
+ public τ(TakeWhile<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ _running = true;
+ _index = 0;
+ }
+
+ public void OnNext(TSource value)
+ {
+ if (_running)
+ {
+ try
+ {
+ _running = _parent._predicateI(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 OnCompleted()
+ {
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Throttle.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Throttle.cs
new file mode 100644
index 0000000..7b7ad86
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Throttle.cs
@@ -0,0 +1,280 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+using System.Reactive.Concurrency;
+using System.Reactive.Disposables;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class Throttle<TSource> : Producer<TSource>
+ {
+ private readonly IObservable<TSource> _source;
+ private readonly TimeSpan _dueTime;
+ private readonly IScheduler _scheduler;
+
+ public Throttle(IObservable<TSource> source, TimeSpan dueTime, IScheduler scheduler)
+ {
+ _source = source;
+ _dueTime = dueTime;
+ _scheduler = scheduler;
+ }
+
+ protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+
+ class _ : Sink<TSource>, IObserver<TSource>
+ {
+ private readonly Throttle<TSource> _parent;
+
+ public _(Throttle<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ private object _gate;
+ private TSource _value;
+ private bool _hasValue;
+ private SerialDisposable _cancelable;
+ private ulong _id;
+
+ public IDisposable Run()
+ {
+ _gate = new object();
+ _value = default(TSource);
+ _hasValue = false;
+ _cancelable = new SerialDisposable();
+ _id = 0UL;
+
+ var subscription = _parent._source.SubscribeSafe(this);
+
+ return new CompositeDisposable(subscription, _cancelable);
+ }
+
+ public void OnNext(TSource value)
+ {
+ var currentid = default(ulong);
+ lock (_gate)
+ {
+ _hasValue = true;
+ _value = value;
+ _id = unchecked(_id + 1);
+ currentid = _id;
+ }
+ var d = new SingleAssignmentDisposable();
+ _cancelable.Disposable = d;
+ d.Disposable = _parent._scheduler.Schedule(currentid, _parent._dueTime, Propagate);
+ }
+
+ private IDisposable Propagate(IScheduler self, ulong currentid)
+ {
+ lock (_gate)
+ {
+ if (_hasValue && _id == currentid)
+ base._observer.OnNext(_value);
+ _hasValue = false;
+ }
+
+ return Disposable.Empty;
+ }
+
+ public void OnError(Exception error)
+ {
+ _cancelable.Dispose();
+
+ lock (_gate)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+
+ _hasValue = false;
+ _id = unchecked(_id + 1);
+ }
+ }
+
+ public void OnCompleted()
+ {
+ _cancelable.Dispose();
+
+ lock (_gate)
+ {
+ if (_hasValue)
+ base._observer.OnNext(_value);
+
+ base._observer.OnCompleted();
+ base.Dispose();
+
+ _hasValue = false;
+ _id = unchecked(_id + 1);
+ }
+ }
+ }
+ }
+
+ class Throttle<TSource, TThrottle> : Producer<TSource>
+ {
+ private readonly IObservable<TSource> _source;
+ private readonly Func<TSource, IObservable<TThrottle>> _throttleSelector;
+
+ public Throttle(IObservable<TSource> source, Func<TSource, IObservable<TThrottle>> throttleSelector)
+ {
+ _source = source;
+ _throttleSelector = throttleSelector;
+ }
+
+ protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+
+ class _ : Sink<TSource>, IObserver<TSource>
+ {
+ private readonly Throttle<TSource, TThrottle> _parent;
+
+ public _(Throttle<TSource, TThrottle> parent, IObserver<TSource> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ private object _gate;
+ private TSource _value;
+ private bool _hasValue;
+ private SerialDisposable _cancelable;
+ private ulong _id;
+
+ public IDisposable Run()
+ {
+ _gate = new object();
+ _value = default(TSource);
+ _hasValue = false;
+ _cancelable = new SerialDisposable();
+ _id = 0UL;
+
+ var subscription = _parent._source.SubscribeSafe(this);
+
+ return new CompositeDisposable(subscription, _cancelable);
+ }
+
+ public void OnNext(TSource value)
+ {
+ var throttle = default(IObservable<TThrottle>);
+ try
+ {
+ throttle = _parent._throttleSelector(value);
+ }
+ catch (Exception error)
+ {
+ lock (_gate)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ return;
+ }
+
+ ulong currentid;
+ lock (_gate)
+ {
+ _hasValue = true;
+ _value = value;
+ _id = unchecked(_id + 1);
+ currentid = _id;
+ }
+
+ var d = new SingleAssignmentDisposable();
+ _cancelable.Disposable = d;
+ d.Disposable = throttle.SubscribeSafe(new δ(this, value, currentid, d));
+ }
+
+ public void OnError(Exception error)
+ {
+ _cancelable.Dispose();
+
+ lock (_gate)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+
+ _hasValue = false;
+ _id = unchecked(_id + 1);
+ }
+ }
+
+ public void OnCompleted()
+ {
+ _cancelable.Dispose();
+
+ lock (_gate)
+ {
+ if (_hasValue)
+ base._observer.OnNext(_value);
+
+ base._observer.OnCompleted();
+ base.Dispose();
+
+ _hasValue = false;
+ _id = unchecked(_id + 1);
+ }
+ }
+
+ class δ : IObserver<TThrottle>
+ {
+ private readonly _ _parent;
+ private readonly TSource _value;
+ private readonly ulong _currentid;
+ private readonly IDisposable _self;
+
+ public δ(_ parent, TSource value, ulong currentid, IDisposable self)
+ {
+ _parent = parent;
+ _value = value;
+ _currentid = currentid;
+ _self = self;
+ }
+
+ public void OnNext(TThrottle value)
+ {
+ lock (_parent._gate)
+ {
+ if (_parent._hasValue && _parent._id == _currentid)
+ _parent._observer.OnNext(_value);
+
+ _parent._hasValue = false;
+ _self.Dispose();
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ lock (_parent._gate)
+ {
+ _parent._observer.OnError(error);
+ _parent.Dispose();
+ }
+ }
+
+ public void OnCompleted()
+ {
+ lock (_parent._gate)
+ {
+ if (_parent._hasValue && _parent._id == _currentid)
+ _parent._observer.OnNext(_value);
+
+ _parent._hasValue = false;
+ _self.Dispose();
+ }
+ }
+ }
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Throw.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Throw.cs
new file mode 100644
index 0000000..3b10894
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Throw.cs
@@ -0,0 +1,50 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+using System.Reactive.Concurrency;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class Throw<TResult> : Producer<TResult>
+ {
+ private readonly Exception _exception;
+ private readonly IScheduler _scheduler;
+
+ public Throw(Exception exception, IScheduler scheduler)
+ {
+ _exception = exception;
+ _scheduler = scheduler;
+ }
+
+ protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+
+ class _ : Sink<TResult>
+ {
+ private readonly Throw<TResult> _parent;
+
+ public _(Throw<TResult> parent, IObserver<TResult> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ public IDisposable Run()
+ {
+ return _parent._scheduler.Schedule(Invoke);
+ }
+
+ private void Invoke()
+ {
+ base._observer.OnError(_parent._exception);
+ base.Dispose();
+ }
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/TimeInterval.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/TimeInterval.cs
new file mode 100644
index 0000000..dacfa03
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/TimeInterval.cs
@@ -0,0 +1,73 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+using System.Diagnostics;
+using System.Reactive.Concurrency;
+using System.Reactive.Disposables;
+using System.Threading;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class TimeInterval<TSource> : Producer<System.Reactive.TimeInterval<TSource>>
+ {
+ private readonly IObservable<TSource> _source;
+ private readonly IScheduler _scheduler;
+
+ public TimeInterval(IObservable<TSource> source, IScheduler scheduler)
+ {
+ _source = source;
+ _scheduler = scheduler;
+ }
+
+ protected override IDisposable Run(IObserver<System.Reactive.TimeInterval<TSource>> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+
+ class _ : Sink<System.Reactive.TimeInterval<TSource>>, IObserver<TSource>
+ {
+ private readonly TimeInterval<TSource> _parent;
+
+ public _(TimeInterval<TSource> parent, IObserver<System.Reactive.TimeInterval<TSource>> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ private IStopwatch _watch;
+ private TimeSpan _last;
+
+ public IDisposable Run()
+ {
+ _watch = _parent._scheduler.StartStopwatch();
+ _last = TimeSpan.Zero;
+
+ return _parent._source.Subscribe(this);
+ }
+
+ public void OnNext(TSource value)
+ {
+ var now = _watch.Elapsed;
+ var span = now.Subtract(_last);
+ _last = now;
+ base._observer.OnNext(new System.Reactive.TimeInterval<TSource>(value, span));
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ base._observer.OnCompleted();
+ Dispose();
+ }
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Timeout.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Timeout.cs
new file mode 100644
index 0000000..4896294
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Timeout.cs
@@ -0,0 +1,432 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+using System.Reactive.Concurrency;
+using System.Reactive.Disposables;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class Timeout<TSource> : Producer<TSource>
+ {
+ private readonly IObservable<TSource> _source;
+ private readonly TimeSpan? _dueTimeR;
+ private readonly DateTimeOffset? _dueTimeA;
+ private readonly IObservable<TSource> _other;
+ private readonly IScheduler _scheduler;
+
+ public Timeout(IObservable<TSource> source, TimeSpan dueTime, IObservable<TSource> other, IScheduler scheduler)
+ {
+ _source = source;
+ _dueTimeR = dueTime;
+ _other = other;
+ _scheduler = scheduler;
+ }
+
+ public Timeout(IObservable<TSource> source, DateTimeOffset dueTime, IObservable<TSource> other, IScheduler scheduler)
+ {
+ _source = source;
+ _dueTimeA = dueTime;
+ _other = other;
+ _scheduler = scheduler;
+ }
+
+ protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ if (_dueTimeA.HasValue)
+ {
+ var sink = new α(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+ else
+ {
+ var sink = new ρ(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+ }
+
+ class α : Sink<TSource>, IObserver<TSource>
+ {
+ private readonly Timeout<TSource> _parent;
+
+ public α(Timeout<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ private SerialDisposable _subscription;
+ private object _gate;
+ private bool _switched;
+
+ public IDisposable Run()
+ {
+ _subscription = new SerialDisposable();
+ var original = new SingleAssignmentDisposable();
+
+ _subscription.Disposable = original;
+
+ _gate = new object();
+ _switched = false;
+
+ var timer = _parent._scheduler.Schedule(_parent._dueTimeA.Value, Timeout);
+
+ original.Disposable = _parent._source.SubscribeSafe(this);
+
+ return new CompositeDisposable(_subscription, timer);
+ }
+
+ private void Timeout()
+ {
+ var timerWins = false;
+
+ lock (_gate)
+ {
+ timerWins = !_switched;
+ _switched = true;
+ }
+
+ if (timerWins)
+ _subscription.Disposable = _parent._other.SubscribeSafe(this.GetForwarder());
+ }
+
+ public void OnNext(TSource value)
+ {
+ lock (_gate)
+ {
+ if (!_switched)
+ base._observer.OnNext(value);
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ var onErrorWins = false;
+
+ lock (_gate)
+ {
+ onErrorWins = !_switched;
+ _switched = true;
+ }
+
+ if (onErrorWins)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+ }
+
+ public void OnCompleted()
+ {
+ var onCompletedWins = false;
+
+ lock (_gate)
+ {
+ onCompletedWins = !_switched;
+ _switched = true;
+ }
+
+ if (onCompletedWins)
+ {
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+
+ class ρ : Sink<TSource>, IObserver<TSource>
+ {
+ private readonly Timeout<TSource> _parent;
+
+ public ρ(Timeout<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ private SerialDisposable _subscription;
+ private SerialDisposable _timer;
+
+ private object _gate;
+ private ulong _id;
+ private bool _switched;
+
+ public IDisposable Run()
+ {
+ _subscription = new SerialDisposable();
+ _timer = new SerialDisposable();
+ var original = new SingleAssignmentDisposable();
+
+ _subscription.Disposable = original;
+
+ _gate = new object();
+ _id = 0UL;
+ _switched = false;
+
+ CreateTimer();
+
+ original.Disposable = _parent._source.SubscribeSafe(this);
+
+ return new CompositeDisposable(_subscription, _timer);
+ }
+
+ private void CreateTimer()
+ {
+ _timer.Disposable = _parent._scheduler.Schedule(_id, _parent._dueTimeR.Value, Timeout);
+ }
+
+ private IDisposable Timeout(IScheduler _, ulong myid)
+ {
+ var timerWins = false;
+
+ lock (_gate)
+ {
+ _switched = (_id == myid);
+ timerWins = _switched;
+ }
+
+ if (timerWins)
+ _subscription.Disposable = _parent._other.SubscribeSafe(this.GetForwarder());
+
+ return Disposable.Empty;
+ }
+
+ public void OnNext(TSource value)
+ {
+ var onNextWins = false;
+
+ lock (_gate)
+ {
+ onNextWins = !_switched;
+ if (onNextWins)
+ {
+ _id = unchecked(_id + 1);
+ }
+ }
+
+ if (onNextWins)
+ {
+ base._observer.OnNext(value);
+ CreateTimer();
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ var onErrorWins = false;
+
+ lock (_gate)
+ {
+ onErrorWins = !_switched;
+ if (onErrorWins)
+ {
+ _id = unchecked(_id + 1);
+ }
+ }
+
+ if (onErrorWins)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+ }
+
+ public void OnCompleted()
+ {
+ var onCompletedWins = false;
+
+ lock (_gate)
+ {
+ onCompletedWins = !_switched;
+ if (onCompletedWins)
+ {
+ _id = unchecked(_id + 1);
+ }
+ }
+
+ if (onCompletedWins)
+ {
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+ }
+
+ class Timeout<TSource, TTimeout> : Producer<TSource>
+ {
+ private readonly IObservable<TSource> _source;
+ private readonly IObservable<TTimeout> _firstTimeout;
+ private readonly Func<TSource, IObservable<TTimeout>> _timeoutSelector;
+ private readonly IObservable<TSource> _other;
+
+ public Timeout(IObservable<TSource> source, IObservable<TTimeout> firstTimeout, Func<TSource, IObservable<TTimeout>> timeoutSelector, IObservable<TSource> other)
+ {
+ _source = source;
+ _firstTimeout = firstTimeout;
+ _timeoutSelector = timeoutSelector;
+ _other = other;
+ }
+
+ protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+
+ class _ : Sink<TSource>, IObserver<TSource>
+ {
+ private readonly Timeout<TSource, TTimeout> _parent;
+
+ public _(Timeout<TSource, TTimeout> parent, IObserver<TSource> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ private SerialDisposable _subscription;
+ private SerialDisposable _timer;
+ private object _gate;
+ private ulong _id;
+ private bool _switched;
+
+ public IDisposable Run()
+ {
+ _subscription = new SerialDisposable();
+ _timer = new SerialDisposable();
+ var original = new SingleAssignmentDisposable();
+
+ _subscription.Disposable = original;
+
+ _gate = new object();
+ _id = 0UL;
+ _switched = false;
+
+ SetTimer(_parent._firstTimeout);
+
+ original.Disposable = _parent._source.SubscribeSafe(this);
+
+ return new CompositeDisposable(_subscription, _timer);
+ }
+
+ public void OnNext(TSource value)
+ {
+ if (ObserverWins())
+ {
+ base._observer.OnNext(value);
+
+ var timeout = default(IObservable<TTimeout>);
+ try
+ {
+ timeout = _parent._timeoutSelector(value);
+ }
+ catch (Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ return;
+ }
+
+ SetTimer(timeout);
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ if (ObserverWins())
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+ }
+
+ public void OnCompleted()
+ {
+ if (ObserverWins())
+ {
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+
+ private void SetTimer(IObservable<TTimeout> timeout)
+ {
+ var myid = _id;
+
+ var d = new SingleAssignmentDisposable();
+ _timer.Disposable = d;
+ d.Disposable = timeout.SubscribeSafe(new τ(this, myid, d));
+ }
+
+ class τ : IObserver<TTimeout>
+ {
+ private readonly _ _parent;
+ private readonly ulong _id;
+ private readonly IDisposable _self;
+
+ public τ(_ parent, ulong id, IDisposable self)
+ {
+ _parent = parent;
+ _id = id;
+ _self = self;
+ }
+
+ public void OnNext(TTimeout value)
+ {
+ if (TimerWins())
+ _parent._subscription.Disposable = _parent._parent._other.SubscribeSafe(_parent.GetForwarder());
+
+ _self.Dispose();
+ }
+
+ public void OnError(Exception error)
+ {
+ if (TimerWins())
+ {
+ _parent._observer.OnError(error);
+ _parent.Dispose();
+ }
+ }
+
+ public void OnCompleted()
+ {
+ if (TimerWins())
+ _parent._subscription.Disposable = _parent._parent._other.SubscribeSafe(_parent.GetForwarder());
+ }
+
+ private bool TimerWins()
+ {
+ var res = false;
+
+ lock (_parent._gate)
+ {
+ _parent._switched = (_parent._id == _id);
+ res = _parent._switched;
+ }
+
+ return res;
+ }
+ }
+
+ private bool ObserverWins()
+ {
+ var res = false;
+
+ lock (_gate)
+ {
+ res = !_switched;
+ if (res)
+ {
+ _id = unchecked(_id + 1);
+ }
+ }
+
+ return res;
+ }
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Timer.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Timer.cs
new file mode 100644
index 0000000..22ee0df
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Timer.cs
@@ -0,0 +1,264 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+using System.Diagnostics;
+using System.Reactive.Concurrency;
+using System.Reactive.Disposables;
+using System.Threading;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class Timer : Producer<long>
+ {
+ 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)
+ {
+ _dueTimeR = dueTime;
+ _period = period;
+ _scheduler = scheduler;
+ }
+
+ protected override IDisposable Run(IObserver<long> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ if (_period.HasValue)
+ {
+ var sink = new π(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+ else
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+ }
+
+ class _ : Sink<long>
+ {
+ private readonly Timer _parent;
+
+ public _(Timer parent, IObserver<long> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ public IDisposable Run()
+ {
+ if (_parent._dueTimeA.HasValue)
+ {
+ return _parent._scheduler.Schedule(_parent._dueTimeA.Value, Invoke);
+ }
+ else
+ {
+ return _parent._scheduler.Schedule(_parent._dueTimeR.Value, Invoke);
+ }
+ }
+
+ private void Invoke()
+ {
+ base._observer.OnNext(0);
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+
+ class π : Sink<long>
+ {
+ private readonly Timer _parent;
+ private readonly TimeSpan _period;
+
+ public π(Timer parent, IObserver<long> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ _period = _parent._period.Value;
+ }
+
+ public IDisposable Run()
+ {
+ if (_parent._dueTimeA.HasValue)
+ {
+ var dueTime = _parent._dueTimeA.Value;
+ return _parent._scheduler.Schedule(default(object), dueTime, InvokeStart);
+ }
+ else
+ {
+ var dueTime = _parent._dueTimeR.Value;
+
+ //
+ // Optimize for the case of Observable.Interval.
+ //
+ if (dueTime == _period)
+ {
+ return _parent._scheduler.SchedulePeriodic(0L, _period, (Func<long, long>)Tick);
+ }
+
+ return _parent._scheduler.Schedule(default(object), dueTime, InvokeStart);
+ }
+ }
+
+ //
+ // 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)
+ {
+ base._observer.OnNext(count);
+ return unchecked(count + 1);
+ }
+
+ private int _pendingTickCount;
+ private IDisposable _periodic;
+
+ 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<long, long>)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<long, long>)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 new CompositeDisposable(2) { d, c };
+ }
+
+ return d;
+ }
+
+ private long Tock(long count)
+ {
+ //
+ // 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);
+ }
+
+ private void CatchUp(long count, Action<long> recurse)
+ {
+ 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));
+ }
+ }
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Timestamp.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Timestamp.cs
new file mode 100644
index 0000000..ed54678
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Timestamp.cs
@@ -0,0 +1,56 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+using System.Reactive.Concurrency;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class Timestamp<TSource> : Producer<Timestamped<TSource>>
+ {
+ private readonly IObservable<TSource> _source;
+ private readonly IScheduler _scheduler;
+
+ public Timestamp(IObservable<TSource> source, IScheduler scheduler)
+ {
+ _source = source;
+ _scheduler = scheduler;
+ }
+
+ protected override IDisposable Run(IObserver<Timestamped<TSource>> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+
+ class _ : Sink<Timestamped<TSource>>, IObserver<TSource>
+ {
+ private readonly Timestamp<TSource> _parent;
+
+ public _(Timestamp<TSource> parent, IObserver<Timestamped<TSource>> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ public void OnNext(TSource value)
+ {
+ base._observer.OnNext(new Timestamped<TSource>(value, _parent._scheduler.Now));
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/ToArray.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/ToArray.cs
new file mode 100644
index 0000000..ba039ae
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/ToArray.cs
@@ -0,0 +1,55 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+using System.Collections.Generic;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class ToArray<TSource> : Producer<TSource[]>
+ {
+ private readonly IObservable<TSource> _source;
+
+ public ToArray(IObservable<TSource> source)
+ {
+ _source = source;
+ }
+
+ protected override IDisposable Run(IObserver<TSource[]> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+
+ class _ : Sink<TSource[]>, IObserver<TSource>
+ {
+ private List<TSource> _list;
+
+ public _(IObserver<TSource[]> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _list = new List<TSource>();
+ }
+
+ public void OnNext(TSource value)
+ {
+ _list.Add(value);
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ base._observer.OnNext(_list.ToArray());
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/ToDictionary.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/ToDictionary.cs
new file mode 100644
index 0000000..919c1a1
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/ToDictionary.cs
@@ -0,0 +1,71 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+using System.Collections.Generic;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class ToDictionary<TSource, TKey, TElement> : Producer<IDictionary<TKey, TElement>>
+ {
+ private readonly IObservable<TSource> _source;
+ private readonly Func<TSource, TKey> _keySelector;
+ private readonly Func<TSource, TElement> _elementSelector;
+ private readonly IEqualityComparer<TKey> _comparer;
+
+ public ToDictionary(IObservable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey> comparer)
+ {
+ _source = source;
+ _keySelector = keySelector;
+ _elementSelector = elementSelector;
+ _comparer = comparer;
+ }
+
+ protected override IDisposable Run(IObserver<IDictionary<TKey, TElement>> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+
+ class _ : Sink<IDictionary<TKey, TElement>>, IObserver<TSource>
+ {
+ private readonly ToDictionary<TSource, TKey, TElement> _parent;
+ private Dictionary<TKey, TElement> _dictionary;
+
+ public _(ToDictionary<TSource, TKey, TElement> parent, IObserver<IDictionary<TKey, TElement>> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ _dictionary = new Dictionary<TKey, TElement>(_parent._comparer);
+ }
+
+ public void OnNext(TSource value)
+ {
+ try
+ {
+ _dictionary.Add(_parent._keySelector(value), _parent._elementSelector(value));
+ }
+ catch (Exception ex)
+ {
+ base._observer.OnError(ex);
+ base.Dispose();
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ base._observer.OnNext(_dictionary);
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/ToList.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/ToList.cs
new file mode 100644
index 0000000..34956d4
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/ToList.cs
@@ -0,0 +1,55 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+using System.Collections.Generic;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class ToList<TSource> : Producer<IList<TSource>>
+ {
+ private readonly IObservable<TSource> _source;
+
+ public ToList(IObservable<TSource> source)
+ {
+ _source = source;
+ }
+
+ protected override IDisposable Run(IObserver<IList<TSource>> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+
+ class _ : Sink<IList<TSource>>, IObserver<TSource>
+ {
+ private List<TSource> _list;
+
+ public _(IObserver<IList<TSource>> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _list = new List<TSource>();
+ }
+
+ public void OnNext(TSource value)
+ {
+ _list.Add(value);
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ base._observer.OnNext(_list);
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/ToLookup.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/ToLookup.cs
new file mode 100644
index 0000000..55ff7d3
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/ToLookup.cs
@@ -0,0 +1,72 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class ToLookup<TSource, TKey, TElement> : Producer<ILookup<TKey, TElement>>
+ {
+ private readonly IObservable<TSource> _source;
+ private readonly Func<TSource, TKey> _keySelector;
+ private readonly Func<TSource, TElement> _elementSelector;
+ private readonly IEqualityComparer<TKey> _comparer;
+
+ public ToLookup(IObservable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey> comparer)
+ {
+ _source = source;
+ _keySelector = keySelector;
+ _elementSelector = elementSelector;
+ _comparer = comparer;
+ }
+
+ protected override IDisposable Run(IObserver<ILookup<TKey, TElement>> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+
+ class _ : Sink<ILookup<TKey, TElement>>, IObserver<TSource>
+ {
+ private readonly ToLookup<TSource, TKey, TElement> _parent;
+ private Lookup<TKey, TElement> _lookup;
+
+ public _(ToLookup<TSource, TKey, TElement> parent, IObserver<ILookup<TKey, TElement>> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ _lookup = new Lookup<TKey, TElement>(_parent._comparer);
+ }
+
+ public void OnNext(TSource value)
+ {
+ try
+ {
+ _lookup.Add(_parent._keySelector(value), _parent._elementSelector(value));
+ }
+ catch (Exception ex)
+ {
+ base._observer.OnError(ex);
+ base.Dispose();
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ base._observer.OnNext(_lookup);
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/ToObservable.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/ToObservable.cs
new file mode 100644
index 0000000..795d54d
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/ToObservable.cs
@@ -0,0 +1,174 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+using System.Collections.Generic;
+using System.Reactive.Concurrency;
+using System.Reactive.Disposables;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class ToObservable<TSource> : Producer<TSource>
+ {
+ private readonly IEnumerable<TSource> _source;
+ private readonly IScheduler _scheduler;
+
+ public ToObservable(IEnumerable<TSource> source, IScheduler scheduler)
+ {
+ _source = source;
+ _scheduler = scheduler;
+ }
+
+ protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+
+ class _ : Sink<TSource>
+ {
+ private readonly ToObservable<TSource> _parent;
+
+ public _(ToObservable<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ public IDisposable Run()
+ {
+ var e = default(IEnumerator<TSource>);
+ try
+ {
+ e = _parent._source.GetEnumerator();
+ }
+ catch (Exception exception)
+ {
+ base._observer.OnError(exception);
+ base.Dispose();
+ return Disposable.Empty;
+ }
+
+ var longRunning = _parent._scheduler.AsLongRunning();
+ if (longRunning != null)
+ {
+ //
+ // Long-running schedulers have the contract they should *never* prevent
+ // the work from starting, such that the scheduled work has the chance
+ // to observe the cancellation and perform proper clean-up. In this case,
+ // we're sure Loop will be entered, allowing us to dispose the enumerator.
+ //
+ return longRunning.ScheduleLongRunning(e, Loop);
+ }
+ else
+ {
+ //
+ // We never allow the scheduled work to be cancelled. Instead, the flag
+ // is used to have LoopRec bail out and perform proper clean-up of the
+ // enumerator.
+ //
+ var flag = new BooleanDisposable();
+ _parent._scheduler.Schedule(new State(flag, e), LoopRec);
+ return flag;
+ }
+ }
+
+ class State
+ {
+ public readonly ICancelable flag;
+ public readonly IEnumerator<TSource> enumerator;
+
+ public State(ICancelable flag, IEnumerator<TSource> enumerator)
+ {
+ this.flag = flag;
+ this.enumerator = enumerator;
+ }
+ }
+
+ private void LoopRec(State state, Action<State> recurse)
+ {
+ var hasNext = false;
+ var ex = default(Exception);
+ var current = default(TSource);
+
+ if (state.flag.IsDisposed)
+ {
+ state.enumerator.Dispose();
+ return;
+ }
+
+ try
+ {
+ hasNext = state.enumerator.MoveNext();
+ if (hasNext)
+ current = state.enumerator.Current;
+ }
+ catch (Exception exception)
+ {
+ ex = exception;
+ }
+
+ if (ex != null)
+ {
+ state.enumerator.Dispose();
+
+ base._observer.OnError(ex);
+ base.Dispose();
+ return;
+ }
+
+ if (!hasNext)
+ {
+ state.enumerator.Dispose();
+
+ base._observer.OnCompleted();
+ base.Dispose();
+ return;
+ }
+
+ base._observer.OnNext(current);
+ recurse(state);
+ }
+
+ private void Loop(IEnumerator<TSource> enumerator, ICancelable cancel)
+ {
+ while (!cancel.IsDisposed)
+ {
+ var hasNext = false;
+ var ex = default(Exception);
+ var current = default(TSource);
+
+ try
+ {
+ hasNext = enumerator.MoveNext();
+ if (hasNext)
+ current = enumerator.Current;
+ }
+ catch (Exception exception)
+ {
+ ex = exception;
+ }
+
+ if (ex != null)
+ {
+ base._observer.OnError(ex);
+ break;
+ }
+
+ if (!hasNext)
+ {
+ base._observer.OnCompleted();
+ break;
+ }
+
+ base._observer.OnNext(current);
+ }
+
+ enumerator.Dispose();
+ base.Dispose();
+ }
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Using.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Using.cs
new file mode 100644
index 0000000..996ee0e
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Using.cs
@@ -0,0 +1,76 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+using System.Reactive.Disposables;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class Using<TSource, TResource> : Producer<TSource>
+ where TResource : IDisposable
+ {
+ private readonly Func<TResource> _resourceFactory;
+ private readonly Func<TResource, IObservable<TSource>> _observableFactory;
+
+ public Using(Func<TResource> resourceFactory, Func<TResource, IObservable<TSource>> observableFactory)
+ {
+ _resourceFactory = resourceFactory;
+ _observableFactory = observableFactory;
+ }
+
+ protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+
+ class _ : Sink<TSource>, IObserver<TSource>
+ {
+ private readonly Using<TSource, TResource> _parent;
+
+ public _(Using<TSource, TResource> parent, IObserver<TSource> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ public IDisposable Run()
+ {
+ var source = default(IObservable<TSource>);
+ var disposable = Disposable.Empty;
+ try
+ {
+ var resource = _parent._resourceFactory();
+ if (resource != null)
+ disposable = resource;
+ source = _parent._observableFactory(resource);
+ }
+ catch (Exception exception)
+ {
+ return new CompositeDisposable(Observable.Throw<TSource>(exception).SubscribeSafe(this), disposable);
+ }
+
+ return new CompositeDisposable(source.SubscribeSafe(this), disposable);
+ }
+
+ public void OnNext(TSource value)
+ {
+ base._observer.OnNext(value);
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Where.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Where.cs
new file mode 100644
index 0000000..a8eaa92
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Where.cs
@@ -0,0 +1,135 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class Where<TSource> : Producer<TSource>
+ {
+ private readonly IObservable<TSource> _source;
+ private readonly Func<TSource, bool> _predicate;
+ private readonly Func<TSource, int, bool> _predicateI;
+
+ public Where(IObservable<TSource> source, Func<TSource, bool> predicate)
+ {
+ _source = source;
+ _predicate = predicate;
+ }
+
+ public Where(IObservable<TSource> source, Func<TSource, int, bool> predicate)
+ {
+ _source = source;
+ _predicateI = predicate;
+ }
+
+ public IObservable<TSource> Ω(Func<TSource, bool> predicate)
+ {
+ if (_predicate != null)
+ return new Where<TSource>(_source, x => _predicate(x) && predicate(x));
+ else
+ return new Where<TSource>(this, predicate);
+ }
+
+ protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ if (_predicate != null)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+ else
+ {
+ var sink = new τ(this, observer, cancel);
+ setSink(sink);
+ return _source.SubscribeSafe(sink);
+ }
+ }
+
+ class _ : Sink<TSource>, IObserver<TSource>
+ {
+ private readonly Where<TSource> _parent;
+
+ public _(Where<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ public void OnNext(TSource value)
+ {
+ var shouldRun = default(bool);
+ try
+ {
+ shouldRun = _parent._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(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+
+ class τ : Sink<TSource>, IObserver<TSource>
+ {
+ private readonly Where<TSource> _parent;
+ private int _index;
+
+ public τ(Where<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ _index = 0;
+ }
+
+ public void OnNext(TSource value)
+ {
+ var shouldRun = default(bool);
+ try
+ {
+ shouldRun = _parent._predicateI(value, checked(_index++));
+ }
+ catch (Exception exception)
+ {
+ base._observer.OnError(exception);
+ 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();
+ }
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/While.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/While.cs
new file mode 100644
index 0000000..178e4c8
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/While.cs
@@ -0,0 +1,53 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+using System.Collections.Generic;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class While<TSource> : Producer<TSource>, IConcatenatable<TSource>
+ {
+ private readonly Func<bool> _condition;
+ private readonly IObservable<TSource> _source;
+
+ public While(Func<bool> condition, IObservable<TSource> source)
+ {
+ _condition = condition;
+ _source = source;
+ }
+
+ protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(observer, cancel);
+ setSink(sink);
+ return sink.Run(GetSources());
+ }
+
+ public IEnumerable<IObservable<TSource>> GetSources()
+ {
+ while (_condition())
+ yield return _source;
+ }
+
+ class _ : ConcatSink<TSource>
+ {
+ public _(IObserver<TSource> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ }
+
+ public override void OnNext(TSource value)
+ {
+ base._observer.OnNext(value);
+ }
+
+ public override void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+ }
+ }
+}
+#endif
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Window.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Window.cs
new file mode 100644
index 0000000..47059c7
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Window.cs
@@ -0,0 +1,758 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Reactive.Concurrency;
+using System.Reactive.Disposables;
+using System.Reactive.Subjects;
+using System.Threading;
+
+namespace System.Reactive.Linq.Observαble
+{
+ class Window<TSource> : Producer<IObservable<TSource>>
+ {
+ private readonly IObservable<TSource> _source;
+ private readonly int _count;
+ private readonly int _skip;
+
+ private readonly TimeSpan _timeSpan;
+ private readonly TimeSpan _timeShift;
+ private readonly IScheduler _scheduler;
+
+ public Window(IObservable<TSource> source, int count, int skip)
+ {
+ _source = source;
+ _count = count;
+ _skip = skip;
+ }
+
+ public Window(IObservable<TSource> source, TimeSpan timeSpan, TimeSpan timeShift, IScheduler scheduler)
+ {
+ _source = source;
+ _timeSpan = timeSpan;
+ _timeShift = timeShift;
+ _scheduler = scheduler;
+ }
+
+ public Window(IObservable<TSource> source, TimeSpan timeSpan, int count, IScheduler scheduler)
+ {
+ _source = source;
+ _timeSpan = timeSpan;
+ _count = count;
+ _scheduler = scheduler;
+ }
+
+ protected override IDisposable Run(IObserver<IObservable<TSource>> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ if (_scheduler == null)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+ else if (_count > 0)
+ {
+ var sink = new μ(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+ else
+ {
+ if (_timeSpan == _timeShift)
+ {
+ var sink = new π(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+ else
+ {
+ var sink = new τ(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+ }
+ }
+
+ class _ : Sink<IObservable<TSource>>, IObserver<TSource>
+ {
+ private readonly Window<TSource> _parent;
+
+ public _(Window<TSource> parent, IObserver<IObservable<TSource>> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ private Queue<ISubject<TSource>> _queue;
+ private int _n;
+ private SingleAssignmentDisposable _m;
+ private RefCountDisposable _refCountDisposable;
+
+ public IDisposable Run()
+ {
+ _queue = new Queue<ISubject<TSource>>();
+ _n = 0;
+ _m = new SingleAssignmentDisposable();
+ _refCountDisposable = new RefCountDisposable(_m);
+
+ var firstWindow = CreateWindow();
+ base._observer.OnNext(firstWindow);
+
+ _m.Disposable = _parent._source.SubscribeSafe(this);
+
+ return _refCountDisposable;
+ }
+
+ private IObservable<TSource> CreateWindow()
+ {
+ var s = new Subject<TSource>();
+ _queue.Enqueue(s);
+ return new WindowObservable<TSource>(s, _refCountDisposable);
+ }
+
+ public void OnNext(TSource value)
+ {
+ foreach (var s in _queue)
+ s.OnNext(value);
+
+ var c = _n - _parent._count + 1;
+ if (c >= 0 && c % _parent._skip == 0)
+ {
+ var s = _queue.Dequeue();
+ s.OnCompleted();
+ }
+
+ _n++;
+ if (_n % _parent._skip == 0)
+ {
+ var newWindow = CreateWindow();
+ base._observer.OnNext(newWindow);
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ while (_queue.Count > 0)
+ _queue.Dequeue().OnError(error);
+
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ while (_queue.Count > 0)
+ _queue.Dequeue().OnCompleted();
+
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+
+ class τ : Sink<IObservable<TSource>>, IObserver<TSource>
+ {
+ private readonly Window<TSource> _parent;
+
+ public τ(Window<TSource> parent, IObserver<IObservable<TSource>> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ private TimeSpan _totalTime;
+ private TimeSpan _nextShift;
+ private TimeSpan _nextSpan;
+
+ private object _gate;
+ private Queue<ISubject<TSource>> _q;
+
+ private SerialDisposable _timerD;
+ private RefCountDisposable _refCountDisposable;
+
+ public IDisposable Run()
+ {
+ _totalTime = TimeSpan.Zero;
+ _nextShift = _parent._timeShift;
+ _nextSpan = _parent._timeSpan;
+
+ _gate = new object();
+ _q = new Queue<ISubject<TSource>>();
+
+ _timerD = new SerialDisposable();
+
+ var groupDisposable = new CompositeDisposable(2) { _timerD };
+ _refCountDisposable = new RefCountDisposable(groupDisposable);
+
+ CreateWindow();
+ CreateTimer();
+
+ groupDisposable.Add(_parent._source.SubscribeSafe(this));
+
+ return _refCountDisposable;
+ }
+
+ private void CreateWindow()
+ {
+ var s = new Subject<TSource>();
+ _q.Enqueue(s);
+ base._observer.OnNext(new WindowObservable<TSource>(s, _refCountDisposable));
+ }
+
+ private void CreateTimer()
+ {
+ var m = new SingleAssignmentDisposable();
+ _timerD.Disposable = m;
+
+ var isSpan = false;
+ var isShift = false;
+ if (_nextSpan == _nextShift)
+ {
+ isSpan = true;
+ isShift = true;
+ }
+ else if (_nextSpan < _nextShift)
+ isSpan = true;
+ else
+ isShift = true;
+
+ var newTotalTime = isSpan ? _nextSpan : _nextShift;
+ var ts = newTotalTime - _totalTime;
+ _totalTime = newTotalTime;
+
+ if (isSpan)
+ _nextSpan += _parent._timeShift;
+ if (isShift)
+ _nextShift += _parent._timeShift;
+
+ m.Disposable = _parent._scheduler.Schedule(new State { isSpan = isSpan, isShift = isShift }, ts, Tick);
+ }
+
+ struct State
+ {
+ public bool isSpan;
+ public bool isShift;
+ }
+
+ private IDisposable Tick(IScheduler self, State state)
+ {
+ lock (_gate)
+ {
+ //
+ // 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();
+
+ return Disposable.Empty;
+ }
+
+ public void OnNext(TSource value)
+ {
+ lock (_gate)
+ {
+ foreach (var s in _q)
+ s.OnNext(value);
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ lock (_gate)
+ {
+ foreach (var s in _q)
+ s.OnError(error);
+
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+ }
+
+ public void OnCompleted()
+ {
+ lock (_gate)
+ {
+ foreach (var s in _q)
+ s.OnCompleted();
+
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+
+ class π : Sink<IObservable<TSource>>, IObserver<TSource>
+ {
+ private readonly Window<TSource> _parent;
+
+ public π(Window<TSource> parent, IObserver<IObservable<TSource>> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ private object _gate;
+ private Subject<TSource> _subject;
+ private RefCountDisposable _refCountDisposable;
+
+ public IDisposable Run()
+ {
+ _gate = new object();
+
+ var groupDisposable = new CompositeDisposable(2);
+ _refCountDisposable = new RefCountDisposable(groupDisposable);
+
+ CreateWindow();
+
+ groupDisposable.Add(_parent._scheduler.SchedulePeriodic(_parent._timeSpan, Tick));
+ groupDisposable.Add(_parent._source.SubscribeSafe(this));
+
+ return _refCountDisposable;
+ }
+
+ private void Tick()
+ {
+ lock (_gate)
+ {
+ _subject.OnCompleted();
+ CreateWindow();
+ }
+ }
+
+ private void CreateWindow()
+ {
+ _subject = new Subject<TSource>();
+ base._observer.OnNext(new WindowObservable<TSource>(_subject, _refCountDisposable));
+ }
+
+ public void OnNext(TSource value)
+ {
+ lock (_gate)
+ {
+ _subject.OnNext(value);
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ lock (_gate)
+ {
+ _subject.OnError(error);
+
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+ }
+
+ public void OnCompleted()
+ {
+ lock (_gate)
+ {
+ _subject.OnCompleted();
+
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+
+ class μ : Sink<IObservable<TSource>>, IObserver<TSource>
+ {
+ private readonly Window<TSource> _parent;
+
+ public μ(Window<TSource> parent, IObserver<IObservable<TSource>> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ private object _gate;
+ private ISubject<TSource> _s;
+ private int _n;
+ private int _windowId;
+
+ private SerialDisposable _timerD;
+ private RefCountDisposable _refCountDisposable;
+
+ public IDisposable Run()
+ {
+ _gate = new object();
+ _s = default(ISubject<TSource>);
+ _n = 0;
+ _windowId = 0;
+
+ _timerD = new SerialDisposable();
+ var groupDisposable = new CompositeDisposable(2) { _timerD };
+ _refCountDisposable = new RefCountDisposable(groupDisposable);
+
+ _s = new Subject<TSource>();
+ base._observer.OnNext(new WindowObservable<TSource>(_s, _refCountDisposable));
+ CreateTimer(0);
+
+ groupDisposable.Add(_parent._source.SubscribeSafe(this));
+
+ return _refCountDisposable;
+ }
+
+ private void CreateTimer(int id)
+ {
+ var m = new SingleAssignmentDisposable();
+ _timerD.Disposable = m;
+
+ m.Disposable = _parent._scheduler.Schedule(id, _parent._timeSpan, Tick);
+ }
+
+ private IDisposable Tick(IScheduler self, int id)
+ {
+ var d = Disposable.Empty;
+
+ var newId = 0;
+ lock (_gate)
+ {
+ if (id != _windowId)
+ return d;
+
+ _n = 0;
+ newId = ++_windowId;
+
+ _s.OnCompleted();
+ _s = new Subject<TSource>();
+ base._observer.OnNext(new WindowObservable<TSource>(_s, _refCountDisposable));
+ }
+
+ CreateTimer(newId);
+
+ return d;
+ }
+
+ public void OnNext(TSource value)
+ {
+ var newWindow = false;
+ var newId = 0;
+
+ lock (_gate)
+ {
+ _s.OnNext(value);
+
+ _n++;
+ if (_n == _parent._count)
+ {
+ newWindow = true;
+ _n = 0;
+ newId = ++_windowId;
+
+ _s.OnCompleted();
+ _s = new Subject<TSource>();
+ base._observer.OnNext(new WindowObservable<TSource>(_s, _refCountDisposable));
+ }
+ }
+
+ if (newWindow)
+ CreateTimer(newId);
+ }
+
+ public void OnError(Exception error)
+ {
+ lock (_gate)
+ {
+ _s.OnError(error);
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+ }
+
+ public void OnCompleted()
+ {
+ lock (_gate)
+ {
+ _s.OnCompleted();
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+ }
+
+ class Window<TSource, TWindowClosing> : Producer<IObservable<TSource>>
+ {
+ private readonly IObservable<TSource> _source;
+ private readonly Func<IObservable<TWindowClosing>> _windowClosingSelector;
+ private readonly IObservable<TWindowClosing> _windowBoundaries;
+
+ public Window(IObservable<TSource> source, Func<IObservable<TWindowClosing>> windowClosingSelector)
+ {
+ _source = source;
+ _windowClosingSelector = windowClosingSelector;
+ }
+
+ public Window(IObservable<TSource> source, IObservable<TWindowClosing> windowBoundaries)
+ {
+ _source = source;
+ _windowBoundaries = windowBoundaries;
+ }
+
+ protected override IDisposable Run(IObserver<IObservable<TSource>> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ if (_windowClosingSelector != null)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+ else
+ {
+ var sink = new β(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+ }
+
+ class _ : Sink<IObservable<TSource>>, IObserver<TSource>
+ {
+ private readonly Window<TSource, TWindowClosing> _parent;
+
+ public _(Window<TSource, TWindowClosing> parent, IObserver<IObservable<TSource>> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ private ISubject<TSource> _window;
+ private object _gate;
+ private AsyncLock _windowGate;
+
+ private SerialDisposable _m;
+ private RefCountDisposable _refCountDisposable;
+
+ public IDisposable Run()
+ {
+ _window = new Subject<TSource>();
+ _gate = new object();
+ _windowGate = new AsyncLock();
+
+ _m = new SerialDisposable();
+ var groupDisposable = new CompositeDisposable(2) { _m };
+ _refCountDisposable = new RefCountDisposable(groupDisposable);
+
+ var window = new WindowObservable<TSource>(_window, _refCountDisposable);
+ base._observer.OnNext(window);
+
+ groupDisposable.Add(_parent._source.SubscribeSafe(this));
+
+ _windowGate.Wait(CreateWindowClose);
+
+ return _refCountDisposable;
+ }
+
+ private void CreateWindowClose()
+ {
+ var windowClose = default(IObservable<TWindowClosing>);
+ try
+ {
+ windowClose = _parent._windowClosingSelector();
+ }
+ catch (Exception exception)
+ {
+ lock (_gate)
+ {
+ base._observer.OnError(exception);
+ base.Dispose();
+ }
+ return;
+ }
+
+ var closingSubscription = new SingleAssignmentDisposable();
+ _m.Disposable = closingSubscription;
+ closingSubscription.Disposable = windowClose.SubscribeSafe(new ω(this, closingSubscription));
+ }
+
+ private void CloseWindow(IDisposable closingSubscription)
+ {
+ closingSubscription.Dispose();
+
+ lock (_gate)
+ {
+ _window.OnCompleted();
+ _window = new Subject<TSource>();
+
+ var window = new WindowObservable<TSource>(_window, _refCountDisposable);
+ base._observer.OnNext(window);
+ }
+
+ _windowGate.Wait(CreateWindowClose);
+ }
+
+ class ω : IObserver<TWindowClosing>
+ {
+ private readonly _ _parent;
+ private readonly IDisposable _self;
+
+ public ω(_ 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(TSource value)
+ {
+ lock (_gate)
+ {
+ _window.OnNext(value);
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ lock (_gate)
+ {
+ _window.OnError(error);
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+ }
+
+ public void OnCompleted()
+ {
+ lock (_gate)
+ {
+ _window.OnCompleted();
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+
+ class β : Sink<IObservable<TSource>>, IObserver<TSource>
+ {
+ private readonly Window<TSource, TWindowClosing> _parent;
+
+ public β(Window<TSource, TWindowClosing> parent, IObserver<IObservable<TSource>> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ private ISubject<TSource> _window;
+ private object _gate;
+
+ private RefCountDisposable _refCountDisposable;
+
+ public IDisposable Run()
+ {
+ _window = new Subject<TSource>();
+ _gate = new object();
+
+ var d = new CompositeDisposable(2);
+ _refCountDisposable = new RefCountDisposable(d);
+
+ var window = new WindowObservable<TSource>(_window, _refCountDisposable);
+ base._observer.OnNext(window);
+
+ d.Add(_parent._source.SubscribeSafe(this));
+ d.Add(_parent._windowBoundaries.SubscribeSafe(new ω(this)));
+
+ return _refCountDisposable;
+ }
+
+ class ω : IObserver<TWindowClosing>
+ {
+ private readonly β _parent;
+
+ public ω(β parent)
+ {
+ _parent = parent;
+ }
+
+ public void OnNext(TWindowClosing value)
+ {
+ lock (_parent._gate)
+ {
+ _parent._window.OnCompleted();
+ _parent._window = new Subject<TSource>();
+
+ var window = new WindowObservable<TSource>(_parent._window, _parent._refCountDisposable);
+ _parent._observer.OnNext(window);
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ _parent.OnError(error);
+ }
+
+ public void OnCompleted()
+ {
+ _parent.OnCompleted();
+ }
+ }
+
+ public void OnNext(TSource value)
+ {
+ lock (_gate)
+ {
+ _window.OnNext(value);
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ lock (_gate)
+ {
+ _window.OnError(error);
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+ }
+
+ public void OnCompleted()
+ {
+ lock (_gate)
+ {
+ _window.OnCompleted();
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+ }
+
+ class WindowObservable<TSource> : AddRef<TSource>
+ {
+ public WindowObservable(IObservable<TSource> source, RefCountDisposable refCount)
+ : base(source, refCount)
+ {
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Zip.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Zip.cs
new file mode 100644
index 0000000..bde6e29
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/Zip.cs
@@ -0,0 +1,2326 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reactive.Disposables;
+
+namespace System.Reactive.Linq.Observαble
+{
+ #region Binary
+
+ class Zip<TFirst, TSecond, TResult> : Producer<TResult>
+ {
+ private readonly IObservable<TFirst> _first;
+ private readonly IObservable<TSecond> _second;
+ private readonly IEnumerable<TSecond> _secondE;
+ private readonly Func<TFirst, TSecond, TResult> _resultSelector;
+
+ public Zip(IObservable<TFirst> first, IObservable<TSecond> second, Func<TFirst, TSecond, TResult> resultSelector)
+ {
+ _first = first;
+ _second = second;
+ _resultSelector = resultSelector;
+ }
+
+ public Zip(IObservable<TFirst> first, IEnumerable<TSecond> second, Func<TFirst, TSecond, TResult> resultSelector)
+ {
+ _first = first;
+ _secondE = second;
+ _resultSelector = resultSelector;
+ }
+
+ protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ if (_second != null)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+ else
+ {
+ var sink = new ε(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+ }
+
+ class _ : Sink<TResult>
+ {
+ private readonly Zip<TFirst, TSecond, TResult> _parent;
+
+ public _(Zip<TFirst, TSecond, TResult> parent, IObserver<TResult> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ private object _gate;
+
+ public IDisposable Run()
+ {
+ _gate = new object();
+
+ var fstSubscription = new SingleAssignmentDisposable();
+ var sndSubscription = new SingleAssignmentDisposable();
+
+ var fstO = new F(this, fstSubscription);
+ var sndO = new S(this, sndSubscription);
+
+ fstO.Other = sndO;
+ sndO.Other = fstO;
+
+ fstSubscription.Disposable = _parent._first.SubscribeSafe(fstO);
+ sndSubscription.Disposable = _parent._second.SubscribeSafe(sndO);
+
+ return new CompositeDisposable(fstSubscription, sndSubscription, fstO, sndO);
+ }
+
+ class F : IObserver<TFirst>, IDisposable
+ {
+ private readonly _ _parent;
+ private readonly IDisposable _self;
+ private S _other;
+ private Queue<TFirst> _queue;
+
+ public F(_ parent, IDisposable self)
+ {
+ _parent = parent;
+ _self = self;
+ _queue = new Queue<TFirst>();
+ }
+
+ public S Other { set { _other = value; } }
+
+ public Queue<TFirst> Queue { get { return _queue; } }
+ public bool Done { get; private set; }
+
+ public void OnNext(TFirst value)
+ {
+ lock (_parent._gate)
+ {
+ if (_other.Queue.Count > 0)
+ {
+ var r = _other.Queue.Dequeue();
+
+ var res = default(TResult);
+ try
+ {
+ res = _parent._parent._resultSelector(value, r);
+ }
+ catch (Exception ex)
+ {
+ _parent._observer.OnError(ex);
+ _parent.Dispose();
+ return;
+ }
+
+ _parent._observer.OnNext(res);
+ }
+ else
+ {
+ if (_other.Done)
+ {
+ _parent._observer.OnCompleted();
+ _parent.Dispose();
+ return;
+ }
+
+ _queue.Enqueue(value);
+ }
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ lock (_parent._gate)
+ {
+ _parent._observer.OnError(error);
+ _parent.Dispose();
+ }
+ }
+
+ 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 S : IObserver<TSecond>, IDisposable
+ {
+ private readonly _ _parent;
+ private readonly IDisposable _self;
+ private F _other;
+ private Queue<TSecond> _queue;
+
+ public S(_ parent, IDisposable self)
+ {
+ _parent = parent;
+ _self = self;
+ _queue = new Queue<TSecond>();
+ }
+
+ public F Other { set { _other = value; } }
+
+ public Queue<TSecond> Queue { get { return _queue; } }
+ public bool Done { get; private set; }
+
+ public void OnNext(TSecond value)
+ {
+ lock (_parent._gate)
+ {
+ if (_other.Queue.Count > 0)
+ {
+ var l = _other.Queue.Dequeue();
+
+ var res = default(TResult);
+ try
+ {
+ res = _parent._parent._resultSelector(l, value);
+ }
+ catch (Exception ex)
+ {
+ _parent._observer.OnError(ex);
+ _parent.Dispose();
+ return;
+ }
+
+ _parent._observer.OnNext(res);
+ }
+ else
+ {
+ if (_other.Done)
+ {
+ _parent._observer.OnCompleted();
+ _parent.Dispose();
+ return;
+ }
+
+ _queue.Enqueue(value);
+ }
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ lock (_parent._gate)
+ {
+ _parent._observer.OnError(error);
+ _parent.Dispose();
+ }
+ }
+
+ 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 ε : Sink<TResult>, IObserver<TFirst>
+ {
+ private readonly Zip<TFirst, TSecond, TResult> _parent;
+
+ public ε(Zip<TFirst, TSecond, TResult> parent, IObserver<TResult> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ private IEnumerator<TSecond> _rightEnumerator;
+
+ public IDisposable Run()
+ {
+ //
+ // 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 new CompositeDisposable(leftSubscription, _rightEnumerator);
+ }
+
+ public void OnNext(TFirst value)
+ {
+ var hasNext = false;
+ try
+ {
+ hasNext = _rightEnumerator.MoveNext();
+ }
+ catch (Exception ex)
+ {
+ base._observer.OnError(ex);
+ base.Dispose();
+ return;
+ }
+
+ if (hasNext)
+ {
+ var right = default(TSecond);
+ try
+ {
+ right = _rightEnumerator.Current;
+ }
+ catch (Exception ex)
+ {
+ base._observer.OnError(ex);
+ base.Dispose();
+ return;
+ }
+
+ TResult result;
+ try
+ {
+ result = _parent._resultSelector(value, right);
+ }
+ catch (Exception ex)
+ {
+ base._observer.OnError(ex);
+ base.Dispose();
+ return;
+ }
+
+ base._observer.OnNext(result);
+ }
+ else
+ {
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void OnCompleted()
+ {
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+
+ #endregion
+
+ #region [3,16]-ary
+
+ /* The following code is generated by a tool checked in to $/.../Source/Tools/CodeGenerators. */
+
+ #region Zip auto-generated code (6/10/2012 8:13:21 PM)
+
+ class Zip<T1, T2, T3, TResult> : Producer<TResult>
+ {
+ private readonly IObservable<T1> _source1;
+ private readonly IObservable<T2> _source2;
+ private readonly IObservable<T3> _source3;
+ private readonly Func<T1, T2, T3, TResult> _resultSelector;
+
+ public Zip(IObservable<T1> source1, IObservable<T2> source2, IObservable<T3> source3, Func<T1, T2, T3, TResult> resultSelector)
+ {
+ _source1 = source1;
+ _source2 = source2;
+ _source3 = source3;
+ _resultSelector = resultSelector;
+ }
+
+ protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+
+ class _ : ZipSink<TResult>
+ {
+ private readonly Zip<T1, T2, T3, TResult> _parent;
+
+ public _(Zip<T1, T2, T3, TResult> parent, IObserver<TResult> observer, IDisposable cancel)
+ : base(3, observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ private ZipObserver<T1> _observer1;
+ private ZipObserver<T2> _observer2;
+ private ZipObserver<T3> _observer3;
+
+ public IDisposable Run()
+ {
+ var subscriptions = new SingleAssignmentDisposable[3];
+ for (int i = 0; i < 3; i++)
+ subscriptions[i] = new SingleAssignmentDisposable();
+
+ _observer1 = new ZipObserver<T1>(_gate, this, 0, subscriptions[0]);
+ _observer2 = new ZipObserver<T2>(_gate, this, 1, subscriptions[1]);
+ _observer3 = new ZipObserver<T3>(_gate, this, 2, subscriptions[2]);
+
+ base.Queues[0] = _observer1.Values;
+ base.Queues[1] = _observer2.Values;
+ base.Queues[2] = _observer3.Values;
+
+ subscriptions[0].Disposable = _parent._source1.SubscribeSafe(_observer1);
+ subscriptions[1].Disposable = _parent._source2.SubscribeSafe(_observer2);
+ subscriptions[2].Disposable = _parent._source3.SubscribeSafe(_observer3);
+
+ return new CompositeDisposable(subscriptions)
+ {
+ Disposable.Create(() =>
+ {
+ _observer1.Values.Clear();
+ _observer2.Values.Clear();
+ _observer3.Values.Clear();
+ })
+ };
+ }
+
+ protected override TResult GetResult()
+ {
+ return _parent._resultSelector(_observer1.Values.Dequeue(), _observer2.Values.Dequeue(), _observer3.Values.Dequeue());
+ }
+ }
+ }
+
+ class Zip<T1, T2, T3, T4, TResult> : Producer<TResult>
+ {
+ private readonly IObservable<T1> _source1;
+ private readonly IObservable<T2> _source2;
+ private readonly IObservable<T3> _source3;
+ private readonly IObservable<T4> _source4;
+ private readonly Func<T1, T2, T3, T4, TResult> _resultSelector;
+
+ public Zip(IObservable<T1> source1, IObservable<T2> source2, IObservable<T3> source3, IObservable<T4> source4, Func<T1, T2, T3, T4, TResult> resultSelector)
+ {
+ _source1 = source1;
+ _source2 = source2;
+ _source3 = source3;
+ _source4 = source4;
+ _resultSelector = resultSelector;
+ }
+
+ protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+
+ class _ : ZipSink<TResult>
+ {
+ private readonly Zip<T1, T2, T3, T4, TResult> _parent;
+
+ public _(Zip<T1, T2, T3, T4, TResult> parent, IObserver<TResult> observer, IDisposable cancel)
+ : base(4, observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ private ZipObserver<T1> _observer1;
+ private ZipObserver<T2> _observer2;
+ private ZipObserver<T3> _observer3;
+ private ZipObserver<T4> _observer4;
+
+ public IDisposable Run()
+ {
+ var subscriptions = new SingleAssignmentDisposable[4];
+ for (int i = 0; i < 4; i++)
+ subscriptions[i] = new SingleAssignmentDisposable();
+
+ _observer1 = new ZipObserver<T1>(_gate, this, 0, subscriptions[0]);
+ _observer2 = new ZipObserver<T2>(_gate, this, 1, subscriptions[1]);
+ _observer3 = new ZipObserver<T3>(_gate, this, 2, subscriptions[2]);
+ _observer4 = new ZipObserver<T4>(_gate, this, 3, subscriptions[3]);
+
+ base.Queues[0] = _observer1.Values;
+ base.Queues[1] = _observer2.Values;
+ base.Queues[2] = _observer3.Values;
+ base.Queues[3] = _observer4.Values;
+
+ 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);
+
+ return new CompositeDisposable(subscriptions)
+ {
+ Disposable.Create(() =>
+ {
+ _observer1.Values.Clear();
+ _observer2.Values.Clear();
+ _observer3.Values.Clear();
+ _observer4.Values.Clear();
+ })
+ };
+ }
+
+ protected override TResult GetResult()
+ {
+ return _parent._resultSelector(_observer1.Values.Dequeue(), _observer2.Values.Dequeue(), _observer3.Values.Dequeue(), _observer4.Values.Dequeue());
+ }
+ }
+ }
+
+#if !NO_LARGEARITY
+ class Zip<T1, T2, T3, T4, T5, TResult> : Producer<TResult>
+ {
+ private readonly IObservable<T1> _source1;
+ private readonly IObservable<T2> _source2;
+ private readonly IObservable<T3> _source3;
+ private readonly IObservable<T4> _source4;
+ private readonly IObservable<T5> _source5;
+ private readonly Func<T1, T2, T3, T4, T5, TResult> _resultSelector;
+
+ public Zip(IObservable<T1> source1, IObservable<T2> source2, IObservable<T3> source3, IObservable<T4> source4, IObservable<T5> source5, Func<T1, T2, T3, T4, T5, TResult> resultSelector)
+ {
+ _source1 = source1;
+ _source2 = source2;
+ _source3 = source3;
+ _source4 = source4;
+ _source5 = source5;
+ _resultSelector = resultSelector;
+ }
+
+ protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+
+ class _ : ZipSink<TResult>
+ {
+ private readonly Zip<T1, T2, T3, T4, T5, TResult> _parent;
+
+ public _(Zip<T1, T2, T3, T4, T5, TResult> parent, IObserver<TResult> observer, IDisposable cancel)
+ : base(5, observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ private ZipObserver<T1> _observer1;
+ private ZipObserver<T2> _observer2;
+ private ZipObserver<T3> _observer3;
+ private ZipObserver<T4> _observer4;
+ private ZipObserver<T5> _observer5;
+
+ public IDisposable Run()
+ {
+ var subscriptions = new SingleAssignmentDisposable[5];
+ for (int i = 0; i < 5; i++)
+ subscriptions[i] = new SingleAssignmentDisposable();
+
+ _observer1 = new ZipObserver<T1>(_gate, this, 0, subscriptions[0]);
+ _observer2 = new ZipObserver<T2>(_gate, this, 1, subscriptions[1]);
+ _observer3 = new ZipObserver<T3>(_gate, this, 2, subscriptions[2]);
+ _observer4 = new ZipObserver<T4>(_gate, this, 3, subscriptions[3]);
+ _observer5 = new ZipObserver<T5>(_gate, this, 4, subscriptions[4]);
+
+ base.Queues[0] = _observer1.Values;
+ base.Queues[1] = _observer2.Values;
+ base.Queues[2] = _observer3.Values;
+ base.Queues[3] = _observer4.Values;
+ base.Queues[4] = _observer5.Values;
+
+ 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);
+
+ return new CompositeDisposable(subscriptions)
+ {
+ Disposable.Create(() =>
+ {
+ _observer1.Values.Clear();
+ _observer2.Values.Clear();
+ _observer3.Values.Clear();
+ _observer4.Values.Clear();
+ _observer5.Values.Clear();
+ })
+ };
+ }
+
+ protected override TResult GetResult()
+ {
+ return _parent._resultSelector(_observer1.Values.Dequeue(), _observer2.Values.Dequeue(), _observer3.Values.Dequeue(), _observer4.Values.Dequeue(), _observer5.Values.Dequeue());
+ }
+ }
+ }
+
+ class Zip<T1, T2, T3, T4, T5, T6, TResult> : Producer<TResult>
+ {
+ private readonly IObservable<T1> _source1;
+ private readonly IObservable<T2> _source2;
+ private readonly IObservable<T3> _source3;
+ private readonly IObservable<T4> _source4;
+ private readonly IObservable<T5> _source5;
+ private readonly IObservable<T6> _source6;
+ private readonly Func<T1, T2, T3, T4, T5, T6, TResult> _resultSelector;
+
+ public Zip(IObservable<T1> source1, IObservable<T2> source2, IObservable<T3> source3, IObservable<T4> source4, IObservable<T5> source5, IObservable<T6> source6, Func<T1, T2, T3, T4, T5, T6, TResult> resultSelector)
+ {
+ _source1 = source1;
+ _source2 = source2;
+ _source3 = source3;
+ _source4 = source4;
+ _source5 = source5;
+ _source6 = source6;
+ _resultSelector = resultSelector;
+ }
+
+ protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+
+ class _ : ZipSink<TResult>
+ {
+ private readonly Zip<T1, T2, T3, T4, T5, T6, TResult> _parent;
+
+ public _(Zip<T1, T2, T3, T4, T5, T6, TResult> parent, IObserver<TResult> observer, IDisposable cancel)
+ : base(6, observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ private ZipObserver<T1> _observer1;
+ private ZipObserver<T2> _observer2;
+ private ZipObserver<T3> _observer3;
+ private ZipObserver<T4> _observer4;
+ private ZipObserver<T5> _observer5;
+ private ZipObserver<T6> _observer6;
+
+ public IDisposable Run()
+ {
+ var subscriptions = new SingleAssignmentDisposable[6];
+ for (int i = 0; i < 6; i++)
+ subscriptions[i] = new SingleAssignmentDisposable();
+
+ _observer1 = new ZipObserver<T1>(_gate, this, 0, subscriptions[0]);
+ _observer2 = new ZipObserver<T2>(_gate, this, 1, subscriptions[1]);
+ _observer3 = new ZipObserver<T3>(_gate, this, 2, subscriptions[2]);
+ _observer4 = new ZipObserver<T4>(_gate, this, 3, subscriptions[3]);
+ _observer5 = new ZipObserver<T5>(_gate, this, 4, subscriptions[4]);
+ _observer6 = new ZipObserver<T6>(_gate, this, 5, subscriptions[5]);
+
+ base.Queues[0] = _observer1.Values;
+ base.Queues[1] = _observer2.Values;
+ base.Queues[2] = _observer3.Values;
+ base.Queues[3] = _observer4.Values;
+ base.Queues[4] = _observer5.Values;
+ base.Queues[5] = _observer6.Values;
+
+ 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);
+
+ return new CompositeDisposable(subscriptions)
+ {
+ Disposable.Create(() =>
+ {
+ _observer1.Values.Clear();
+ _observer2.Values.Clear();
+ _observer3.Values.Clear();
+ _observer4.Values.Clear();
+ _observer5.Values.Clear();
+ _observer6.Values.Clear();
+ })
+ };
+ }
+
+ 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());
+ }
+ }
+ }
+
+ class Zip<T1, T2, T3, T4, T5, T6, T7, TResult> : Producer<TResult>
+ {
+ private readonly IObservable<T1> _source1;
+ private readonly IObservable<T2> _source2;
+ private readonly IObservable<T3> _source3;
+ private readonly IObservable<T4> _source4;
+ private readonly IObservable<T5> _source5;
+ private readonly IObservable<T6> _source6;
+ private readonly IObservable<T7> _source7;
+ private readonly Func<T1, T2, T3, T4, T5, T6, T7, TResult> _resultSelector;
+
+ public Zip(IObservable<T1> source1, IObservable<T2> source2, IObservable<T3> source3, IObservable<T4> source4, IObservable<T5> source5, IObservable<T6> source6, IObservable<T7> source7, Func<T1, T2, T3, T4, T5, T6, T7, TResult> resultSelector)
+ {
+ _source1 = source1;
+ _source2 = source2;
+ _source3 = source3;
+ _source4 = source4;
+ _source5 = source5;
+ _source6 = source6;
+ _source7 = source7;
+ _resultSelector = resultSelector;
+ }
+
+ protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+
+ class _ : ZipSink<TResult>
+ {
+ private readonly Zip<T1, T2, T3, T4, T5, T6, T7, TResult> _parent;
+
+ public _(Zip<T1, T2, T3, T4, T5, T6, T7, TResult> parent, IObserver<TResult> observer, IDisposable cancel)
+ : base(7, observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ private ZipObserver<T1> _observer1;
+ private ZipObserver<T2> _observer2;
+ private ZipObserver<T3> _observer3;
+ private ZipObserver<T4> _observer4;
+ private ZipObserver<T5> _observer5;
+ private ZipObserver<T6> _observer6;
+ private ZipObserver<T7> _observer7;
+
+ public IDisposable Run()
+ {
+ var subscriptions = new SingleAssignmentDisposable[7];
+ for (int i = 0; i < 7; i++)
+ subscriptions[i] = new SingleAssignmentDisposable();
+
+ _observer1 = new ZipObserver<T1>(_gate, this, 0, subscriptions[0]);
+ _observer2 = new ZipObserver<T2>(_gate, this, 1, subscriptions[1]);
+ _observer3 = new ZipObserver<T3>(_gate, this, 2, subscriptions[2]);
+ _observer4 = new ZipObserver<T4>(_gate, this, 3, subscriptions[3]);
+ _observer5 = new ZipObserver<T5>(_gate, this, 4, subscriptions[4]);
+ _observer6 = new ZipObserver<T6>(_gate, this, 5, subscriptions[5]);
+ _observer7 = new ZipObserver<T7>(_gate, this, 6, subscriptions[6]);
+
+ base.Queues[0] = _observer1.Values;
+ base.Queues[1] = _observer2.Values;
+ base.Queues[2] = _observer3.Values;
+ base.Queues[3] = _observer4.Values;
+ base.Queues[4] = _observer5.Values;
+ base.Queues[5] = _observer6.Values;
+ base.Queues[6] = _observer7.Values;
+
+ 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);
+
+ return new CompositeDisposable(subscriptions)
+ {
+ Disposable.Create(() =>
+ {
+ _observer1.Values.Clear();
+ _observer2.Values.Clear();
+ _observer3.Values.Clear();
+ _observer4.Values.Clear();
+ _observer5.Values.Clear();
+ _observer6.Values.Clear();
+ _observer7.Values.Clear();
+ })
+ };
+ }
+
+ 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());
+ }
+ }
+ }
+
+ class Zip<T1, T2, T3, T4, T5, T6, T7, T8, TResult> : Producer<TResult>
+ {
+ private readonly IObservable<T1> _source1;
+ private readonly IObservable<T2> _source2;
+ private readonly IObservable<T3> _source3;
+ private readonly IObservable<T4> _source4;
+ private readonly IObservable<T5> _source5;
+ private readonly IObservable<T6> _source6;
+ private readonly IObservable<T7> _source7;
+ private readonly IObservable<T8> _source8;
+ private readonly Func<T1, T2, T3, T4, T5, T6, T7, T8, TResult> _resultSelector;
+
+ public Zip(IObservable<T1> source1, IObservable<T2> source2, IObservable<T3> source3, IObservable<T4> source4, IObservable<T5> source5, IObservable<T6> source6, IObservable<T7> source7, IObservable<T8> source8, Func<T1, T2, T3, T4, T5, T6, T7, T8, TResult> resultSelector)
+ {
+ _source1 = source1;
+ _source2 = source2;
+ _source3 = source3;
+ _source4 = source4;
+ _source5 = source5;
+ _source6 = source6;
+ _source7 = source7;
+ _source8 = source8;
+ _resultSelector = resultSelector;
+ }
+
+ protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+
+ class _ : ZipSink<TResult>
+ {
+ private readonly Zip<T1, T2, T3, T4, T5, T6, T7, T8, TResult> _parent;
+
+ public _(Zip<T1, T2, T3, T4, T5, T6, T7, T8, TResult> parent, IObserver<TResult> observer, IDisposable cancel)
+ : base(8, observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ private ZipObserver<T1> _observer1;
+ private ZipObserver<T2> _observer2;
+ private ZipObserver<T3> _observer3;
+ private ZipObserver<T4> _observer4;
+ private ZipObserver<T5> _observer5;
+ private ZipObserver<T6> _observer6;
+ private ZipObserver<T7> _observer7;
+ private ZipObserver<T8> _observer8;
+
+ public IDisposable Run()
+ {
+ var subscriptions = new SingleAssignmentDisposable[8];
+ for (int i = 0; i < 8; i++)
+ subscriptions[i] = new SingleAssignmentDisposable();
+
+ _observer1 = new ZipObserver<T1>(_gate, this, 0, subscriptions[0]);
+ _observer2 = new ZipObserver<T2>(_gate, this, 1, subscriptions[1]);
+ _observer3 = new ZipObserver<T3>(_gate, this, 2, subscriptions[2]);
+ _observer4 = new ZipObserver<T4>(_gate, this, 3, subscriptions[3]);
+ _observer5 = new ZipObserver<T5>(_gate, this, 4, subscriptions[4]);
+ _observer6 = new ZipObserver<T6>(_gate, this, 5, subscriptions[5]);
+ _observer7 = new ZipObserver<T7>(_gate, this, 6, subscriptions[6]);
+ _observer8 = new ZipObserver<T8>(_gate, this, 7, subscriptions[7]);
+
+ base.Queues[0] = _observer1.Values;
+ base.Queues[1] = _observer2.Values;
+ base.Queues[2] = _observer3.Values;
+ base.Queues[3] = _observer4.Values;
+ base.Queues[4] = _observer5.Values;
+ base.Queues[5] = _observer6.Values;
+ base.Queues[6] = _observer7.Values;
+ base.Queues[7] = _observer8.Values;
+
+ 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);
+
+ return new CompositeDisposable(subscriptions)
+ {
+ Disposable.Create(() =>
+ {
+ _observer1.Values.Clear();
+ _observer2.Values.Clear();
+ _observer3.Values.Clear();
+ _observer4.Values.Clear();
+ _observer5.Values.Clear();
+ _observer6.Values.Clear();
+ _observer7.Values.Clear();
+ _observer8.Values.Clear();
+ })
+ };
+ }
+
+ 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());
+ }
+ }
+ }
+
+ class Zip<T1, T2, T3, T4, T5, T6, T7, T8, T9, TResult> : Producer<TResult>
+ {
+ private readonly IObservable<T1> _source1;
+ private readonly IObservable<T2> _source2;
+ private readonly IObservable<T3> _source3;
+ private readonly IObservable<T4> _source4;
+ private readonly IObservable<T5> _source5;
+ private readonly IObservable<T6> _source6;
+ private readonly IObservable<T7> _source7;
+ private readonly IObservable<T8> _source8;
+ private readonly IObservable<T9> _source9;
+ private readonly Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, TResult> _resultSelector;
+
+ public Zip(IObservable<T1> source1, IObservable<T2> source2, IObservable<T3> source3, IObservable<T4> source4, IObservable<T5> source5, IObservable<T6> source6, IObservable<T7> source7, IObservable<T8> source8, IObservable<T9> source9, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, TResult> resultSelector)
+ {
+ _source1 = source1;
+ _source2 = source2;
+ _source3 = source3;
+ _source4 = source4;
+ _source5 = source5;
+ _source6 = source6;
+ _source7 = source7;
+ _source8 = source8;
+ _source9 = source9;
+ _resultSelector = resultSelector;
+ }
+
+ protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+
+ class _ : ZipSink<TResult>
+ {
+ private readonly Zip<T1, T2, T3, T4, T5, T6, T7, T8, T9, TResult> _parent;
+
+ public _(Zip<T1, T2, T3, T4, T5, T6, T7, T8, T9, TResult> parent, IObserver<TResult> observer, IDisposable cancel)
+ : base(9, observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ private ZipObserver<T1> _observer1;
+ private ZipObserver<T2> _observer2;
+ private ZipObserver<T3> _observer3;
+ private ZipObserver<T4> _observer4;
+ private ZipObserver<T5> _observer5;
+ private ZipObserver<T6> _observer6;
+ private ZipObserver<T7> _observer7;
+ private ZipObserver<T8> _observer8;
+ private ZipObserver<T9> _observer9;
+
+ public IDisposable Run()
+ {
+ var subscriptions = new SingleAssignmentDisposable[9];
+ for (int i = 0; i < 9; i++)
+ subscriptions[i] = new SingleAssignmentDisposable();
+
+ _observer1 = new ZipObserver<T1>(_gate, this, 0, subscriptions[0]);
+ _observer2 = new ZipObserver<T2>(_gate, this, 1, subscriptions[1]);
+ _observer3 = new ZipObserver<T3>(_gate, this, 2, subscriptions[2]);
+ _observer4 = new ZipObserver<T4>(_gate, this, 3, subscriptions[3]);
+ _observer5 = new ZipObserver<T5>(_gate, this, 4, subscriptions[4]);
+ _observer6 = new ZipObserver<T6>(_gate, this, 5, subscriptions[5]);
+ _observer7 = new ZipObserver<T7>(_gate, this, 6, subscriptions[6]);
+ _observer8 = new ZipObserver<T8>(_gate, this, 7, subscriptions[7]);
+ _observer9 = new ZipObserver<T9>(_gate, this, 8, subscriptions[8]);
+
+ base.Queues[0] = _observer1.Values;
+ base.Queues[1] = _observer2.Values;
+ base.Queues[2] = _observer3.Values;
+ base.Queues[3] = _observer4.Values;
+ base.Queues[4] = _observer5.Values;
+ base.Queues[5] = _observer6.Values;
+ base.Queues[6] = _observer7.Values;
+ base.Queues[7] = _observer8.Values;
+ base.Queues[8] = _observer9.Values;
+
+ 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);
+
+ return new CompositeDisposable(subscriptions)
+ {
+ Disposable.Create(() =>
+ {
+ _observer1.Values.Clear();
+ _observer2.Values.Clear();
+ _observer3.Values.Clear();
+ _observer4.Values.Clear();
+ _observer5.Values.Clear();
+ _observer6.Values.Clear();
+ _observer7.Values.Clear();
+ _observer8.Values.Clear();
+ _observer9.Values.Clear();
+ })
+ };
+ }
+
+ 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());
+ }
+ }
+ }
+
+ class Zip<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TResult> : Producer<TResult>
+ {
+ private readonly IObservable<T1> _source1;
+ private readonly IObservable<T2> _source2;
+ private readonly IObservable<T3> _source3;
+ private readonly IObservable<T4> _source4;
+ private readonly IObservable<T5> _source5;
+ private readonly IObservable<T6> _source6;
+ private readonly IObservable<T7> _source7;
+ private readonly IObservable<T8> _source8;
+ private readonly IObservable<T9> _source9;
+ private readonly IObservable<T10> _source10;
+ private readonly Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TResult> _resultSelector;
+
+ public Zip(IObservable<T1> source1, IObservable<T2> source2, IObservable<T3> source3, IObservable<T4> source4, IObservable<T5> source5, IObservable<T6> source6, IObservable<T7> source7, IObservable<T8> source8, IObservable<T9> source9, IObservable<T10> source10, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TResult> resultSelector)
+ {
+ _source1 = source1;
+ _source2 = source2;
+ _source3 = source3;
+ _source4 = source4;
+ _source5 = source5;
+ _source6 = source6;
+ _source7 = source7;
+ _source8 = source8;
+ _source9 = source9;
+ _source10 = source10;
+ _resultSelector = resultSelector;
+ }
+
+ protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+
+ class _ : ZipSink<TResult>
+ {
+ private readonly Zip<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TResult> _parent;
+
+ public _(Zip<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TResult> parent, IObserver<TResult> observer, IDisposable cancel)
+ : base(10, observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ private ZipObserver<T1> _observer1;
+ private ZipObserver<T2> _observer2;
+ private ZipObserver<T3> _observer3;
+ private ZipObserver<T4> _observer4;
+ private ZipObserver<T5> _observer5;
+ private ZipObserver<T6> _observer6;
+ private ZipObserver<T7> _observer7;
+ private ZipObserver<T8> _observer8;
+ private ZipObserver<T9> _observer9;
+ private ZipObserver<T10> _observer10;
+
+ public IDisposable Run()
+ {
+ var subscriptions = new SingleAssignmentDisposable[10];
+ for (int i = 0; i < 10; i++)
+ subscriptions[i] = new SingleAssignmentDisposable();
+
+ _observer1 = new ZipObserver<T1>(_gate, this, 0, subscriptions[0]);
+ _observer2 = new ZipObserver<T2>(_gate, this, 1, subscriptions[1]);
+ _observer3 = new ZipObserver<T3>(_gate, this, 2, subscriptions[2]);
+ _observer4 = new ZipObserver<T4>(_gate, this, 3, subscriptions[3]);
+ _observer5 = new ZipObserver<T5>(_gate, this, 4, subscriptions[4]);
+ _observer6 = new ZipObserver<T6>(_gate, this, 5, subscriptions[5]);
+ _observer7 = new ZipObserver<T7>(_gate, this, 6, subscriptions[6]);
+ _observer8 = new ZipObserver<T8>(_gate, this, 7, subscriptions[7]);
+ _observer9 = new ZipObserver<T9>(_gate, this, 8, subscriptions[8]);
+ _observer10 = new ZipObserver<T10>(_gate, this, 9, subscriptions[9]);
+
+ base.Queues[0] = _observer1.Values;
+ base.Queues[1] = _observer2.Values;
+ base.Queues[2] = _observer3.Values;
+ base.Queues[3] = _observer4.Values;
+ base.Queues[4] = _observer5.Values;
+ base.Queues[5] = _observer6.Values;
+ base.Queues[6] = _observer7.Values;
+ base.Queues[7] = _observer8.Values;
+ base.Queues[8] = _observer9.Values;
+ base.Queues[9] = _observer10.Values;
+
+ 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);
+
+ return new CompositeDisposable(subscriptions)
+ {
+ Disposable.Create(() =>
+ {
+ _observer1.Values.Clear();
+ _observer2.Values.Clear();
+ _observer3.Values.Clear();
+ _observer4.Values.Clear();
+ _observer5.Values.Clear();
+ _observer6.Values.Clear();
+ _observer7.Values.Clear();
+ _observer8.Values.Clear();
+ _observer9.Values.Clear();
+ _observer10.Values.Clear();
+ })
+ };
+ }
+
+ 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());
+ }
+ }
+ }
+
+ class Zip<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TResult> : Producer<TResult>
+ {
+ private readonly IObservable<T1> _source1;
+ private readonly IObservable<T2> _source2;
+ private readonly IObservable<T3> _source3;
+ private readonly IObservable<T4> _source4;
+ private readonly IObservable<T5> _source5;
+ private readonly IObservable<T6> _source6;
+ private readonly IObservable<T7> _source7;
+ private readonly IObservable<T8> _source8;
+ private readonly IObservable<T9> _source9;
+ private readonly IObservable<T10> _source10;
+ private readonly IObservable<T11> _source11;
+ private readonly Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TResult> _resultSelector;
+
+ public Zip(IObservable<T1> source1, IObservable<T2> source2, IObservable<T3> source3, IObservable<T4> source4, IObservable<T5> source5, IObservable<T6> source6, IObservable<T7> source7, IObservable<T8> source8, IObservable<T9> source9, IObservable<T10> source10, IObservable<T11> source11, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TResult> resultSelector)
+ {
+ _source1 = source1;
+ _source2 = source2;
+ _source3 = source3;
+ _source4 = source4;
+ _source5 = source5;
+ _source6 = source6;
+ _source7 = source7;
+ _source8 = source8;
+ _source9 = source9;
+ _source10 = source10;
+ _source11 = source11;
+ _resultSelector = resultSelector;
+ }
+
+ protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+
+ class _ : ZipSink<TResult>
+ {
+ private readonly Zip<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TResult> _parent;
+
+ public _(Zip<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TResult> parent, IObserver<TResult> observer, IDisposable cancel)
+ : base(11, observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ private ZipObserver<T1> _observer1;
+ private ZipObserver<T2> _observer2;
+ private ZipObserver<T3> _observer3;
+ private ZipObserver<T4> _observer4;
+ private ZipObserver<T5> _observer5;
+ private ZipObserver<T6> _observer6;
+ private ZipObserver<T7> _observer7;
+ private ZipObserver<T8> _observer8;
+ private ZipObserver<T9> _observer9;
+ private ZipObserver<T10> _observer10;
+ private ZipObserver<T11> _observer11;
+
+ public IDisposable Run()
+ {
+ var subscriptions = new SingleAssignmentDisposable[11];
+ for (int i = 0; i < 11; i++)
+ subscriptions[i] = new SingleAssignmentDisposable();
+
+ _observer1 = new ZipObserver<T1>(_gate, this, 0, subscriptions[0]);
+ _observer2 = new ZipObserver<T2>(_gate, this, 1, subscriptions[1]);
+ _observer3 = new ZipObserver<T3>(_gate, this, 2, subscriptions[2]);
+ _observer4 = new ZipObserver<T4>(_gate, this, 3, subscriptions[3]);
+ _observer5 = new ZipObserver<T5>(_gate, this, 4, subscriptions[4]);
+ _observer6 = new ZipObserver<T6>(_gate, this, 5, subscriptions[5]);
+ _observer7 = new ZipObserver<T7>(_gate, this, 6, subscriptions[6]);
+ _observer8 = new ZipObserver<T8>(_gate, this, 7, subscriptions[7]);
+ _observer9 = new ZipObserver<T9>(_gate, this, 8, subscriptions[8]);
+ _observer10 = new ZipObserver<T10>(_gate, this, 9, subscriptions[9]);
+ _observer11 = new ZipObserver<T11>(_gate, this, 10, subscriptions[10]);
+
+ base.Queues[0] = _observer1.Values;
+ base.Queues[1] = _observer2.Values;
+ base.Queues[2] = _observer3.Values;
+ base.Queues[3] = _observer4.Values;
+ base.Queues[4] = _observer5.Values;
+ base.Queues[5] = _observer6.Values;
+ base.Queues[6] = _observer7.Values;
+ base.Queues[7] = _observer8.Values;
+ base.Queues[8] = _observer9.Values;
+ base.Queues[9] = _observer10.Values;
+ base.Queues[10] = _observer11.Values;
+
+ 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);
+
+ return new CompositeDisposable(subscriptions)
+ {
+ Disposable.Create(() =>
+ {
+ _observer1.Values.Clear();
+ _observer2.Values.Clear();
+ _observer3.Values.Clear();
+ _observer4.Values.Clear();
+ _observer5.Values.Clear();
+ _observer6.Values.Clear();
+ _observer7.Values.Clear();
+ _observer8.Values.Clear();
+ _observer9.Values.Clear();
+ _observer10.Values.Clear();
+ _observer11.Values.Clear();
+ })
+ };
+ }
+
+ 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());
+ }
+ }
+ }
+
+ class Zip<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TResult> : Producer<TResult>
+ {
+ private readonly IObservable<T1> _source1;
+ private readonly IObservable<T2> _source2;
+ private readonly IObservable<T3> _source3;
+ private readonly IObservable<T4> _source4;
+ private readonly IObservable<T5> _source5;
+ private readonly IObservable<T6> _source6;
+ private readonly IObservable<T7> _source7;
+ private readonly IObservable<T8> _source8;
+ private readonly IObservable<T9> _source9;
+ private readonly IObservable<T10> _source10;
+ private readonly IObservable<T11> _source11;
+ private readonly IObservable<T12> _source12;
+ private readonly Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TResult> _resultSelector;
+
+ public Zip(IObservable<T1> source1, IObservable<T2> source2, IObservable<T3> source3, IObservable<T4> source4, IObservable<T5> source5, IObservable<T6> source6, IObservable<T7> source7, IObservable<T8> source8, IObservable<T9> source9, IObservable<T10> source10, IObservable<T11> source11, IObservable<T12> source12, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TResult> resultSelector)
+ {
+ _source1 = source1;
+ _source2 = source2;
+ _source3 = source3;
+ _source4 = source4;
+ _source5 = source5;
+ _source6 = source6;
+ _source7 = source7;
+ _source8 = source8;
+ _source9 = source9;
+ _source10 = source10;
+ _source11 = source11;
+ _source12 = source12;
+ _resultSelector = resultSelector;
+ }
+
+ protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+
+ class _ : ZipSink<TResult>
+ {
+ private readonly Zip<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TResult> _parent;
+
+ public _(Zip<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TResult> parent, IObserver<TResult> observer, IDisposable cancel)
+ : base(12, observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ private ZipObserver<T1> _observer1;
+ private ZipObserver<T2> _observer2;
+ private ZipObserver<T3> _observer3;
+ private ZipObserver<T4> _observer4;
+ private ZipObserver<T5> _observer5;
+ private ZipObserver<T6> _observer6;
+ private ZipObserver<T7> _observer7;
+ private ZipObserver<T8> _observer8;
+ private ZipObserver<T9> _observer9;
+ private ZipObserver<T10> _observer10;
+ private ZipObserver<T11> _observer11;
+ private ZipObserver<T12> _observer12;
+
+ public IDisposable Run()
+ {
+ var subscriptions = new SingleAssignmentDisposable[12];
+ for (int i = 0; i < 12; i++)
+ subscriptions[i] = new SingleAssignmentDisposable();
+
+ _observer1 = new ZipObserver<T1>(_gate, this, 0, subscriptions[0]);
+ _observer2 = new ZipObserver<T2>(_gate, this, 1, subscriptions[1]);
+ _observer3 = new ZipObserver<T3>(_gate, this, 2, subscriptions[2]);
+ _observer4 = new ZipObserver<T4>(_gate, this, 3, subscriptions[3]);
+ _observer5 = new ZipObserver<T5>(_gate, this, 4, subscriptions[4]);
+ _observer6 = new ZipObserver<T6>(_gate, this, 5, subscriptions[5]);
+ _observer7 = new ZipObserver<T7>(_gate, this, 6, subscriptions[6]);
+ _observer8 = new ZipObserver<T8>(_gate, this, 7, subscriptions[7]);
+ _observer9 = new ZipObserver<T9>(_gate, this, 8, subscriptions[8]);
+ _observer10 = new ZipObserver<T10>(_gate, this, 9, subscriptions[9]);
+ _observer11 = new ZipObserver<T11>(_gate, this, 10, subscriptions[10]);
+ _observer12 = new ZipObserver<T12>(_gate, this, 11, subscriptions[11]);
+
+ base.Queues[0] = _observer1.Values;
+ base.Queues[1] = _observer2.Values;
+ base.Queues[2] = _observer3.Values;
+ base.Queues[3] = _observer4.Values;
+ base.Queues[4] = _observer5.Values;
+ base.Queues[5] = _observer6.Values;
+ base.Queues[6] = _observer7.Values;
+ base.Queues[7] = _observer8.Values;
+ base.Queues[8] = _observer9.Values;
+ base.Queues[9] = _observer10.Values;
+ base.Queues[10] = _observer11.Values;
+ base.Queues[11] = _observer12.Values;
+
+ 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);
+
+ return new CompositeDisposable(subscriptions)
+ {
+ Disposable.Create(() =>
+ {
+ _observer1.Values.Clear();
+ _observer2.Values.Clear();
+ _observer3.Values.Clear();
+ _observer4.Values.Clear();
+ _observer5.Values.Clear();
+ _observer6.Values.Clear();
+ _observer7.Values.Clear();
+ _observer8.Values.Clear();
+ _observer9.Values.Clear();
+ _observer10.Values.Clear();
+ _observer11.Values.Clear();
+ _observer12.Values.Clear();
+ })
+ };
+ }
+
+ 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());
+ }
+ }
+ }
+
+ class Zip<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TResult> : Producer<TResult>
+ {
+ private readonly IObservable<T1> _source1;
+ private readonly IObservable<T2> _source2;
+ private readonly IObservable<T3> _source3;
+ private readonly IObservable<T4> _source4;
+ private readonly IObservable<T5> _source5;
+ private readonly IObservable<T6> _source6;
+ private readonly IObservable<T7> _source7;
+ private readonly IObservable<T8> _source8;
+ private readonly IObservable<T9> _source9;
+ private readonly IObservable<T10> _source10;
+ private readonly IObservable<T11> _source11;
+ private readonly IObservable<T12> _source12;
+ private readonly IObservable<T13> _source13;
+ private readonly Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TResult> _resultSelector;
+
+ public Zip(IObservable<T1> source1, IObservable<T2> source2, IObservable<T3> source3, IObservable<T4> source4, IObservable<T5> source5, IObservable<T6> source6, IObservable<T7> source7, IObservable<T8> source8, IObservable<T9> source9, IObservable<T10> source10, IObservable<T11> source11, IObservable<T12> source12, IObservable<T13> source13, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TResult> resultSelector)
+ {
+ _source1 = source1;
+ _source2 = source2;
+ _source3 = source3;
+ _source4 = source4;
+ _source5 = source5;
+ _source6 = source6;
+ _source7 = source7;
+ _source8 = source8;
+ _source9 = source9;
+ _source10 = source10;
+ _source11 = source11;
+ _source12 = source12;
+ _source13 = source13;
+ _resultSelector = resultSelector;
+ }
+
+ protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+
+ class _ : ZipSink<TResult>
+ {
+ private readonly Zip<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TResult> _parent;
+
+ public _(Zip<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TResult> parent, IObserver<TResult> observer, IDisposable cancel)
+ : base(13, observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ private ZipObserver<T1> _observer1;
+ private ZipObserver<T2> _observer2;
+ private ZipObserver<T3> _observer3;
+ private ZipObserver<T4> _observer4;
+ private ZipObserver<T5> _observer5;
+ private ZipObserver<T6> _observer6;
+ private ZipObserver<T7> _observer7;
+ private ZipObserver<T8> _observer8;
+ private ZipObserver<T9> _observer9;
+ private ZipObserver<T10> _observer10;
+ private ZipObserver<T11> _observer11;
+ private ZipObserver<T12> _observer12;
+ private ZipObserver<T13> _observer13;
+
+ public IDisposable Run()
+ {
+ var subscriptions = new SingleAssignmentDisposable[13];
+ for (int i = 0; i < 13; i++)
+ subscriptions[i] = new SingleAssignmentDisposable();
+
+ _observer1 = new ZipObserver<T1>(_gate, this, 0, subscriptions[0]);
+ _observer2 = new ZipObserver<T2>(_gate, this, 1, subscriptions[1]);
+ _observer3 = new ZipObserver<T3>(_gate, this, 2, subscriptions[2]);
+ _observer4 = new ZipObserver<T4>(_gate, this, 3, subscriptions[3]);
+ _observer5 = new ZipObserver<T5>(_gate, this, 4, subscriptions[4]);
+ _observer6 = new ZipObserver<T6>(_gate, this, 5, subscriptions[5]);
+ _observer7 = new ZipObserver<T7>(_gate, this, 6, subscriptions[6]);
+ _observer8 = new ZipObserver<T8>(_gate, this, 7, subscriptions[7]);
+ _observer9 = new ZipObserver<T9>(_gate, this, 8, subscriptions[8]);
+ _observer10 = new ZipObserver<T10>(_gate, this, 9, subscriptions[9]);
+ _observer11 = new ZipObserver<T11>(_gate, this, 10, subscriptions[10]);
+ _observer12 = new ZipObserver<T12>(_gate, this, 11, subscriptions[11]);
+ _observer13 = new ZipObserver<T13>(_gate, this, 12, subscriptions[12]);
+
+ base.Queues[0] = _observer1.Values;
+ base.Queues[1] = _observer2.Values;
+ base.Queues[2] = _observer3.Values;
+ base.Queues[3] = _observer4.Values;
+ base.Queues[4] = _observer5.Values;
+ base.Queues[5] = _observer6.Values;
+ base.Queues[6] = _observer7.Values;
+ base.Queues[7] = _observer8.Values;
+ base.Queues[8] = _observer9.Values;
+ base.Queues[9] = _observer10.Values;
+ base.Queues[10] = _observer11.Values;
+ base.Queues[11] = _observer12.Values;
+ base.Queues[12] = _observer13.Values;
+
+ 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);
+
+ return new CompositeDisposable(subscriptions)
+ {
+ Disposable.Create(() =>
+ {
+ _observer1.Values.Clear();
+ _observer2.Values.Clear();
+ _observer3.Values.Clear();
+ _observer4.Values.Clear();
+ _observer5.Values.Clear();
+ _observer6.Values.Clear();
+ _observer7.Values.Clear();
+ _observer8.Values.Clear();
+ _observer9.Values.Clear();
+ _observer10.Values.Clear();
+ _observer11.Values.Clear();
+ _observer12.Values.Clear();
+ _observer13.Values.Clear();
+ })
+ };
+ }
+
+ 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());
+ }
+ }
+ }
+
+ class Zip<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TResult> : Producer<TResult>
+ {
+ private readonly IObservable<T1> _source1;
+ private readonly IObservable<T2> _source2;
+ private readonly IObservable<T3> _source3;
+ private readonly IObservable<T4> _source4;
+ private readonly IObservable<T5> _source5;
+ private readonly IObservable<T6> _source6;
+ private readonly IObservable<T7> _source7;
+ private readonly IObservable<T8> _source8;
+ private readonly IObservable<T9> _source9;
+ private readonly IObservable<T10> _source10;
+ private readonly IObservable<T11> _source11;
+ private readonly IObservable<T12> _source12;
+ private readonly IObservable<T13> _source13;
+ private readonly IObservable<T14> _source14;
+ private readonly Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TResult> _resultSelector;
+
+ public Zip(IObservable<T1> source1, IObservable<T2> source2, IObservable<T3> source3, IObservable<T4> source4, IObservable<T5> source5, IObservable<T6> source6, IObservable<T7> source7, IObservable<T8> source8, IObservable<T9> source9, IObservable<T10> source10, IObservable<T11> source11, IObservable<T12> source12, IObservable<T13> source13, IObservable<T14> source14, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TResult> resultSelector)
+ {
+ _source1 = source1;
+ _source2 = source2;
+ _source3 = source3;
+ _source4 = source4;
+ _source5 = source5;
+ _source6 = source6;
+ _source7 = source7;
+ _source8 = source8;
+ _source9 = source9;
+ _source10 = source10;
+ _source11 = source11;
+ _source12 = source12;
+ _source13 = source13;
+ _source14 = source14;
+ _resultSelector = resultSelector;
+ }
+
+ protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+
+ class _ : ZipSink<TResult>
+ {
+ private readonly Zip<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TResult> _parent;
+
+ public _(Zip<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TResult> parent, IObserver<TResult> observer, IDisposable cancel)
+ : base(14, observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ private ZipObserver<T1> _observer1;
+ private ZipObserver<T2> _observer2;
+ private ZipObserver<T3> _observer3;
+ private ZipObserver<T4> _observer4;
+ private ZipObserver<T5> _observer5;
+ private ZipObserver<T6> _observer6;
+ private ZipObserver<T7> _observer7;
+ private ZipObserver<T8> _observer8;
+ private ZipObserver<T9> _observer9;
+ private ZipObserver<T10> _observer10;
+ private ZipObserver<T11> _observer11;
+ private ZipObserver<T12> _observer12;
+ private ZipObserver<T13> _observer13;
+ private ZipObserver<T14> _observer14;
+
+ public IDisposable Run()
+ {
+ var subscriptions = new SingleAssignmentDisposable[14];
+ for (int i = 0; i < 14; i++)
+ subscriptions[i] = new SingleAssignmentDisposable();
+
+ _observer1 = new ZipObserver<T1>(_gate, this, 0, subscriptions[0]);
+ _observer2 = new ZipObserver<T2>(_gate, this, 1, subscriptions[1]);
+ _observer3 = new ZipObserver<T3>(_gate, this, 2, subscriptions[2]);
+ _observer4 = new ZipObserver<T4>(_gate, this, 3, subscriptions[3]);
+ _observer5 = new ZipObserver<T5>(_gate, this, 4, subscriptions[4]);
+ _observer6 = new ZipObserver<T6>(_gate, this, 5, subscriptions[5]);
+ _observer7 = new ZipObserver<T7>(_gate, this, 6, subscriptions[6]);
+ _observer8 = new ZipObserver<T8>(_gate, this, 7, subscriptions[7]);
+ _observer9 = new ZipObserver<T9>(_gate, this, 8, subscriptions[8]);
+ _observer10 = new ZipObserver<T10>(_gate, this, 9, subscriptions[9]);
+ _observer11 = new ZipObserver<T11>(_gate, this, 10, subscriptions[10]);
+ _observer12 = new ZipObserver<T12>(_gate, this, 11, subscriptions[11]);
+ _observer13 = new ZipObserver<T13>(_gate, this, 12, subscriptions[12]);
+ _observer14 = new ZipObserver<T14>(_gate, this, 13, subscriptions[13]);
+
+ base.Queues[0] = _observer1.Values;
+ base.Queues[1] = _observer2.Values;
+ base.Queues[2] = _observer3.Values;
+ base.Queues[3] = _observer4.Values;
+ base.Queues[4] = _observer5.Values;
+ base.Queues[5] = _observer6.Values;
+ base.Queues[6] = _observer7.Values;
+ base.Queues[7] = _observer8.Values;
+ base.Queues[8] = _observer9.Values;
+ base.Queues[9] = _observer10.Values;
+ base.Queues[10] = _observer11.Values;
+ base.Queues[11] = _observer12.Values;
+ base.Queues[12] = _observer13.Values;
+ base.Queues[13] = _observer14.Values;
+
+ 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);
+
+ return new CompositeDisposable(subscriptions)
+ {
+ Disposable.Create(() =>
+ {
+ _observer1.Values.Clear();
+ _observer2.Values.Clear();
+ _observer3.Values.Clear();
+ _observer4.Values.Clear();
+ _observer5.Values.Clear();
+ _observer6.Values.Clear();
+ _observer7.Values.Clear();
+ _observer8.Values.Clear();
+ _observer9.Values.Clear();
+ _observer10.Values.Clear();
+ _observer11.Values.Clear();
+ _observer12.Values.Clear();
+ _observer13.Values.Clear();
+ _observer14.Values.Clear();
+ })
+ };
+ }
+
+ 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());
+ }
+ }
+ }
+
+ class Zip<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TResult> : Producer<TResult>
+ {
+ private readonly IObservable<T1> _source1;
+ private readonly IObservable<T2> _source2;
+ private readonly IObservable<T3> _source3;
+ private readonly IObservable<T4> _source4;
+ private readonly IObservable<T5> _source5;
+ private readonly IObservable<T6> _source6;
+ private readonly IObservable<T7> _source7;
+ private readonly IObservable<T8> _source8;
+ private readonly IObservable<T9> _source9;
+ private readonly IObservable<T10> _source10;
+ private readonly IObservable<T11> _source11;
+ private readonly IObservable<T12> _source12;
+ private readonly IObservable<T13> _source13;
+ private readonly IObservable<T14> _source14;
+ private readonly IObservable<T15> _source15;
+ private readonly Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TResult> _resultSelector;
+
+ public Zip(IObservable<T1> source1, IObservable<T2> source2, IObservable<T3> source3, IObservable<T4> source4, IObservable<T5> source5, IObservable<T6> source6, IObservable<T7> source7, IObservable<T8> source8, IObservable<T9> source9, IObservable<T10> source10, IObservable<T11> source11, IObservable<T12> source12, IObservable<T13> source13, IObservable<T14> source14, IObservable<T15> source15, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TResult> resultSelector)
+ {
+ _source1 = source1;
+ _source2 = source2;
+ _source3 = source3;
+ _source4 = source4;
+ _source5 = source5;
+ _source6 = source6;
+ _source7 = source7;
+ _source8 = source8;
+ _source9 = source9;
+ _source10 = source10;
+ _source11 = source11;
+ _source12 = source12;
+ _source13 = source13;
+ _source14 = source14;
+ _source15 = source15;
+ _resultSelector = resultSelector;
+ }
+
+ protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+
+ class _ : ZipSink<TResult>
+ {
+ private readonly Zip<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TResult> _parent;
+
+ public _(Zip<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TResult> parent, IObserver<TResult> observer, IDisposable cancel)
+ : base(15, observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ private ZipObserver<T1> _observer1;
+ private ZipObserver<T2> _observer2;
+ private ZipObserver<T3> _observer3;
+ private ZipObserver<T4> _observer4;
+ private ZipObserver<T5> _observer5;
+ private ZipObserver<T6> _observer6;
+ private ZipObserver<T7> _observer7;
+ private ZipObserver<T8> _observer8;
+ private ZipObserver<T9> _observer9;
+ private ZipObserver<T10> _observer10;
+ private ZipObserver<T11> _observer11;
+ private ZipObserver<T12> _observer12;
+ private ZipObserver<T13> _observer13;
+ private ZipObserver<T14> _observer14;
+ private ZipObserver<T15> _observer15;
+
+ public IDisposable Run()
+ {
+ var subscriptions = new SingleAssignmentDisposable[15];
+ for (int i = 0; i < 15; i++)
+ subscriptions[i] = new SingleAssignmentDisposable();
+
+ _observer1 = new ZipObserver<T1>(_gate, this, 0, subscriptions[0]);
+ _observer2 = new ZipObserver<T2>(_gate, this, 1, subscriptions[1]);
+ _observer3 = new ZipObserver<T3>(_gate, this, 2, subscriptions[2]);
+ _observer4 = new ZipObserver<T4>(_gate, this, 3, subscriptions[3]);
+ _observer5 = new ZipObserver<T5>(_gate, this, 4, subscriptions[4]);
+ _observer6 = new ZipObserver<T6>(_gate, this, 5, subscriptions[5]);
+ _observer7 = new ZipObserver<T7>(_gate, this, 6, subscriptions[6]);
+ _observer8 = new ZipObserver<T8>(_gate, this, 7, subscriptions[7]);
+ _observer9 = new ZipObserver<T9>(_gate, this, 8, subscriptions[8]);
+ _observer10 = new ZipObserver<T10>(_gate, this, 9, subscriptions[9]);
+ _observer11 = new ZipObserver<T11>(_gate, this, 10, subscriptions[10]);
+ _observer12 = new ZipObserver<T12>(_gate, this, 11, subscriptions[11]);
+ _observer13 = new ZipObserver<T13>(_gate, this, 12, subscriptions[12]);
+ _observer14 = new ZipObserver<T14>(_gate, this, 13, subscriptions[13]);
+ _observer15 = new ZipObserver<T15>(_gate, this, 14, subscriptions[14]);
+
+ base.Queues[0] = _observer1.Values;
+ base.Queues[1] = _observer2.Values;
+ base.Queues[2] = _observer3.Values;
+ base.Queues[3] = _observer4.Values;
+ base.Queues[4] = _observer5.Values;
+ base.Queues[5] = _observer6.Values;
+ base.Queues[6] = _observer7.Values;
+ base.Queues[7] = _observer8.Values;
+ base.Queues[8] = _observer9.Values;
+ base.Queues[9] = _observer10.Values;
+ base.Queues[10] = _observer11.Values;
+ base.Queues[11] = _observer12.Values;
+ base.Queues[12] = _observer13.Values;
+ base.Queues[13] = _observer14.Values;
+ base.Queues[14] = _observer15.Values;
+
+ 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);
+
+ return new CompositeDisposable(subscriptions)
+ {
+ Disposable.Create(() =>
+ {
+ _observer1.Values.Clear();
+ _observer2.Values.Clear();
+ _observer3.Values.Clear();
+ _observer4.Values.Clear();
+ _observer5.Values.Clear();
+ _observer6.Values.Clear();
+ _observer7.Values.Clear();
+ _observer8.Values.Clear();
+ _observer9.Values.Clear();
+ _observer10.Values.Clear();
+ _observer11.Values.Clear();
+ _observer12.Values.Clear();
+ _observer13.Values.Clear();
+ _observer14.Values.Clear();
+ _observer15.Values.Clear();
+ })
+ };
+ }
+
+ 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());
+ }
+ }
+ }
+
+ class Zip<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, TResult> : Producer<TResult>
+ {
+ private readonly IObservable<T1> _source1;
+ private readonly IObservable<T2> _source2;
+ private readonly IObservable<T3> _source3;
+ private readonly IObservable<T4> _source4;
+ private readonly IObservable<T5> _source5;
+ private readonly IObservable<T6> _source6;
+ private readonly IObservable<T7> _source7;
+ private readonly IObservable<T8> _source8;
+ private readonly IObservable<T9> _source9;
+ private readonly IObservable<T10> _source10;
+ private readonly IObservable<T11> _source11;
+ private readonly IObservable<T12> _source12;
+ private readonly IObservable<T13> _source13;
+ private readonly IObservable<T14> _source14;
+ private readonly IObservable<T15> _source15;
+ private readonly IObservable<T16> _source16;
+ private readonly Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, TResult> _resultSelector;
+
+ public Zip(IObservable<T1> source1, IObservable<T2> source2, IObservable<T3> source3, IObservable<T4> source4, IObservable<T5> source5, IObservable<T6> source6, IObservable<T7> source7, IObservable<T8> source8, IObservable<T9> source9, IObservable<T10> source10, IObservable<T11> source11, IObservable<T12> source12, IObservable<T13> source13, IObservable<T14> source14, IObservable<T15> source15, IObservable<T16> source16, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, TResult> resultSelector)
+ {
+ _source1 = source1;
+ _source2 = source2;
+ _source3 = source3;
+ _source4 = source4;
+ _source5 = source5;
+ _source6 = source6;
+ _source7 = source7;
+ _source8 = source8;
+ _source9 = source9;
+ _source10 = source10;
+ _source11 = source11;
+ _source12 = source12;
+ _source13 = source13;
+ _source14 = source14;
+ _source15 = source15;
+ _source16 = source16;
+ _resultSelector = resultSelector;
+ }
+
+ protected override IDisposable Run(IObserver<TResult> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+
+ class _ : ZipSink<TResult>
+ {
+ private readonly Zip<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, TResult> _parent;
+
+ public _(Zip<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, TResult> parent, IObserver<TResult> observer, IDisposable cancel)
+ : base(16, observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ private ZipObserver<T1> _observer1;
+ private ZipObserver<T2> _observer2;
+ private ZipObserver<T3> _observer3;
+ private ZipObserver<T4> _observer4;
+ private ZipObserver<T5> _observer5;
+ private ZipObserver<T6> _observer6;
+ private ZipObserver<T7> _observer7;
+ private ZipObserver<T8> _observer8;
+ private ZipObserver<T9> _observer9;
+ private ZipObserver<T10> _observer10;
+ private ZipObserver<T11> _observer11;
+ private ZipObserver<T12> _observer12;
+ private ZipObserver<T13> _observer13;
+ private ZipObserver<T14> _observer14;
+ private ZipObserver<T15> _observer15;
+ private ZipObserver<T16> _observer16;
+
+ public IDisposable Run()
+ {
+ var subscriptions = new SingleAssignmentDisposable[16];
+ for (int i = 0; i < 16; i++)
+ subscriptions[i] = new SingleAssignmentDisposable();
+
+ _observer1 = new ZipObserver<T1>(_gate, this, 0, subscriptions[0]);
+ _observer2 = new ZipObserver<T2>(_gate, this, 1, subscriptions[1]);
+ _observer3 = new ZipObserver<T3>(_gate, this, 2, subscriptions[2]);
+ _observer4 = new ZipObserver<T4>(_gate, this, 3, subscriptions[3]);
+ _observer5 = new ZipObserver<T5>(_gate, this, 4, subscriptions[4]);
+ _observer6 = new ZipObserver<T6>(_gate, this, 5, subscriptions[5]);
+ _observer7 = new ZipObserver<T7>(_gate, this, 6, subscriptions[6]);
+ _observer8 = new ZipObserver<T8>(_gate, this, 7, subscriptions[7]);
+ _observer9 = new ZipObserver<T9>(_gate, this, 8, subscriptions[8]);
+ _observer10 = new ZipObserver<T10>(_gate, this, 9, subscriptions[9]);
+ _observer11 = new ZipObserver<T11>(_gate, this, 10, subscriptions[10]);
+ _observer12 = new ZipObserver<T12>(_gate, this, 11, subscriptions[11]);
+ _observer13 = new ZipObserver<T13>(_gate, this, 12, subscriptions[12]);
+ _observer14 = new ZipObserver<T14>(_gate, this, 13, subscriptions[13]);
+ _observer15 = new ZipObserver<T15>(_gate, this, 14, subscriptions[14]);
+ _observer16 = new ZipObserver<T16>(_gate, this, 15, subscriptions[15]);
+
+ base.Queues[0] = _observer1.Values;
+ base.Queues[1] = _observer2.Values;
+ base.Queues[2] = _observer3.Values;
+ base.Queues[3] = _observer4.Values;
+ base.Queues[4] = _observer5.Values;
+ base.Queues[5] = _observer6.Values;
+ base.Queues[6] = _observer7.Values;
+ base.Queues[7] = _observer8.Values;
+ base.Queues[8] = _observer9.Values;
+ base.Queues[9] = _observer10.Values;
+ base.Queues[10] = _observer11.Values;
+ base.Queues[11] = _observer12.Values;
+ base.Queues[12] = _observer13.Values;
+ base.Queues[13] = _observer14.Values;
+ base.Queues[14] = _observer15.Values;
+ base.Queues[15] = _observer16.Values;
+
+ 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);
+
+ return new CompositeDisposable(subscriptions)
+ {
+ Disposable.Create(() =>
+ {
+ _observer1.Values.Clear();
+ _observer2.Values.Clear();
+ _observer3.Values.Clear();
+ _observer4.Values.Clear();
+ _observer5.Values.Clear();
+ _observer6.Values.Clear();
+ _observer7.Values.Clear();
+ _observer8.Values.Clear();
+ _observer9.Values.Clear();
+ _observer10.Values.Clear();
+ _observer11.Values.Clear();
+ _observer12.Values.Clear();
+ _observer13.Values.Clear();
+ _observer14.Values.Clear();
+ _observer15.Values.Clear();
+ _observer16.Values.Clear();
+ })
+ };
+ }
+
+ 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());
+ }
+ }
+ }
+
+#endif
+
+ #endregion
+
+ #region Helpers for n-ary overloads
+
+ interface IZip
+ {
+ void Next(int index);
+ void Fail(Exception error);
+ void Done(int index);
+ }
+
+ abstract class ZipSink<TResult> : Sink<TResult>, IZip
+ {
+ protected readonly object _gate;
+
+ private readonly ICollection[] _queues;
+ private readonly bool[] _isDone;
+
+ public ZipSink(int arity, IObserver<TResult> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _gate = new object();
+
+ _isDone = new bool[arity];
+ _queues = new ICollection[arity];
+ }
+
+ public ICollection[] Queues
+ {
+ get { return _queues; }
+ }
+
+ public void Next(int index)
+ {
+ var hasValueAll = true;
+ foreach (var queue in _queues)
+ {
+ if (queue.Count == 0)
+ {
+ hasValueAll = false;
+ break;
+ }
+ }
+
+ if (hasValueAll)
+ {
+ var res = default(TResult);
+ try
+ {
+ res = GetResult();
+ }
+ catch (Exception ex)
+ {
+ base._observer.OnError(ex);
+ base.Dispose();
+ return;
+ }
+
+ base._observer.OnNext(res);
+ }
+ else
+ {
+ var allOthersDone = true;
+ for (int i = 0; i < _isDone.Length; i++)
+ {
+ if (i != index && !_isDone[i])
+ {
+ allOthersDone = false;
+ break;
+ }
+ }
+
+ if (allOthersDone)
+ {
+ base._observer.OnCompleted();
+ base.Dispose();
+ }
+ }
+ }
+
+ protected abstract TResult GetResult();
+
+ public void Fail(Exception error)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+
+ public void Done(int index)
+ {
+ _isDone[index] = true;
+
+ var allDone = true;
+ foreach (var isDone in _isDone)
+ {
+ if (!isDone)
+ {
+ allDone = false;
+ break;
+ }
+ }
+
+ if (allDone)
+ {
+ base._observer.OnCompleted();
+ base.Dispose();
+ return;
+ }
+ }
+ }
+
+ class ZipObserver<T> : IObserver<T>
+ {
+ private readonly object _gate;
+ private readonly IZip _parent;
+ private readonly int _index;
+ private readonly IDisposable _self;
+ private readonly Queue<T> _values;
+
+ public ZipObserver(object gate, IZip parent, int index, IDisposable self)
+ {
+ _gate = gate;
+ _parent = parent;
+ _index = index;
+ _self = self;
+ _values = new Queue<T>();
+ }
+
+ public Queue<T> Values
+ {
+ get { return _values; }
+ }
+
+ public void OnNext(T value)
+ {
+ lock (_gate)
+ {
+ _values.Enqueue(value);
+ _parent.Next(_index);
+ }
+ }
+
+ public void OnError(Exception error)
+ {
+ _self.Dispose();
+
+ lock (_gate)
+ {
+ _parent.Fail(error);
+ }
+ }
+
+ public void OnCompleted()
+ {
+ _self.Dispose();
+
+ lock (_gate)
+ {
+ _parent.Done(_index);
+ }
+ }
+ }
+
+ #endregion
+
+ #endregion
+
+ #region N-ary
+
+ class Zip<TSource> : Producer<IList<TSource>>
+ {
+ private readonly IEnumerable<IObservable<TSource>> _sources;
+
+ public Zip(IEnumerable<IObservable<TSource>> sources)
+ {
+ _sources = sources;
+ }
+
+ protected override IDisposable Run(IObserver<IList<TSource>> observer, IDisposable cancel, Action<IDisposable> setSink)
+ {
+ var sink = new _(this, observer, cancel);
+ setSink(sink);
+ return sink.Run();
+ }
+
+ class _ : Sink<IList<TSource>>
+ {
+ private readonly Zip<TSource> _parent;
+
+ public _(Zip<TSource> parent, IObserver<IList<TSource>> observer, IDisposable cancel)
+ : base(observer, cancel)
+ {
+ _parent = parent;
+ }
+
+ private object _gate;
+ private Queue<TSource>[] _queues;
+ private bool[] _isDone;
+ private IDisposable[] _subscriptions;
+
+ public IDisposable Run()
+ {
+ var srcs = _parent._sources.ToArray();
+
+ var N = srcs.Length;
+
+ _queues = new Queue<TSource>[N];
+ for (int i = 0; i < N; i++)
+ _queues[i] = new Queue<TSource>();
+
+ _isDone = new bool[N];
+
+ _subscriptions = new SingleAssignmentDisposable[N];
+
+ _gate = new object();
+
+ for (int i = 0; i < N; i++)
+ {
+ var j = i;
+
+ var d = new SingleAssignmentDisposable();
+ _subscriptions[j] = d;
+
+ var o = new O(this, j);
+ d.Disposable = srcs[j].SubscribeSafe(o);
+ }
+
+ return new CompositeDisposable(_subscriptions) { Disposable.Create(() => { foreach (var q in _queues) q.Clear(); }) };
+ }
+
+ private void OnNext(int index, TSource value)
+ {
+ lock (_gate)
+ {
+ _queues[index].Enqueue(value);
+
+ if (_queues.All(q => q.Count > 0))
+ {
+ var res = _queues.Select(q => q.Dequeue()).ToList();
+ base._observer.OnNext(res);
+ }
+ else if (_isDone.Where((x, i) => i != index).All(Stubs<bool>.I))
+ {
+ base._observer.OnCompleted();
+ base.Dispose();
+ return;
+ }
+ }
+ }
+
+ private void OnError(Exception error)
+ {
+ lock (_gate)
+ {
+ base._observer.OnError(error);
+ base.Dispose();
+ }
+ }
+
+ private void OnCompleted(int index)
+ {
+ lock (_gate)
+ {
+ _isDone[index] = true;
+
+ if (_isDone.All(Stubs<bool>.I))
+ {
+ base._observer.OnCompleted();
+ base.Dispose();
+ return;
+ }
+ else
+ {
+ _subscriptions[index].Dispose();
+ }
+ }
+ }
+
+ class O : IObserver<TSource>
+ {
+ private readonly _ _parent;
+ private readonly int _index;
+
+ public O(_ parent, int index)
+ {
+ _parent = parent;
+ _index = index;
+ }
+
+ public void OnNext(TSource value)
+ {
+ _parent.OnNext(_index, value);
+ }
+
+ public void OnError(Exception error)
+ {
+ _parent.OnError(error);
+ }
+
+ public void OnCompleted()
+ {
+ _parent.OnCompleted(_index);
+ }
+ }
+ }
+ }
+
+ #endregion
+}
+#endif \ No newline at end of file
diff --git a/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/_.cs b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/_.cs
new file mode 100644
index 0000000..d4b0dbc
--- /dev/null
+++ b/Rx/NET/Source/System.Reactive.Linq/Reactive/Linq/Observable/_.cs
@@ -0,0 +1,9 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_PERF
+using System;
+
+namespace System.Reactive.Linq.Observαble
+{
+}
+#endif