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

hu.akarnokd.rxjava2.subscribers.AsyncObserver Maven / Gradle / Ivy

There is a newer version: 2.0.0-RC3
Show newest version
/**
 * 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.subscribers;

import java.util.concurrent.atomic.*;

import org.reactivestreams.*;

import hu.akarnokd.rxjava2.disposables.*;
import hu.akarnokd.rxjava2.internal.disposables.ListCompositeResource;
import hu.akarnokd.rxjava2.internal.functions.Objects;
import hu.akarnokd.rxjava2.internal.subscriptions.SubscriptionHelper;
import hu.akarnokd.rxjava2.internal.util.BackpressureHelper;

/**
 * An abstract Subscriber implementation that allows asynchronous cancellation of its
 * subscription.
 * 
 * 

This implementation let's you chose if the AsyncObserver manages resources or not, * thus saving memory on cases where there is no need for that. * *

All pre-implemented final methods are thread-safe. * * @param the value type */ public abstract class AsyncObserver implements Subscriber, Disposable { /** The active subscription. */ private volatile Subscription s; /** Updater of s. */ @SuppressWarnings("rawtypes") private static final AtomicReferenceFieldUpdater S = AtomicReferenceFieldUpdater.newUpdater(AsyncObserver.class, Subscription.class, "s"); /** The resource composite, can be null. */ private final ListCompositeResource resources; /** Remembers the request(n) counts until a subscription arrives. */ @SuppressWarnings("unused") private volatile long missedRequested; /** The updater of missedRequested. */ @SuppressWarnings("rawtypes") private static final AtomicLongFieldUpdater MISSED_REQUESTED = AtomicLongFieldUpdater.newUpdater(AsyncObserver.class, "missedRequested"); /** The cancelled subscription indicator. */ private static final Subscription CANCELLED = new Subscription() { @Override public void request(long n) { // deliberately no op } @Override public void cancel() { // deliberately no op } }; /** * Constructs an AsyncObserver with resource support. */ public AsyncObserver() { this(true); } /** * Constructs an AsyncObserver and allows specifying if it should support resources or not. * @param withResources true if resource support should be on. */ public AsyncObserver(boolean withResources) { this.resources = withResources ? new ListCompositeResource(Disposables.consumeAndDispose()) : null; } /** * Adds a resource to this AsyncObserver. * *

Note that if the AsyncObserver doesn't manage resources, this method will * throw an IllegalStateException. Use {@link #supportsResources()} to determine if * this AsyncObserver manages resources or not. * * @param resource the resource to add * * @throws NullPointerException if resource is null * @throws IllegalStateException if this AsyncObserver doesn't manage resources * @see #supportsResources() */ public final void add(Disposable resource) { Objects.requireNonNull(resource, "resource is null"); if (resources != null) { add(resource); } else { resource.dispose(); throw new IllegalStateException("This AsyncObserver doesn't manage additional resources"); } } /** * Returns true if this AsyncObserver supports resources added via the add() method. * @return true if this AsyncObserver supports resources added via the add() method * @see #add(Disposable) */ public final boolean supportsResources() { return resources != null; } @Override public final void onSubscribe(Subscription s) { if (!S.compareAndSet(this, null, s)) { s.cancel(); if (s != CANCELLED) { SubscriptionHelper.reportSubscriptionSet(); } return; } long mr = MISSED_REQUESTED.getAndSet(this, 0L); if (mr != 0L) { s.request(mr); } onStart(); } /** * Called once the upstream sets a Subscription on this AsyncObserver. * *

You can perform initialization at this moment. The default * implementation requests Long.MAX_VALUE from upstream. */ protected void onStart() { request(Long.MAX_VALUE); } /** * Request the specified amount of elements from upstream. * *

This method can be called before the upstream calls onSubscribe(). * When the subscription happens, all missed requests are requested. * * @param n the request amount, must be positive */ protected final void request(long n) { if (SubscriptionHelper.validateRequest(n)) { return; } Subscription a = s; if (a == null) { BackpressureHelper.add(MISSED_REQUESTED, this, n); a = s; if (a != null) { long mr = MISSED_REQUESTED.getAndSet(this, 0L); if (mr != 0L) { a.request(mr); } } } else { a.request(n); } } /** * Cancels the subscription (if any) and disposes the resources associated with * this AsyncObserver (if any). * *

This method can be called before the upstream calls onSubscribe at which * case the Subscription will be immediately cancelled. */ protected final void cancel() { Subscription a = s; if (a != CANCELLED) { a = S.getAndSet(this, CANCELLED); if (a != CANCELLED && a != null) { a.cancel(); if (resources != null) { resources.dispose(); } } } } @Override public final void dispose() { cancel(); } /** * Returns true if this AsyncObserver has been disposed/cancelled. * @return true if this AsyncObserver has been disposed/cancelled */ public final boolean isDisposed() { return s == CANCELLED; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy