IteratingCallback implements Consumer<Result<Void>> { public void iterate() { boolean process = false; loop: while (true) { try (Locker.Lock lock = locker.lock()) { switch (state) { case PENDING: case CALLED: break loop; case IDLE: state = State.PROCESSING; process = true; break loop; case PROCESSING: iterate = true; break loop; case FAILED: case SUCCEEDED: break loop; case CLOSED: default: throw new IllegalStateException(toString()); } } } if (process) processing(); } protected  IteratingCallback(); protected  IteratingCallback(boolean needReset); void iterate(); @Override void accept(Result<Void> result); void close(); boolean isClosed(); boolean isFailed(); boolean isSucceeded(); boolean reset(); @Override String toString();  }
@Test public void testWaitingProcess() throws Exception { TestCB cb = new TestCB() { int i = 4; @Override protected Action process() throws Exception { processed++; if (i-- > 1) { scheduler.schedule(successTask, 50, TimeUnit.MILLISECONDS); return Action.SCHEDULED; } return Action.SUCCEEDED; } }; cb.iterate(); assertTrue(cb.waitForComplete()); assertEquals(4, cb.processed); }
@Test public void testWaitingProcessFailure() throws Exception { TestCB cb = new TestCB() { int i = 4; @Override protected Action process() { processed++; if (i-- > 1) { scheduler.schedule(i > 2 ? successTask : failTask, 50, TimeUnit.MILLISECONDS); return Action.SCHEDULED; } return Action.SUCCEEDED; } }; cb.iterate(); assertFalse(cb.waitForComplete()); assertEquals(2, cb.processed); }