class AsyncCommand<K, V, T> extends CompletableFuture<T>
        implements RedisCommand<K, V, T>, RedisFuture<T>, CompleteableCommand<T>, DecoratedCommand<K, V, T> {

    @SuppressWarnings("rawtypes")
    private static final AtomicIntegerFieldUpdater<AsyncCommand> COUNT_UPDATER = AtomicIntegerFieldUpdater
            .newUpdater(AsyncCommand.class, "count");

    private final RedisCommand<K, V, T> command;

    // access via COUNT_UPDATER
    @SuppressWarnings({ "unused" })
    private volatile int count = 1;

    /**
     * @param command the command, must not be {@code null}.
     */
    public AsyncCommand(RedisCommand<K, V, T> command) {
        this(command, 1);
    }

    /**
     * @param command the command, must not be {@code null}.
     */
    protected AsyncCommand(RedisCommand<K, V, T> command, int count) {
        LettuceAssert.notNull(command, "RedisCommand must not be null");
        this.command = command;
        this.count = count;
    }

    /**
     * Wait up to the specified time for the command output to become available.
     *
     * @param timeout Maximum time to wait for a result.
     * @param unit Unit of time for the timeout.
     *
     * @return true if the output became available.
     */
    @Override
    public boolean await(long timeout, TimeUnit unit) {<FILL_FUNCTION_BODY>}

    /**
     * Get the object that holds this command's output.
     *
     * @return The command output object.
     */
    @Override
    public CommandOutput<K, V, T> getOutput() {
        return command.getOutput();
    }

    /**
     * Mark this command complete and notify all waiting threads.
     */
    @Override
    public void complete() {
        if (COUNT_UPDATER.decrementAndGet(this) == 0) {
            completeResult();
            command.complete();
        }
    }

    protected void completeResult() {
        if (command.getOutput() == null) {
            complete(null);
        } else if (command.getOutput().hasError()) {
            doCompleteExceptionally(ExceptionFactory.createExecutionException(command.getOutput().getError()));
        } else {
            complete(command.getOutput().get());
        }
    }

    @Override
    public boolean completeExceptionally(Throwable ex) {
        boolean result = false;

        int ref = COUNT_UPDATER.get(this);
        if (ref > 0 && COUNT_UPDATER.compareAndSet(this, ref, 0)) {
            result = doCompleteExceptionally(ex);
        }
        return result;
    }

    private boolean doCompleteExceptionally(Throwable ex) {
        command.completeExceptionally(ex);
        return super.completeExceptionally(ex);
    }

    @Override
    public boolean cancel(boolean mayInterruptIfRunning) {
        try {
            command.cancel();
            return super.cancel(mayInterruptIfRunning);
        } finally {
            COUNT_UPDATER.set(this, 0);
        }
    }

    @Override
    public String getError() {
        return command.getOutput().getError();
    }

    @Override
    public CommandArgs<K, V> getArgs() {
        return command.getArgs();
    }

    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder();
        sb.append(getClass().getSimpleName());
        sb.append(" [type=").append(getType());
        sb.append(", output=").append(getOutput());
        sb.append(", commandType=").append(command.getClass().getName());
        sb.append(']');
        return sb.toString();
    }

    @Override
    public ProtocolKeyword getType() {
        return command.getType();
    }

    @Override
    public void cancel() {
        cancel(true);
    }

    @Override
    public void encode(ByteBuf buf) {
        command.encode(buf);
    }

    @Override
    public void setOutput(CommandOutput<K, V, T> output) {
        command.setOutput(output);
    }

    @Override
    public void onComplete(Consumer<? super T> action) {
        thenAccept(action);
    }

    @Override
    public void onComplete(BiConsumer<? super T, Throwable> action) {
        whenComplete(action);
    }

    @Override
    public RedisCommand<K, V, T> getDelegate() {
        return command;
    }

    @Override
    public boolean equals(Object o) {

        if (this == o)
            return true;
        if (!(o instanceof RedisCommand)) {
            return false;
        }

        RedisCommand<?, ?, ?> left = CommandWrapper.unwrap(command);
        RedisCommand<?, ?, ?> right = CommandWrapper.unwrap((RedisCommand<?, ?, ?>) o);

        return left == right;
    }

    @Override
    public int hashCode() {

        RedisCommand<?, ?, ?> toHash = CommandWrapper.unwrap(command);

        return toHash != null ? toHash.hashCode() : 0;
    }

}

        try {
            get(timeout, unit);
            return true;
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new RedisCommandInterruptedException(e);
        } catch (ExecutionException e) {
            return true;
        } catch (TimeoutException e) {
            return false;
        }
    
