@CanIgnoreReturnValue
  @Override
  public V get(long timeout, TimeUnit unit)
      throws InterruptedException, TimeoutException, ExecutionException {
    // NOTE: if timeout < 0, remainingNanos will be < 0 and we will fall into the while(true) loop
    // at the bottom and throw a timeoutexception.
    long remainingNanos = unit.toNanos(timeout); // we rely on the implicit null check on unit.
    if (Thread.interrupted()) {
      throw new InterruptedException();
    }
    Object localValue = value;
    if (localValue != null & !(localValue instanceof AbstractFuture.SetFuture)) {
      return getDoneValue(localValue);
    }
    // we delay calling nanoTime until we know we will need to either park or spin
    final long endNanos = remainingNanos > 0 ? System.nanoTime() + remainingNanos : 0;
    long_wait_loop:
    if (remainingNanos >= SPIN_THRESHOLD_NANOS) {
      Waiter oldHead = waiters;
      if (oldHead != Waiter.TOMBSTONE) {
        Waiter node = new Waiter();
        do {
          node.setNext(oldHead);
          if (ATOMIC_HELPER.casWaiters(this, oldHead, node)) {
            while (true) {
              LockSupport.parkNanos(this, remainingNanos);
              // Check interruption first, if we woke up due to interruption we need to honor that.
              if (Thread.interrupted()) {
                removeWaiter(node);
                throw new InterruptedException();
              }

              // Otherwise re-read and check doneness. If we loop then it must have been a spurious
              // wakeup
              localValue = value;
              if (localValue != null & !(localValue instanceof AbstractFuture.SetFuture)) {
                return getDoneValue(localValue);
              }

              // timed out?
              remainingNanos = endNanos - System.nanoTime();
              if (remainingNanos < SPIN_THRESHOLD_NANOS) {
                // Remove the waiter, one way or another we are done parking this thread.
                removeWaiter(node);
                break long_wait_loop; // jump down to the busy wait loop
              }
            }
          }
          oldHead = waiters; // re-read and loop.
        } while (oldHead != Waiter.TOMBSTONE);
      }
      // re-read value, if we get here then we must have observed a TOMBSTONE while trying to add a
      // waiter.
      return getDoneValue(value);
    }
    // If we get here then we have remainingNanos < SPIN_THRESHOLD_NANOS and there is no node on the
    // waiters list
    while (remainingNanos > 0) {
      localValue = value;
      if (localValue != null & !(localValue instanceof AbstractFuture.SetFuture)) {
        return getDoneValue(localValue);
      }
      if (Thread.interrupted()) {
        throw new InterruptedException();
      }
      remainingNanos = endNanos - System.nanoTime();
    }
    throw new TimeoutException();
  }
@ CanIgnoreReturnValue @ Override public V get ( long timeout , TimeUnit unit ) throws InterruptedException , TimeoutException , ExecutionException { long remainingNanos = unit . toNanos ( timeout ) ; if ( Thread . interrupted ( ) ) { throw new InterruptedException ( ) ; } Object localValue = value ; if ( localValue != null & ! ( localValue instanceof AbstractFuture . SetFuture ) ) { return getDoneValue ( localValue ) ; } final long endNanos = remainingNanos > 0 ? System . nanoTime ( ) + remainingNanos : 0 ; long_wait_loop : if ( remainingNanos >= SPIN_THRESHOLD_NANOS ) { Waiter oldHead = waiters ; if ( oldHead != Waiter . TOMBSTONE ) { Waiter node = new Waiter ( ) ; do { node . setNext ( oldHead ) ; if ( ATOMIC_HELPER . casWaiters ( this , oldHead , node ) ) { while ( true ) { LockSupport . parkNanos ( this , remainingNanos ) ; if ( Thread . interrupted ( ) ) { removeWaiter ( node ) ; throw new InterruptedException ( ) ; } localValue = value ; if ( localValue != null & ! ( localValue instanceof AbstractFuture . SetFuture ) ) { return getDoneValue ( localValue ) ; } remainingNanos = endNanos - System . nanoTime ( ) ; if ( remainingNanos < SPIN_THRESHOLD_NANOS ) { removeWaiter ( node ) ; break long_wait_loop ; } } } oldHead = waiters ; } while ( oldHead != Waiter . TOMBSTONE ) ; } return getDoneValue ( value ) ; } while ( remainingNanos > 0 ) { localValue = value ; if ( localValue != null & ! ( localValue instanceof AbstractFuture . SetFuture ) ) { return getDoneValue ( localValue ) ; } if ( Thread . interrupted ( ) ) { throw new InterruptedException ( ) ; } remainingNanos = endNanos - System . nanoTime ( ) ; } throw new TimeoutException ( ) ; }
{@inheritDoc}

<p>The default {@link AbstractFuture} implementation throws {@code InterruptedException} if the
current thread is interrupted before or during the call, even if the value is already
available.

@throws InterruptedException if the current thread was interrupted before or during the call
(optional but recommended).
@throws CancellationException {@inheritDoc}