hu.akarnokd.rxjava2.internal.operators.nbp.NbpOnSubscribeSequenceEqual Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of rxjava2-backport Show documentation
Show all versions of rxjava2-backport Show documentation
rxjava2-backport developed by David Karnok
/**
* Copyright 2015 David Karnok and Netflix, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is
* distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See
* the License for the specific language governing permissions and limitations under the License.
*/
package hu.akarnokd.rxjava2.internal.operators.nbp;
import java.util.Queue;
import java.util.concurrent.atomic.*;
import hu.akarnokd.rxjava2.NbpObservable;
import hu.akarnokd.rxjava2.NbpObservable.*;
import hu.akarnokd.rxjava2.disposables.*;
import hu.akarnokd.rxjava2.functions.BiPredicate;
import hu.akarnokd.rxjava2.internal.disposables.ArrayCompositeResource;
import hu.akarnokd.rxjava2.internal.queue.SpscLinkedArrayQueue;
public final class NbpOnSubscribeSequenceEqual implements NbpOnSubscribe {
final NbpObservable extends T> first;
final NbpObservable extends T> second;
final BiPredicate super T, ? super T> comparer;
final int bufferSize;
public NbpOnSubscribeSequenceEqual(NbpObservable extends T> first, NbpObservable extends T> second,
BiPredicate super T, ? super T> comparer, int bufferSize) {
this.first = first;
this.second = second;
this.comparer = comparer;
this.bufferSize = bufferSize;
}
@Override
public void accept(NbpSubscriber super Boolean> s) {
EqualCoordinator ec = new EqualCoordinator(s, bufferSize, first, second, comparer);
ec.subscribe();
}
static final class EqualCoordinator extends AtomicInteger implements Disposable {
/** */
private static final long serialVersionUID = -6178010334400373240L;
final NbpSubscriber super Boolean> actual;
final BiPredicate super T, ? super T> comparer;
final ArrayCompositeResource resources;
final NbpObservable extends T> first;
final NbpObservable extends T> second;
final EqualSubscriber[] subscribers;
volatile boolean cancelled;
volatile int once;
@SuppressWarnings("rawtypes")
static final AtomicIntegerFieldUpdater ONCE =
AtomicIntegerFieldUpdater.newUpdater(EqualCoordinator.class, "once");
public EqualCoordinator(NbpSubscriber super Boolean> actual, int bufferSize,
NbpObservable extends T> first, NbpObservable extends T> second,
BiPredicate super T, ? super T> comparer) {
this.actual = actual;
this.first = first;
this.second = second;
this.comparer = comparer;
@SuppressWarnings("unchecked")
EqualSubscriber[] as = new EqualSubscriber[2];
this.subscribers = as;
as[0] = new EqualSubscriber(this, 0, bufferSize);
as[1] = new EqualSubscriber(this, 1, bufferSize);
this.resources = new ArrayCompositeResource(2, Disposables.consumeAndDispose());
}
boolean setSubscription(Disposable s, int index) {
return resources.setResource(index, s);
}
void subscribe() {
EqualSubscriber[] as = subscribers;
first.subscribe(as[0]);
second.subscribe(as[1]);
}
@Override
public void dispose() {
if (!cancelled) {
cancelled = true;
resources.dispose();
if (getAndIncrement() == 0) {
EqualSubscriber[] as = subscribers;
as[0].queue.clear();
as[1].queue.clear();
}
}
}
void cancel(Queue q1, Queue q2) {
cancelled = true;
q1.clear();
q2.clear();
}
void drain() {
if (getAndIncrement() != 0) {
return;
}
int missed = 1;
EqualSubscriber[] as = subscribers;
final EqualSubscriber s1 = as[0];
final Queue q1 = s1.queue;
final EqualSubscriber s2 = as[1];
final Queue q2 = s2.queue;
for (;;) {
for (;;) {
if (cancelled) {
q1.clear();
q2.clear();
return;
}
boolean d1 = s1.done;
T v1 = q1.peek();
boolean e1 = v1 == null;
if (d1) {
Throwable e = s1.error;
if (e != null) {
cancel(q1, q2);
actual.onError(e);
return;
}
}
boolean d2 = s2.done;
T v2 = q2.peek();
boolean e2 = v2 == null;
if (d2) {
Throwable e = s2.error;
if (e != null) {
cancel(q1, q2);
actual.onError(e);
return;
}
}
if (d1 && d2 && e1 && e2) {
actual.onNext(true);
actual.onComplete();
return;
}
if ((d1 && d2) && (e1 != e2)) {
cancel(q1, q2);
actual.onNext(false);
actual.onComplete();
return;
}
if (!e1 && !e2) {
q1.poll();
q2.poll();
boolean c;
try {
c = comparer.test(v1, v2);
} catch (Throwable ex) {
cancel(q1, q2);
actual.onError(ex);
return;
}
if (!c) {
cancel(q1, q2);
actual.onNext(false);
actual.onComplete();
return;
}
}
if (e1 || e2) {
break;
}
}
missed = addAndGet(-missed);
if (missed == 0) {
break;
}
}
}
}
static final class EqualSubscriber implements NbpSubscriber {
final EqualCoordinator parent;
final Queue queue;
final int index;
volatile boolean done;
Throwable error;
Disposable s;
public EqualSubscriber(EqualCoordinator parent, int index, int bufferSize) {
this.parent = parent;
this.index = index;
this.queue = new SpscLinkedArrayQueue(bufferSize);
}
@Override
public void onSubscribe(Disposable s) {
if (parent.setSubscription(s, index)) {
this.s = s;
}
}
@Override
public void onNext(T t) {
if (!queue.offer(t)) {
onError(new IllegalStateException("Queue full?!"));
return;
}
parent.drain();
}
@Override
public void onError(Throwable t) {
error = t;
done = true;
parent.drain();
}
@Override
public void onComplete() {
done = true;
parent.drain();
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy