IgniteFutureImpl implements IgniteFuture<V> { @Override public <T> IgniteFuture<T> chainAsync(final IgniteClosure<? super IgniteFuture<V>, T> doneCb, Executor exec) { A.notNull(doneCb, "doneCb"); A.notNull(exec, "exec"); return new IgniteFutureImpl<>(chainInternal(doneCb, exec)); } IgniteFutureImpl(IgniteInternalFuture<V> fut); IgniteInternalFuture<V> internalFuture(); @Override boolean isCancelled(); @Override boolean isDone(); @Override void listen(IgniteInClosure<? super IgniteFuture<V>> lsnr); @Override void listenAsync(IgniteInClosure<? super IgniteFuture<V>> lsnr, Executor exec); @Override IgniteFuture<T> chain(final IgniteClosure<? super IgniteFuture<V>, T> doneCb); @Override IgniteFuture<T> chainAsync(final IgniteClosure<? super IgniteFuture<V>, T> doneCb,
        Executor exec); @Override boolean cancel(); @Override V get(); @Override V get(long timeout); @Override V get(long timeout, TimeUnit unit); @Override String toString();  }
@Test public void testChainAsync() throws Exception { GridFutureAdapter<String> fut0 = new GridFutureAdapter<>(); IgniteFuture<String> fut = createFuture(fut0); C1<IgniteFuture<String>, Integer> chainClos = new C1<IgniteFuture<String>, Integer>() { @Override public Integer apply(IgniteFuture<String> fut) { assertEquals(CUSTOM_THREAD_NAME, Thread.currentThread().getName()); return Integer.valueOf(fut.get()); } }; IgniteFuture<Integer> chained1 = fut.chainAsync(chainClos, customExec); assertFalse(chained1.isDone()); final CountDownLatch latch = new CountDownLatch(1); class TestClosure implements CI1<IgniteFuture<Integer>> { private final CountDownLatch latch; private TestClosure(CountDownLatch latch) { this.latch = latch; } @Override public void apply(IgniteFuture<Integer> fut) { assertEquals(CUSTOM_THREAD_NAME, Thread.currentThread().getName()); assertEquals(10, (int)fut.get()); latch.countDown(); } } chained1.listen(new TestClosure(latch)); fut0.onDone("10"); chained1.get(100, TimeUnit.MILLISECONDS); assertTrue(chained1.isDone()); assertEquals(10, (int)chained1.get()); assert latch.await(100, TimeUnit.MILLISECONDS); assertTrue(fut.isDone()); assertEquals("10", fut.get()); GridFinishedFuture<String> ffut0 = new GridFinishedFuture<>("10"); CountDownLatch latch1 = new CountDownLatch(1); IgniteFuture<Integer> chained2 = createFuture(ffut0).chainAsync(chainClos, customExec); chained2.listen(new TestClosure(latch1)); chained2.get(100, TimeUnit.MILLISECONDS); assertTrue(chained2.isDone()); assertEquals(10, (int)chained2.get()); assert latch1.await(100, TimeUnit.MILLISECONDS); }