io.vertx.reactivex.impl.ObservableReadStream Maven / Gradle / Ivy
package io.vertx.reactivex.impl;
import io.reactivex.Observable;
import io.reactivex.Observer;
import io.reactivex.disposables.Disposable;
import io.vertx.core.streams.ReadStream;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Function;
/**
* @author Julien Viet
*/
public class ObservableReadStream extends Observable {
private final ReadStream stream;
private final Function f;
private final AtomicReference> observer = new AtomicReference<>();
public ObservableReadStream(ReadStream stream, Function f) {
stream.pause();
this.stream = stream;
this.f = f;
}
class Subscription implements Disposable {
private static final int SUBSCRIBED = 0x01;
private static final int DISPOSED = 0x02;
private AtomicInteger status = new AtomicInteger();
private final Observer super U> observer;
public Subscription(Observer super U> observer) {
this.observer = observer;
}
private boolean cancel() {
while (true) {
int current = status.get();
if ((current & DISPOSED) != 0) {
return false;
}
int next = current | DISPOSED;
if (status.compareAndSet(current, next)) {
if ((next & SUBSCRIBED) != 0) {
unset();
}
return true;
}
}
}
private void set() {
stream.endHandler(v -> {
if (cancel()) {
observer.onComplete();
}
});
stream.exceptionHandler(err -> {
if (cancel()) {
observer.onError(err);
}
});
stream.handler(item -> {
observer.onNext(f.apply(item));
});
while (true) {
int current = status.get();
int next = current | SUBSCRIBED;
if (status.compareAndSet(current, next)) {
if ((current & DISPOSED) != 0) {
unset();
}
break;
}
}
}
private void unset() {
stream.exceptionHandler(null);
stream.endHandler(null);
stream.handler(null);
ObservableReadStream.this.observer.set(null);
}
@Override
public void dispose() {
cancel();
}
@Override
public boolean isDisposed() {
return (status.get() & DISPOSED) != 0;
}
}
@Override
protected void subscribeActual(Observer super U> o) {
if (observer.compareAndSet(o, null)) {
o.onError(new RuntimeException("Already subscribed"));
return;
}
Subscription sub = new Subscription(o);
stream.pause();
sub.set();
o.onSubscribe(sub);
stream.resume();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy