Aside: This code assumes a class Option that can be Some or None to represent the presence (Some) or absence (None) of the value it contains. Haskell calls it Maybe.
Here is my first pass at wrapping Iterator in a thread-safe way:
public synchronized Option<T> nextBlocking() {
return iter.hasNext() ? Option.of(iter.next())
: Option.none();
}
I don't like that it's synchronized - it requires locking in order to work across multiple threads. On the other hand, if we remove the word synchronized
, one thread could call iter.hasNext()
which returns true (e.g. for the last item in the Iterator), then a second thread calls iter.next()
before the first thread does, using up that last item and causing the first thread to get a NoSuchElementException when it finally calls iter.next()
.
The following isn't going to win any object-oriented style points, but I think it mostly works around this issue in a non-blocking way:
public Option<T> nextNonBlocking() {
try {
return Option.of(iter.next());
} catch (NoSuchElementException nsee) {
if(iter.hasNext()) {
// Oops, exception was thrown for reason other than end-of-iterator.
// Rethrow that exception.
throw nsee;
}
}
return Option.none();
}
That could still fail if a nsee is thrown for some reason before end-of-iterator, then another thread reaches the true end-of-iterator before the first thread calls iter.hasNext(). While possible, this situation probably represents a coding failure in the underlying Iterable. It's very tempting to trade this tiny weakness for a non-blocking iterator wrapper.