class CountDownFuture extends GridFutureAdapter<Void> {
    /** */
    private AtomicInteger remaining;

    /** */
    private AtomicReference<Exception> errCollector;

    /**
     * @param cnt Number of completing parties.
     */
    public CountDownFuture(int cnt) {
        remaining = new AtomicInteger(cnt);
        errCollector = new AtomicReference<>();
    }

    /** {@inheritDoc} */
    @Override public boolean onDone(@Nullable Void res, @Nullable Throwable err) {
        if (err != null)
            addError(err);

        int left = remaining.decrementAndGet();

        boolean done = left == 0 && super.onDone(res, errCollector.get());

        if (done)
            afterDone();

        return done;
    }

    /**
     *
     */
    protected void afterDone() {
        // No-op, to be overridden in subclasses.
    }

    /**
     * @param err Error.
     */
    private void addError(Throwable err) {<FILL_FUNCTION_BODY>}
}

        Exception ex = errCollector.get();

        if (ex == null) {
            Exception compound = new IgniteCheckedException("Compound exception for CountDownFuture.");

            ex = errCollector.compareAndSet(null, compound) ? compound : errCollector.get();
        }

        assert ex != null;

        ex.addSuppressed(err);
    
<methods>public non-sealed void <init>() ,public boolean cancel() throws org.apache.ignite.IgniteCheckedException,public IgniteInternalFuture<T> chain(IgniteClosure<? super IgniteInternalFuture<java.lang.Void>,T>) ,public IgniteInternalFuture<T> chain(IgniteOutClosure<T>) ,public IgniteInternalFuture<T> chain(IgniteClosure<? super IgniteInternalFuture<java.lang.Void>,T>, java.util.concurrent.Executor) ,public IgniteInternalFuture<T> chain(IgniteOutClosure<T>, java.util.concurrent.Executor) ,public IgniteInternalFuture<T> chainCompose(IgniteClosure<? super IgniteInternalFuture<java.lang.Void>,IgniteInternalFuture<T>>) ,public IgniteInternalFuture<T> chainCompose(IgniteClosure<? super IgniteInternalFuture<java.lang.Void>,IgniteInternalFuture<T>>, java.util.concurrent.Executor) ,public java.lang.Throwable error() ,public java.lang.Void get() throws org.apache.ignite.IgniteCheckedException,public java.lang.Void get(long) throws org.apache.ignite.IgniteCheckedException,public java.lang.Void get(long, java.util.concurrent.TimeUnit) throws org.apache.ignite.IgniteCheckedException,public java.lang.Void getUninterruptibly() throws org.apache.ignite.IgniteCheckedException,public void ignoreInterrupts() ,public boolean isCancelled() ,public boolean isDone() ,public boolean isFailed() ,public void listen(IgniteInClosure<? super IgniteInternalFuture<java.lang.Void>>) ,public void listen(org.apache.ignite.lang.IgniteRunnable) ,public org.apache.ignite.IgniteLogger logger() ,public boolean onCancelled() ,public final boolean onDone() ,public final boolean onDone(java.lang.Void) ,public final boolean onDone(java.lang.Throwable) ,public boolean onDone(java.lang.Void, java.lang.Throwable) ,public void reset() ,public java.lang.Void result() ,public java.lang.String toString() <variables>private static final java.lang.Object CANCELLED,private static final java.lang.String DONE,private static final org.apache.ignite.internal.util.future.GridFutureAdapter.Node INIT,private volatile boolean ignoreInterrupts,private volatile java.lang.Object state,private static final AtomicReferenceFieldUpdater<GridFutureAdapter#RAW,java.lang.Object> stateUpdater