public LeftJoinSubject(IPushObservable <TInLeft> leftS, IPushObservable <TInRight> rightS, LeftJoinParams <TInLeft, TInRight, TOut> leftJoinParams) : base(CancellationTokenSource.CreateLinkedTokenSource(leftS.CancellationToken, rightS.CancellationToken).Token) { var leftSide = new Side <TInLeft>(); var rightSide = new Side <TInRight>(); _leftSubscription = leftS.Subscribe( (leftValue) => { if (CancellationToken.IsCancellationRequested) { return; } lock (_sync) { leftSide.Enqueue(leftValue); TryUnstackQueues(leftSide, rightSide, leftJoinParams); } }, () => { lock (_sync) { leftSide.IsComplete = true; TryUnstackQueues(leftSide, rightSide, leftJoinParams); } } ); _rightSubscription = rightS.Subscribe( (rightValue) => { if (CancellationToken.IsCancellationRequested) { return; } lock (_sync) { rightSide.Enqueue(rightValue); TryUnstackQueues(leftSide, rightSide, leftJoinParams); } }, () => { lock (_sync) { rightSide.IsComplete = true; TryUnstackQueues(leftSide, rightSide, leftJoinParams); } } ); }
public LeftJoinSubject(IPushObservable <TInLeft> leftS, IPushObservable <TInRight> rightS, LeftJoinParams <TInLeft, TInRight, TOut> leftJoinParams) { var leftSide = new Side <TInLeft>(); var rightSide = new Side <TInRight>(); _leftSubscription = leftS.Subscribe( (leftValue) => { lock (_sync) { leftSide.Enqueue(leftValue); TryUnstackQueues(leftSide, rightSide, leftJoinParams); } }, () => { lock (_sync) { leftSide.IsComplete = true; TryUnstackQueues(leftSide, rightSide, leftJoinParams); } } ); _rightSubscription = rightS.Subscribe( (rightValue) => { lock (_sync) { rightSide.Enqueue(rightValue); TryUnstackQueues(leftSide, rightSide, leftJoinParams); } }, () => { lock (_sync) { rightSide.IsComplete = true; TryUnstackQueues(leftSide, rightSide, leftJoinParams); } } ); }
public LeftJoinSubject(IPushObservable <TInLeft> leftS, IPushObservable <TInRight> rightS, IComparer <TInLeft, TInRight> comparer, Func <TInLeft, TInRight, TOut> selector) { var leftSide = new Side <TInLeft>(); var rightSide = new Side <TInRight>(); object gate = new object(); Action TryUnstackQueues = () => { bool somethingChanged; do { somethingChanged = false; while (!rightSide.IsEmpty && !leftSide.IsEmpty && comparer.Compare(leftSide.CurrentValue, rightSide.CurrentValue) > 0) { rightSide.Dequeue(); somethingChanged = true; } int comparison; while (!leftSide.IsEmpty && !rightSide.IsEmpty && (comparison = comparer.Compare(leftSide.CurrentValue, rightSide.CurrentValue)) <= 0) { TOut ret; try { ret = selector(leftSide.Dequeue(), comparison == 0 ? rightSide.CurrentValue : default(TInRight)); this.PushValue(ret); } catch (Exception ex) { PushException(ex); } somethingChanged = true; } if (rightSide.IsEmpty && rightSide.IsComplete) { while (!leftSide.IsEmpty) { TOut ret; try { ret = selector(leftSide.Dequeue(), default(TInRight)); this.PushValue(ret); } catch (Exception ex) { PushException(ex); } somethingChanged = true; } } } while (somethingChanged); if (leftSide.IsComplete && (leftSide.IsEmpty || rightSide.IsComplete)) { this.Complete(); } }; _leftSubscription = leftS.Subscribe( (leftValue) => { lock (gate) { leftSide.Enqueue(leftValue); TryUnstackQueues(); } }, () => { lock (gate) { leftSide.IsComplete = true; TryUnstackQueues(); } } ); _rightSubscription = rightS.Subscribe( (rightValue) => { lock (gate) { rightSide.Enqueue(rightValue); TryUnstackQueues(); } }, () => { lock (gate) { rightSide.IsComplete = true; TryUnstackQueues(); } } ); }