@Override public void dispose() { H h = getAndSet(null); if (h != null) { parent.unregister(this); } }
@Override public Runnable apply(Runnable t) throws Exception { Runnable[] ref = { t }; forEach(ref, this); return ref[0]; }
@Override public boolean isDisposed() { return get() == null; } }
@Test public void normal() { manager.enable(); try { Disposable d1 = manager.register(new Function<Runnable, Runnable>() { @Override public Runnable apply(Runnable r) throws Exception { manager.register(new Function<Runnable, Runnable>() { @Override public Runnable apply(Runnable r) throws Exception { manager.disable(); manager.forEach(new Consumer<Function<Runnable, Runnable>>() { @Override public void accept(Function<Runnable, Runnable> f) manager.clear(); manager.forEach(new Consumer<Function<Runnable, Runnable>>() { @Override public void accept(Function<Runnable, Runnable> f)
@Test public void handlerCrash() throws Exception { manager.register(new Function<Runnable, Runnable>() { @Override public Runnable apply(Runnable r) throws Exception { manager.register(new Function<Runnable, Runnable>() { @Override public Runnable apply(Runnable r) throws Exception { manager.apply(Functions.EMPTY_RUNNABLE); manager.forEach(new Consumer<Function<Runnable, Runnable>>() { @Override public void accept(Function<Runnable, Runnable> f)
@Test public void append() { try { manager.append(); manager.disable(); manager.enable(); manager.append(); manager.disable(); assertNull(RxJavaPlugins.getScheduleHandler()); RxJavaPlugins.setScheduleHandler(new Function<Runnable, Runnable>() { @Override public Runnable apply(Runnable r) throws Exception { calls++; return r; } }); manager.append(); manager.register(new Function<Runnable, Runnable>() { @Override public Runnable apply(Runnable r) throws Exception { calls++; return r; } }); RxJavaPlugins.onSchedule(Functions.EMPTY_RUNNABLE); assertEquals(2, calls); } finally { RxJavaPlugins.reset(); } }
@Test public void forEachConsumerRace() { for (int i = 0; i < 1000; i++) { final Disposable d = manager.register(Functions.<Runnable>identity()); assertTrue(manager.hasHandlers()); Runnable r1 = new Runnable() { @Override public void run() { d.dispose(); } }; Runnable r2 = new Runnable() { @Override public void run() { manager.forEach(Functions.<Function<Runnable, Runnable>>emptyConsumer()); } }; TestHelper.race(r1, r2, Schedulers.single()); assertFalse(manager.hasHandlers()); } }
/** * Adds the current non-null OnSchedule hook to this handler and replaces it * in RxJavaPlugins with this OnScheduleMultiHandlerManager. */ public void append() { @SuppressWarnings("unchecked") Function<Runnable, Runnable> existing = (Function<Runnable, Runnable>)RxJavaPlugins.getScheduleHandler(); if (existing != this) { if (existing != null) { register(existing); } RxJavaPlugins.setScheduleHandler(this); } }
HandlerRegistration(MultiHandlerManager<H> parent, H handler) { this.parent = parent; lazySet(handler); }
/** * Registers the specified handler instance with this MultiHandlerManager. * <p> * Handlers don't have to be unique instances, if the same handler is * registered multiple times, it will be invoked multiple times as well. * <p> * 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<H> hr = new HandlerRegistration<H>(this, handler); handlers.add(hr); return hr; }
@Override public Runnable apply(Runnable t) throws Exception { Runnable[] ref = { t }; forEach(ref, this); return ref[0]; }
@Override public void dispose() { H h = getAndSet(null); if (h != null) { parent.unregister(this); } }
@Test public void forEachBiConsumerRace() { for (int i = 0; i < 1000; i++) { final Disposable d = manager.register(Functions.<Runnable>identity()); assertTrue(manager.hasHandlers()); assertFalse(manager.hasHandlers());
/** * Adds the current non-null OnSchedule hook to this handler and replaces it * in RxJavaPlugins with this OnScheduleMultiHandlerManager. */ public void append() { @SuppressWarnings("unchecked") Function<Runnable, Runnable> existing = (Function<Runnable, Runnable>)RxJavaPlugins.getScheduleHandler(); if (existing != this) { if (existing != null) { register(existing); } RxJavaPlugins.setScheduleHandler(this); } }
@Override public boolean isDisposed() { return get() == null; } }
HandlerRegistration(MultiHandlerManager<H> parent, H handler) { this.parent = parent; lazySet(handler); }
/** * Registers the specified handler instance with this MultiHandlerManager. * <p> * Handlers don't have to be unique instances, if the same handler is * registered multiple times, it will be invoked multiple times as well. * <p> * 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<H> hr = new HandlerRegistration<H>(this, handler); handlers.add(hr); return hr; }
@Override public void run() { manager.forEach(0, new BiConsumer<Integer, Function<Runnable, Runnable>>() { @Override public void accept(Integer s, Function<Runnable, Runnable> f) throws Exception { // no op } }); } };
/** * The given consumer is invoked with each registered handler instance. * <p> * 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. * <p> * This method is threadsafe. * @param consumer the consumer to invoke */ public final void forEach(@NonNull Consumer<H> consumer) { ObjectHelper.requireNonNull(consumer, "consumer is null"); Iterator<HandlerRegistration<H>> it = handlers.iterator(); while (it.hasNext()) { try { HandlerRegistration<H> 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); } } }
@Override public void run() { manager.forEach(Functions.<Function<Runnable, Runnable>>emptyConsumer()); } };