@NonNull @Override public Disposable schedule(@NonNull Runnable run, long delay, @NonNull TimeUnit unit) { if (disposed) { return REJECTED; } Runnable decoratedRun = RxJavaCommonPlugins.onSchedule(run); ScheduledRunnable sr = new ScheduledRunnable(decoratedRun, tasks); tasks.add(sr); try { Future<?> f; if (delay <= 0L) { f = executor.submit((Callable<Object>)sr); } else { f = executor.schedule((Callable<Object>)sr, delay, unit); } sr.setFuture(f); } catch (RejectedExecutionException ex) { dispose(); RxJavaCommonPlugins.onError(ex); return REJECTED; } return sr; }
@NonNull @Override public Disposable schedule(@NonNull Runnable run, long delay, @NonNull TimeUnit unit) { if (disposed) { return REJECTED; } Runnable decoratedRun = RxJavaCommonPlugins.onSchedule(run); ScheduledRunnable sr = new ScheduledRunnable(decoratedRun, tasks); tasks.add(sr); try { Future<?> f; if (delay <= 0L) { f = executor.submit((Callable<Object>)sr); } else { f = executor.schedule((Callable<Object>)sr, delay, unit); } sr.setFuture(f); } catch (RejectedExecutionException ex) { dispose(); RxJavaCommonPlugins.onError(ex); return REJECTED; } return sr; }
@NonNull @Override public Disposable schedule(@NonNull Runnable run, long delay, @NonNull TimeUnit unit) { if (disposed) { return REJECTED; } Runnable decoratedRun = RxJavaCommonPlugins.onSchedule(run); ScheduledRunnable sr = new ScheduledRunnable(decoratedRun, tasks); tasks.add(sr); try { Future<?> f; if (delay <= 0L) { f = executor.submit((Callable<Object>)sr); } else { f = executor.schedule((Callable<Object>)sr, delay, unit); } sr.setFuture(f); } catch (RejectedExecutionException ex) { dispose(); RxJavaCommonPlugins.onError(ex); return REJECTED; } return sr; }
@Test public void withFutureDisposed2() { ScheduledRunnable run = new ScheduledRunnable(Functions.EMPTY_RUNNABLE, null); run.dispose(); run.setFuture(new FutureTask<Void>(Functions.EMPTY_RUNNABLE, null)); run.call(); }
@Test public void withoutParentDisposed() { ScheduledRunnable run = new ScheduledRunnable(Functions.EMPTY_RUNNABLE, null); run.dispose(); run.call(); }
@Test public void withFutureDisposed() { ScheduledRunnable run = new ScheduledRunnable(Functions.EMPTY_RUNNABLE, null); run.setFuture(new FutureTask<Void>(Functions.EMPTY_RUNNABLE, null)); run.dispose(); run.call(); }
@Test public void withFutureDisposed3() { ScheduledRunnable run = new ScheduledRunnable(Functions.EMPTY_RUNNABLE, null); run.dispose(); run.set(2, Thread.currentThread()); run.setFuture(new FutureTask<Void>(Functions.EMPTY_RUNNABLE, null)); run.call(); }
@Test public void runFuture() { for (int i = 0; i < 500; i++) { CompositeDisposable set = new CompositeDisposable(); final ScheduledRunnable run = new ScheduledRunnable(Functions.EMPTY_RUNNABLE, set); set.add(run); final FutureTask<Void> ft = new FutureTask<Void>(Functions.EMPTY_RUNNABLE, null); Runnable r1 = new Runnable() { @Override public void run() { run.call(); } }; Runnable r2 = new Runnable() { @Override public void run() { run.setFuture(ft); } }; TestCommonHelper.race(r1, r2); } } }
@Test public void withParentDisposed() { ScheduledRunnable run = new ScheduledRunnable(Functions.EMPTY_RUNNABLE, new CompositeDisposable()); run.dispose(); run.call(); }
@Test public void setFutureRunRace() { for (int i = 0; i < 500; i++) { CompositeDisposable set = new CompositeDisposable(); final ScheduledRunnable run = new ScheduledRunnable(Functions.EMPTY_RUNNABLE, set); set.add(run); final FutureTask<Object> ft = new FutureTask<Object>(Functions.EMPTY_RUNNABLE, 0); Runnable r1 = new Runnable() { @Override public void run() { run.setFuture(ft); } }; Runnable r2 = new Runnable() { @Override public void run() { run.run(); } }; TestCommonHelper.race(r1, r2); assertEquals(0, set.size()); } }
@Test public void setFutureCancelRace() { for (int i = 0; i < 500; i++) { CompositeDisposable set = new CompositeDisposable(); final ScheduledRunnable run = new ScheduledRunnable(Functions.EMPTY_RUNNABLE, set); set.add(run); final FutureTask<Object> ft = new FutureTask<Object>(Functions.EMPTY_RUNNABLE, 0); Runnable r1 = new Runnable() { @Override public void run() { run.setFuture(ft); } }; Runnable r2 = new Runnable() { @Override public void run() { run.dispose(); } }; TestCommonHelper.race(r1, r2); assertEquals(0, set.size()); } }
@Test public void pluginCrash() { Thread.currentThread().setUncaughtExceptionHandler(new UncaughtExceptionHandler() { @Override public void uncaughtException(Thread t, Throwable e) { throw new TestException("Second"); } }); CompositeDisposable set = new CompositeDisposable(); final ScheduledRunnable run = new ScheduledRunnable(new Runnable() { @Override public void run() { throw new TestException("First"); } }, set); set.add(run); try { run.run(); fail("Should have thrown!"); } catch (TestException ex) { assertEquals("Second", ex.getMessage()); } finally { Thread.currentThread().setUncaughtExceptionHandler(null); } assertTrue(run.isDisposed()); assertEquals(0, set.size()); }
@Test public void disposeRace() { for (int i = 0; i < 500; i++) { CompositeDisposable set = new CompositeDisposable(); final ScheduledRunnable run = new ScheduledRunnable(Functions.EMPTY_RUNNABLE, set); set.add(run); Runnable r1 = new Runnable() { @Override public void run() { run.dispose(); } }; TestCommonHelper.race(r1, r1); assertEquals(0, set.size()); } }
@NonNull @Override public Disposable schedule(@NonNull Runnable run, long delay, @NonNull TimeUnit unit) { if (delay <= 0) { return schedule(run); } if (disposed) { return REJECTED; } SequentialDisposable first = new SequentialDisposable(); final SequentialDisposable mar = new SequentialDisposable(first); final Runnable decoratedRun = RxJavaCommonPlugins.onSchedule(run); ScheduledRunnable sr = new ScheduledRunnable(new SequentialDispose(mar, decoratedRun), tasks); tasks.add(sr); if (executor instanceof ScheduledExecutorService) { try { Future<?> f = ((ScheduledExecutorService)executor).schedule((Callable<Object>)sr, delay, unit); sr.setFuture(f); } catch (RejectedExecutionException ex) { disposed = true; RxJavaCommonPlugins.onError(ex); return REJECTED; } } else { final Disposable d = HELPER.scheduleDirect(sr, delay, unit); sr.setFuture(new DisposeOnCancel(d)); } first.replace(sr); return mar; }
@NonNull @Override public Disposable schedule(@NonNull Runnable run, long delay, @NonNull TimeUnit unit) { if (delay <= 0) { return schedule(run); } if (disposed) { return REJECTED; } SequentialDisposable first = new SequentialDisposable(); final SequentialDisposable mar = new SequentialDisposable(first); final Runnable decoratedRun = RxJavaCommonPlugins.onSchedule(run); ScheduledRunnable sr = new ScheduledRunnable(new SequentialDispose(mar, decoratedRun), tasks); tasks.add(sr); if (executor instanceof ScheduledExecutorService) { try { Future<?> f = ((ScheduledExecutorService)executor).schedule((Callable<Object>)sr, delay, unit); sr.setFuture(f); } catch (RejectedExecutionException ex) { disposed = true; RxJavaCommonPlugins.onError(ex); return REJECTED; } } else { final Disposable d = HELPER.scheduleDirect(sr, delay, unit); sr.setFuture(new DisposeOnCancel(d)); } first.replace(sr); return mar; }
@NonNull @Override public Disposable schedule(@NonNull Runnable run, long delay, @NonNull TimeUnit unit) { if (delay <= 0) { return schedule(run); } if (disposed) { return REJECTED; } SequentialDisposable first = new SequentialDisposable(); final SequentialDisposable mar = new SequentialDisposable(first); final Runnable decoratedRun = RxJavaCommonPlugins.onSchedule(run); ScheduledRunnable sr = new ScheduledRunnable(new SequentialDispose(mar, decoratedRun), tasks); tasks.add(sr); if (executor instanceof ScheduledExecutorService) { try { Future<?> f = ((ScheduledExecutorService)executor).schedule((Callable<Object>)sr, delay, unit); sr.setFuture(f); } catch (RejectedExecutionException ex) { disposed = true; RxJavaCommonPlugins.onError(ex); return REJECTED; } } else { final Disposable d = HELPER.scheduleDirect(sr, delay, unit); sr.setFuture(new DisposeOnCancel(d)); } first.replace(sr); return mar; }
@Test public void runDispose() { for (int i = 0; i < 500; i++) { CompositeDisposable set = new CompositeDisposable(); final ScheduledRunnable run = new ScheduledRunnable(Functions.EMPTY_RUNNABLE, set); set.add(run); Runnable r1 = new Runnable() { @Override public void run() { run.call(); } }; Runnable r2 = new Runnable() { @Override public void run() { run.dispose(); } }; TestCommonHelper.race(r1, r2); assertEquals(0, set.size()); } }
@Test public void dispose() { CompositeDisposable set = new CompositeDisposable(); ScheduledRunnable run = new ScheduledRunnable(Functions.EMPTY_RUNNABLE, set); set.add(run); assertFalse(run.isDisposed()); set.dispose(); assertTrue(run.isDisposed()); }
@Test public void disposeRun() { CompositeDisposable set = new CompositeDisposable(); ScheduledRunnable run = new ScheduledRunnable(Functions.EMPTY_RUNNABLE, set); set.add(run); assertFalse(run.isDisposed()); run.dispose(); run.dispose(); assertTrue(run.isDisposed()); }
@Test public void crashReported() { List<Throwable> errors = TestCommonHelper.trackPluginErrors(); try { CompositeDisposable set = new CompositeDisposable(); final ScheduledRunnable run = new ScheduledRunnable(new Runnable() { @Override public void run() { throw new TestException("First"); } }, set); set.add(run); run.run(); assertTrue(run.isDisposed()); assertEquals(0, set.size()); TestCommonHelper.assertUndeliverable(errors, 0, TestException.class, "First"); } finally { RxJavaCommonPlugins.reset(); } }