public boolean hasNext() {
if (!connected)
throw new IllegalStateException("Pipe not connected");
if (closedByConsumer)
throw new RiotException("Pipe closed");
if (finished)
return false;
consumerThread = Thread.currentThread();
// Depending on how code and/or the JVM schedules the threads involved
// there is a scenario that exists where a producer can finish/die
// before theconsumer is started and the consumer is scheduled onto the
// same thread thus resulting in a deadlock on the consumer because it
// will never be able to detect that the producer died
// In this scenario we need to set a special flag to indicate the
// possibility
if (producerThread != null && producerThread == consumerThread)
threadReused = true;
if (slot != null)
return true;
int attempts = 0;
while (true) {
attempts++;
try {
slot = queue.poll(this.pollTimeout, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
throw new CancellationException();
}
if (null != slot)
break;
// If the producer thread died and did not call finish() then
// declare this pipe to be "broken"
// Since check is after the break, we will drain as much as possible
// out of the queue before throwing this exception
if (threadReused || (producerThread != null && !producerThread.isAlive() && !closedByProducer)) {
closedByConsumer = true;
throw new RiotException("Producer dead");
}
// Need to check this inside the loop as otherwise outside code that
// attempts to break the deadlock by causing close() on the iterator
// cannot do so
if (closedByConsumer)
throw new RiotException("Pipe closed");
// Need to check whether polling attempts have been exceeded
// If so declare the producer dead and exit
if (attempts >= this.maxPolls) {
closedByConsumer = true;
if (producerThread != null) {
throw new RiotException(
"Producer failed to produce any data within the specified number of polling attempts, declaring producer dead");
} else {
throw new RiotException("Producer failed to ever call start(), declaring producer dead");
}
}
}
// When the end marker is seen set slot to null