public boolean offer ( float value , long timeout , TimeUnit unit ) throws InterruptedException { // non volatile read ( which is quicker ) final int writeLocation = this . producerWriteLocation ; // sets the nextWriteLocation my moving it on by 1, this may cause it it wrap back to the start. final int nextWriteLocation = ( writeLocation + 1 == capacity ) ? 0 : writeLocation + 1 ; if ( nextWriteLocation == capacity - 1 ) { final long timeoutAt = System . nanoTime ( ) + unit . toNanos ( timeout ) ; while ( readLocation == 0 ) // this condition handles the case where writer has caught up with the read, // we will wait for a read, ( which will cause a change on the read location ) { if ( ! blockAtAdd ( timeoutAt ) ) return false ; } } else { final long timeoutAt = System . nanoTime ( ) + unit . toNanos ( timeout ) ; while ( nextWriteLocation == readLocation ) // this condition handles the case general case where the read is at the start of the backing array and we are at the end, // blocks as our backing array is full, we will wait for a read, ( which will cause a change on the read location ) { if ( ! blockAtAdd ( timeoutAt ) ) return false ; } } // purposely not volatile see the comment below data [ writeLocation ] = value ; // the line below, is where the write memory barrier occurs, // we have just written back the data in the line above ( which is not require to have a memory barrier as we will be doing that in the line below setWriteLocation ( nextWriteLocation ) ; return true ; }
Inserts the specified element into this queue waiting up to the specified wait time if necessary for space to become available .