private void TryUnstackQueues(Side <TInLeft> lSide, Side <TInRight> rSide, LeftJoinParams <TInLeft, TInRight, TOut> leftJoinParams) { bool somethingChanged; do { somethingChanged = false; while (!rSide.IsEmpty && !lSide.IsEmpty && leftJoinParams.comparer.Compare(lSide.CurrentValue, rSide.CurrentValue) > 0) { rSide.Dequeue(); somethingChanged = true; } int comparison; while (!lSide.IsEmpty && !rSide.IsEmpty && (comparison = leftJoinParams.comparer.Compare(lSide.CurrentValue, rSide.CurrentValue)) <= 0) { TOut ret; try { ret = leftJoinParams.selector(lSide.Dequeue(), comparison == 0 ? rSide.CurrentValue : default(TInRight)); this.PushValue(ret); } catch (Exception ex) { PushException(ex); } somethingChanged = true; } if (rSide.IsEmpty && rSide.IsComplete) { while (!lSide.IsEmpty) { TOut ret; try { ret = leftJoinParams.selector(lSide.Dequeue(), default(TInRight)); this.PushValue(ret); } catch (Exception ex) { PushException(ex); } somethingChanged = true; } } } while (somethingChanged); if (lSide.IsComplete && (lSide.IsEmpty || rSide.IsComplete)) { this.Complete(); } }
private void TryUnstackQueues(Side <TInLeft> lSide, Side <TInRight> rSide, LeftJoinParams <TInLeft, TInRight, TOut> leftJoinParams) { bool somethingChanged; do { if (CancellationToken.IsCancellationRequested) { break; } somethingChanged = false; while (!rSide.IsEmpty && !lSide.IsEmpty && leftJoinParams.comparer.Compare(lSide.CurrentValue, rSide.CurrentValue) > 0) { if (CancellationToken.IsCancellationRequested) { break; } rSide.Dequeue(); somethingChanged = true; } int comparison; while (!lSide.IsEmpty && !rSide.IsEmpty && (comparison = leftJoinParams.comparer.Compare(lSide.CurrentValue, rSide.CurrentValue)) <= 0) { if (CancellationToken.IsCancellationRequested) { break; } this.TryPushValue(() => leftJoinParams.selector(lSide.Dequeue(), comparison == 0 ? rSide.CurrentValue : default(TInRight))); somethingChanged = true; } if (rSide.IsEmpty && rSide.IsComplete) { while (!lSide.IsEmpty) { if (CancellationToken.IsCancellationRequested) { break; } this.TryPushValue(() => leftJoinParams.selector(lSide.Dequeue(), default(TInRight))); somethingChanged = true; } } } while (somethingChanged); if (lSide.IsComplete && (lSide.IsEmpty || rSide.IsComplete)) { this.Complete(); } }
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, 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); } } ); }