<methods>public void <init>() ,public CompletableFuture<java.lang.Void> acceptEither(CompletionStage<? extends T>, Consumer<? super T>) ,public CompletableFuture<java.lang.Void> acceptEitherAsync(CompletionStage<? extends T>, Consumer<? super T>) ,public CompletableFuture<java.lang.Void> acceptEitherAsync(CompletionStage<? extends T>, Consumer<? super T>, java.util.concurrent.Executor) ,public static transient CompletableFuture<java.lang.Void> allOf(CompletableFuture<?>[]) ,public static transient CompletableFuture<java.lang.Object> anyOf(CompletableFuture<?>[]) ,public CompletableFuture<U> applyToEither(CompletionStage<? extends T>, Function<? super T,U>) ,public CompletableFuture<U> applyToEitherAsync(CompletionStage<? extends T>, Function<? super T,U>) ,public CompletableFuture<U> applyToEitherAsync(CompletionStage<? extends T>, Function<? super T,U>, java.util.concurrent.Executor) ,public boolean cancel(boolean) ,public boolean complete(T) ,public CompletableFuture<T> completeAsync(Supplier<? extends T>) ,public CompletableFuture<T> completeAsync(Supplier<? extends T>, java.util.concurrent.Executor) ,public boolean completeExceptionally(java.lang.Throwable) ,public CompletableFuture<T> completeOnTimeout(T, long, java.util.concurrent.TimeUnit) ,public static CompletableFuture<U> completedFuture(U) ,public static CompletionStage<U> completedStage(U) ,public CompletableFuture<T> copy() ,public java.util.concurrent.Executor defaultExecutor() ,public static java.util.concurrent.Executor delayedExecutor(long, java.util.concurrent.TimeUnit) ,public static java.util.concurrent.Executor delayedExecutor(long, java.util.concurrent.TimeUnit, java.util.concurrent.Executor) ,public CompletableFuture<T> exceptionally(Function<java.lang.Throwable,? extends T>) ,public CompletableFuture<T> exceptionallyAsync(Function<java.lang.Throwable,? extends T>) ,public CompletableFuture<T> exceptionallyAsync(Function<java.lang.Throwable,? extends T>, java.util.concurrent.Executor) ,public CompletableFuture<T> exceptionallyCompose(Function<java.lang.Throwable,? extends CompletionStage<T>>) ,public CompletableFuture<T> exceptionallyComposeAsync(Function<java.lang.Throwable,? extends CompletionStage<T>>) ,public CompletableFuture<T> exceptionallyComposeAsync(Function<java.lang.Throwable,? extends CompletionStage<T>>, java.util.concurrent.Executor) ,public static CompletableFuture<U> failedFuture(java.lang.Throwable) ,public static CompletionStage<U> failedStage(java.lang.Throwable) ,public T get() throws java.lang.InterruptedException, java.util.concurrent.ExecutionException,public T get(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException, java.util.concurrent.ExecutionException, java.util.concurrent.TimeoutException,public T getNow(T) ,public int getNumberOfDependents() ,public CompletableFuture<U> handle(BiFunction<? super T,java.lang.Throwable,? extends U>) ,public CompletableFuture<U> handleAsync(BiFunction<? super T,java.lang.Throwable,? extends U>) ,public CompletableFuture<U> handleAsync(BiFunction<? super T,java.lang.Throwable,? extends U>, java.util.concurrent.Executor) ,public boolean isCancelled() ,public boolean isCompletedExceptionally() ,public boolean isDone() ,public T join() ,public CompletionStage<T> minimalCompletionStage() ,public CompletableFuture<U> newIncompleteFuture() ,public void obtrudeException(java.lang.Throwable) ,public void obtrudeValue(T) ,public CompletableFuture<T> orTimeout(long, java.util.concurrent.TimeUnit) ,public CompletableFuture<java.lang.Void> runAfterBoth(CompletionStage<?>, java.lang.Runnable) ,public CompletableFuture<java.lang.Void> runAfterBothAsync(CompletionStage<?>, java.lang.Runnable) ,public CompletableFuture<java.lang.Void> runAfterBothAsync(CompletionStage<?>, java.lang.Runnable, java.util.concurrent.Executor) ,public CompletableFuture<java.lang.Void> runAfterEither(CompletionStage<?>, java.lang.Runnable) ,public CompletableFuture<java.lang.Void> runAfterEitherAsync(CompletionStage<?>, java.lang.Runnable) ,public CompletableFuture<java.lang.Void> runAfterEitherAsync(CompletionStage<?>, java.lang.Runnable, java.util.concurrent.Executor) ,public static CompletableFuture<java.lang.Void> runAsync(java.lang.Runnable) ,public static CompletableFuture<java.lang.Void> runAsync(java.lang.Runnable, java.util.concurrent.Executor) ,public static CompletableFuture<U> supplyAsync(Supplier<U>) ,public static CompletableFuture<U> supplyAsync(Supplier<U>, java.util.concurrent.Executor) ,public CompletableFuture<java.lang.Void> thenAccept(Consumer<? super T>) ,public CompletableFuture<java.lang.Void> thenAcceptAsync(Consumer<? super T>) ,public CompletableFuture<java.lang.Void> thenAcceptAsync(Consumer<? super T>, java.util.concurrent.Executor) ,public CompletableFuture<java.lang.Void> thenAcceptBoth(CompletionStage<? extends U>, BiConsumer<? super T,? super U>) ,public CompletableFuture<java.lang.Void> thenAcceptBothAsync(CompletionStage<? extends U>, BiConsumer<? super T,? super U>) ,public CompletableFuture<java.lang.Void> thenAcceptBothAsync(CompletionStage<? extends U>, BiConsumer<? super T,? super U>, java.util.concurrent.Executor) ,public CompletableFuture<U> thenApply(Function<? super T,? extends U>) ,public CompletableFuture<U> thenApplyAsync(Function<? super T,? extends U>) ,public CompletableFuture<U> thenApplyAsync(Function<? super T,? extends U>, java.util.concurrent.Executor) ,public CompletableFuture<V> thenCombine(CompletionStage<? extends U>, BiFunction<? super T,? super U,? extends V>) ,public CompletableFuture<V> thenCombineAsync(CompletionStage<? extends U>, BiFunction<? super T,? super U,? extends V>) ,public CompletableFuture<V> thenCombineAsync(CompletionStage<? extends U>, BiFunction<? super T,? super U,? extends V>, java.util.concurrent.Executor) ,public CompletableFuture<U> thenCompose(Function<? super T,? extends CompletionStage<U>>) ,public CompletableFuture<U> thenComposeAsync(Function<? super T,? extends CompletionStage<U>>) ,public CompletableFuture<U> thenComposeAsync(Function<? super T,? extends CompletionStage<U>>, java.util.concurrent.Executor) ,public CompletableFuture<java.lang.Void> thenRun(java.lang.Runnable) ,public CompletableFuture<java.lang.Void> thenRunAsync(java.lang.Runnable) ,public CompletableFuture<java.lang.Void> thenRunAsync(java.lang.Runnable, java.util.concurrent.Executor) ,public CompletableFuture<T> toCompletableFuture() ,public java.lang.String toString() ,public CompletableFuture<T> whenComplete(BiConsumer<? super T,? super java.lang.Throwable>) ,public CompletableFuture<T> whenCompleteAsync(BiConsumer<? super T,? super java.lang.Throwable>) ,public CompletableFuture<T> whenCompleteAsync(BiConsumer<? super T,? super java.lang.Throwable>, java.util.concurrent.Executor) <variables>static final int ASYNC,private static final java.util.concurrent.Executor ASYNC_POOL,static final int NESTED,private static final java.lang.invoke.VarHandle NEXT,static final java.util.concurrent.CompletableFuture.AltResult NIL,private static final java.lang.invoke.VarHandle RESULT,private static final java.lang.invoke.VarHandle STACK,static final int SYNC,private static final boolean USE_COMMON_POOL,volatile java.lang.Object result,volatile java.util.concurrent.CompletableFuture.Completion stack