TimeoutScheduler { public CompletableFuture<Void> whenTimedOut() { final TimeoutFuture whenTimedOut = this.whenTimedOut; if (whenTimedOut != null) { return whenTimedOut; } final TimeoutFuture timeoutFuture = new TimeoutFuture(); if (whenTimedOutUpdater.compareAndSet(this, null, timeoutFuture)) { return timeoutFuture; } else { return this.whenTimedOut; } } TimeoutScheduler(long timeoutNanos); void init(EventExecutor eventLoop, TimeoutTask timeoutTask, long initialTimeoutNanos); void clearTimeout(); void clearTimeout(boolean resetTimeout); void setTimeoutNanos(TimeoutMode mode, long timeoutNanos); void timeoutNow(); boolean isTimedOut(); long timeoutNanos(); CompletableFuture<Void> whenTimingOut(); CompletableFuture<Void> whenTimedOut(); @Nullable Long startTimeNanos();  }
@Test void whenTimedOut() { final AtomicReference<CompletableFuture<Void>> timeoutFutureRef = new AtomicReference<>(); executeInEventLoop(0, timeoutScheduler -> { final CompletableFuture<Void> timeoutFuture = timeoutScheduler.whenTimedOut(); assertThat(timeoutFuture).isNotDone(); timeoutScheduler.setTimeoutNanos(SET_FROM_NOW, MILLISECONDS.toNanos(1000)); timeoutFutureRef.set(timeoutFuture); }); timeoutFutureRef.get().join(); }