All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.davidmoten.rx.internal.operators.TransformerDelayFinalUnsubscribe Maven / Gradle / Ivy

package com.github.davidmoten.rx.internal.operators;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;

import rx.Observable;
import rx.Observable.Operator;
import rx.Observable.Transformer;
import rx.Scheduler;
import rx.Scheduler.Worker;
import rx.Subscriber;
import rx.functions.Action0;
import rx.observers.Subscribers;
import rx.subscriptions.Subscriptions;

public final class TransformerDelayFinalUnsubscribe implements Transformer {

	private final long delayMs;
	private final Scheduler scheduler;

	public TransformerDelayFinalUnsubscribe(long delayMs, Scheduler scheduler) {
		this.delayMs = delayMs;
		this.scheduler = scheduler;
	}

	@Override
	public Observable call(final Observable o) {
		final AtomicInteger count = new AtomicInteger();
		final AtomicReference> extra = new AtomicReference>();
		final AtomicReference worker = new AtomicReference();
		final Object lock = new Object();
		return o //
				.doOnSubscribe(new Action0() {
					@Override
					public void call() {
						if (count.incrementAndGet() == 1) {
							final Worker w;
							final Subscriber sub;
							synchronized (lock) {
								if (extra.get() == null) {
									sub = doNothing();
									extra.set(sub);
								} else {
									sub = null;
								}
								w = worker.get();
								worker.set(null);
							}
							if (w != null) {
								w.unsubscribe();
							}
							if (sub != null) {
								o.subscribe(sub);
							}
						} else {
							final Worker w;
							synchronized (lock) {
								w = worker.get();
								worker.set(null);
							}
							if (w != null) {
								w.unsubscribe();
							}
						}
					}
				}) //
				.lift(new OperatorAddToSubscription(new Action0() {

					@Override
					public void call() {
						if (count.decrementAndGet() == 0) {
							final Worker newW;
							final Worker w;
							synchronized (lock) {
								w = worker.get();
								newW = scheduler.createWorker();
								worker.set(newW);
							}
							if (w != null) {
								w.unsubscribe();
							}
							// scheduler unsubscribe
							newW.schedule(new Action0() {
								@Override
								public void call() {
									Subscriber sub;
									synchronized (lock) {
										sub = extra.get();
										extra.set(null);
									}
									sub.unsubscribe();
									newW.unsubscribe();
									worker.compareAndSet(newW, null);
								}
							}, delayMs, TimeUnit.MILLISECONDS);
						}
					}
				}));
	}

	private static  Subscriber doNothing() {
		return new Subscriber() {

			@Override
			public void onCompleted() {
			}

			@Override
			public void onError(Throwable e) {
			}

			@Override
			public void onNext(T t) {
			}
		};
	}

	private static final class OperatorAddToSubscription implements Operator {

		private final Action0 action;

		OperatorAddToSubscription(Action0 action) {
			this.action = action;
		}

		@Override
		public Subscriber call(Subscriber child) {
			Subscriber parent = Subscribers.wrap(child);
			child.add(Subscriptions.create(action));
			return parent;
		}

	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy