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

rx.internal.util.SubscriptionIndexedRingBuffer Maven / Gradle / Ivy

There is a newer version: 1.3.8
Show newest version
/**
 * Copyright 2014 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 rx.internal.util;

import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;

import rx.Subscription;
import rx.functions.Func1;

/**
 * Similar to CompositeSubscription but giving extra access to internals so we can reuse a datastructure.
 * 

* NOTE: This purposefully is leaking the internal data structure through the API for efficiency reasons to avoid extra object allocations. */ public final class SubscriptionIndexedRingBuffer implements Subscription { private volatile IndexedRingBuffer subscriptions = IndexedRingBuffer.getInstance(); private volatile int unsubscribed = 0; @SuppressWarnings("rawtypes") private final static AtomicIntegerFieldUpdater UNSUBSCRIBED = AtomicIntegerFieldUpdater.newUpdater(SubscriptionIndexedRingBuffer.class, "unsubscribed"); public SubscriptionIndexedRingBuffer() { } @Override public boolean isUnsubscribed() { return unsubscribed == 1; } /** * Adds a new {@link Subscription} to this {@code CompositeSubscription} if the {@code CompositeSubscription} is not yet unsubscribed. If the {@code CompositeSubscription} is * unsubscribed, {@code add} will indicate this by explicitly unsubscribing the new {@code Subscription} as * well. * * @param s * the {@link Subscription} to add * * @return int index that can be used to remove a Subscription */ public synchronized int add(final T s) { // TODO figure out how to remove synchronized here. See https://github.com/ReactiveX/RxJava/issues/1420 if (unsubscribed == 1 || subscriptions == null) { s.unsubscribe(); return -1; } else { int n = subscriptions.add(s); // double check for race condition if (unsubscribed == 1) { s.unsubscribe(); } return n; } } /** * Uses the Node received from `add` to remove this Subscription. *

* Unsubscribes the Subscription after removal */ public void remove(final int n) { if (unsubscribed == 1 || subscriptions == null || n < 0) { return; } Subscription t = subscriptions.remove(n); if (t != null) { // if we removed successfully we then need to call unsubscribe on it if (t != null) { t.unsubscribe(); } } } /** * Uses the Node received from `add` to remove this Subscription. *

* Does not unsubscribe the Subscription after removal. */ public void removeSilently(final int n) { if (unsubscribed == 1 || subscriptions == null || n < 0) { return; } subscriptions.remove(n); } @Override public void unsubscribe() { if (UNSUBSCRIBED.compareAndSet(this, 0, 1) && subscriptions != null) { // we will only get here once unsubscribeFromAll(subscriptions); IndexedRingBuffer s = subscriptions; subscriptions = null; s.unsubscribe(); } } public int forEach(Func1 action) { return forEach(action, 0); } /** * * @param action * @return int of last index seen if forEach exited early */ public synchronized int forEach(Func1 action, int startIndex) { // TODO figure out how to remove synchronized here. See https://github.com/ReactiveX/RxJava/issues/1420 if (unsubscribed == 1 || subscriptions == null) { return 0; } return subscriptions.forEach(action, startIndex); } private static void unsubscribeFromAll(IndexedRingBuffer subscriptions) { if (subscriptions == null) { return; } // TODO migrate to drain (remove while we're doing this) so we don't have to immediately clear it in IndexedRingBuffer.releaseToPool? subscriptions.forEach(UNSUBSCRIBE); } private final static Func1 UNSUBSCRIBE = new Func1() { @Override public Boolean call(Subscription s) { s.unsubscribe(); return Boolean.TRUE; } }; }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy