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;
    }
public boolean offer ( float value , long timeout , TimeUnit unit ) throws InterruptedException { final int writeLocation = this . producerWriteLocation ; final int nextWriteLocation = ( writeLocation + 1 == capacity ) ? 0 : writeLocation + 1 ; if ( nextWriteLocation == capacity - 1 ) { final long timeoutAt = System . nanoTime ( ) + unit . toNanos ( timeout ) ; while ( readLocation == 0 ) { if ( ! blockAtAdd ( timeoutAt ) ) return false ; } } else { final long timeoutAt = System . nanoTime ( ) + unit . toNanos ( timeout ) ; while ( nextWriteLocation == readLocation ) { if ( ! blockAtAdd ( timeoutAt ) ) return false ; } } data [ writeLocation ] = value ; 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.

@param value   the element to add
@param timeout how long to wait before giving up, in units of <tt>unit</tt>
@param unit    a <tt>TimeUnit</tt> determining how to interpret the <tt>timeout</tt> parameter
@return <tt>true</tt> if successful, or <tt>false</tt> if the specified waiting time elapses before
space is available
@throws InterruptedException if interrupted while waiting