public boolean offer ( E o ) { /*log.fine("public boolean offer(E o): called");*/ /*log.fine("o = " + o);*/ // Ensure that the item to add is not null. if ( o == null ) { throw new IllegalArgumentException ( "The 'o' parameter may not be null." ) ; } // Derive the integer priority of the element using the priority function, shift it into this queues range if // necessary and adjust it to any offset caused by lowest priority not equal to zero. int level = priorityToLevel ( p . apply ( o ) ) ; /*log.fine("offer level = " + level);*/ // Create a new node to hold the new data element. Node < E > newNode = new DataNode < E > ( o , markers [ level + 1 ] ) ; // Add the element to the tail of the queue with matching level, looping until this can complete as an atomic // operation. while ( true ) { // Get tail and next ref. Would expect next ref to be null, but other thread may update it. Node < E > t = markers [ level + 1 ] . getTail ( ) ; Node < E > s = t . getNext ( ) ; /*log.fine("t = " + t);*/ /*log.fine("s = " + s);*/ // Recheck the tail ref, to ensure other thread has not already moved it. This can potentially prevent // a relatively expensive compare and set from failing later on, if another thread has already shited // the tail. if ( t == markers [ level + 1 ] . getTail ( ) ) { /*log.fine("t is still the tail.");*/ // Check that the next element reference on the tail is the tail marker, to confirm that another thread // has not updated it. Again, this may prevent a cas from failing later. if ( s == markers [ level + 1 ] ) { /*log.fine("s is the tail marker.");*/ // Try to join the new tail onto the old one. if ( t . casNext ( s , newNode ) ) { // The tail join was succesfull, so now update the queues tail reference. No conflict should // occurr here as the tail join was succesfull, so its just a question of updating the tail // reference. A compare and set is still used because ... markers [ level + 1 ] . casTail ( t , newNode ) ; // Increment the queue size count. count . incrementAndGet ( ) ; return true ; } } // Update the tail reference, other thread may also be doing the same. else { // Why bother doing this at all? I suppose, because another thread may be stalled and doing this // will enable this one to keep running. // Update the tail reference for the queue because another thread has already added a new tail // but not yet managed to update the tail reference. markers [ level + 1 ] . casTail ( t , s ) ; } } } }
Inserts the specified element onto the tail of this queue .