private int awaitDone ( boolean timed , long nanos ) throws InterruptedException { // The code below is very delicate, to achieve these goals: // - call nanoTime exactly once for each call to park // - if nanos <= 0L, return promptly without allocation or nanoTime // - if nanos == Long.MIN_VALUE, don't underflow // - if nanos == Long.MAX_VALUE, and nanoTime is non-monotonic // and we suffer a spurious wakeup, we will do no worse than // to park-spin for a while long startTime = 0L ; // Special value 0L means not yet parked WaitNode q = null ; boolean queued = false ; for ( ; ; ) { int s = state ; if ( s > COMPLETING ) { if ( q != null ) q . thread = null ; return s ; } else if ( s == COMPLETING ) // We may have already promised (via isDone) that we are done // so never return empty-handed or throw InterruptedException Thread . yield ( ) ; else if ( Thread . interrupted ( ) ) { removeWaiter ( q ) ; throw new InterruptedException ( ) ; } else if ( q == null ) { if ( timed && nanos <= 0L ) return s ; q = new WaitNode ( ) ; } else if ( ! queued ) queued = U . compareAndSwapObject ( this , WAITERS , q . next = waiters , q ) ; else if ( timed ) { final long parkNanos ; if ( startTime == 0L ) { // first time startTime = System . nanoTime ( ) ; if ( startTime == 0L ) startTime = 1L ; parkNanos = nanos ; } else { long elapsed = System . nanoTime ( ) - startTime ; if ( elapsed >= nanos ) { removeWaiter ( q ) ; return state ; } parkNanos = nanos - elapsed ; } // nanoTime may be slow; recheck before parking if ( state < COMPLETING ) LockSupport . parkNanos ( this , parkNanos ) ; } else LockSupport . park ( this ) ; } }
Awaits completion or aborts on interrupt or timeout .