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

hu.akarnokd.rxjava2.debug.multihook.MultiHandlerManager Maven / Gradle / Ivy

There is a newer version: 0.20.10
Show newest version
/*
 * Copyright 2016-2018 David Karnok
 *
 * 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.debug.multihook;

import java.util.Iterator;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicReference;

import io.reactivex.annotations.NonNull;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.*;
import io.reactivex.internal.functions.ObjectHelper;

/**
 * Manages an array of handlers.
 *
 * @param  the handler type
 * @since 0.18.0
 */
public class MultiHandlerManager {

    /**
     * The copy-on-write registry of handlers wrapped into a HandlerRegistration container
     * to support disposing/unregistering a particular registration.
     */
    protected final CopyOnWriteArrayList> handlers;

    /**
     * Constructs an empty handler manager.
     */
    public MultiHandlerManager() {
        handlers = new CopyOnWriteArrayList>();
    }

    /**
     * Registers the specified handler instance with this MultiHandlerManager.
     * 

* Handlers don't have to be unique instances, if the same handler is * registered multiple times, it will be invoked multiple times as well. *

* This method is threadsafe. * @param handler the handler to register * @return the Disposable instance to unregister the handler. */ @NonNull public final Disposable register(@NonNull H handler) { ObjectHelper.requireNonNull(handler, "handler is null"); HandlerRegistration hr = new HandlerRegistration(this, handler); handlers.add(hr); return hr; } final void unregister(HandlerRegistration handler) { handlers.remove(handler); } /** * The given consumer is invoked with each registered handler instance. *

* Exceptions raised by the invocation of the consumer for a particular * handler are printed to the console and the current thread's * uncaught exception handler is notified. *

* This method is threadsafe. * @param consumer the consumer to invoke */ public final void forEach(@NonNull Consumer consumer) { ObjectHelper.requireNonNull(consumer, "consumer is null"); Iterator> it = handlers.iterator(); while (it.hasNext()) { try { HandlerRegistration hr = it.next(); H h = hr.get(); if (h != null) { consumer.accept(h); } } catch (Throwable ex) { ex.printStackTrace(); Thread t = Thread.currentThread(); t.getUncaughtExceptionHandler().uncaughtException(t, ex); } } } /** * The given consumer is invoked with each registered handler instance. *

* Exceptions raised by the invocation of the consumer for a particular * handler are printed to the console and the current thread's * uncaught exception handler is notified. *

* This method is threadsafe. * @param the type of the extra state provided to the consumer * @param state the extra state provided to the consumer * @param consumer the consumer to invoke */ public final void forEach(S state, @NonNull BiConsumer consumer) { ObjectHelper.requireNonNull(consumer, "consumer is null"); Iterator> it = handlers.iterator(); while (it.hasNext()) { try { HandlerRegistration hr = it.next(); H h = hr.get(); if (h != null) { consumer.accept(state, h); } } catch (Throwable ex) { ex.printStackTrace(); Thread t = Thread.currentThread(); t.getUncaughtExceptionHandler().uncaughtException(t, ex); } } } /** * Removes all handlers from this MultiHandlerManager. *

* This method is threadsafe. */ public final void clear() { handlers.clear(); } /** * Returns true if this manager has any handlers registered. *

* This method is threadsafe. * @return true if this manager has any handlers registered. */ public final boolean hasHandlers() { return !handlers.isEmpty(); } static final class HandlerRegistration extends AtomicReference implements Disposable { private static final long serialVersionUID = -3761960052630027297L; final MultiHandlerManager parent; HandlerRegistration(MultiHandlerManager parent, H handler) { this.parent = parent; lazySet(handler); } @Override public void dispose() { H h = getAndSet(null); if (h != null) { parent.unregister(this); } } @Override public boolean isDisposed() { return get() == null; } } }