The issue is that for the items that fail the predicate need to be put back into the queue. This cannot be done better than we have here if we only have poll and add.

The better solution is to atomically swap the tail out with an empty queue, filter the existing items and push those failing the filter onto a new queue, then move into a phase of draining the tail. When the tail is drained, atomically swap the refilled queue with old location. I don't think this is needed for the case we are considering because there is only one thread processing input tuples and that is the same thread that will cass this dequeueAll. So, there is no (or little) concern with out-of-order issues.