package org.enumerable.lambda.enumerable.jruby;
import static java.lang.System.*;
import static java.util.Arrays.*;
import static org.enumerable.lambda.exception.UncheckedException.*;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import org.enumerable.lambda.weaving.Debug;
import org.jruby.threading.DaemonThreadFactory;
public abstract class QueueIterator implements Iterator<Object>, Runnable {
static boolean debug = Debug.debug;
static final int LOST_INTEREST_TIME_OUT = 500;
Executor e = Executors.newCachedThreadPool(new DaemonThreadFactory());
Object endOfQueue = "<End of Queue>";
Object noElement = "<No Element>";
Object nullElement = "<Null>";
RuntimeException[] exception = new RuntimeException[1];
BlockingQueue<Object> yieldQueue = new ArrayBlockingQueue<Object>(1);
Object current = noElement;
boolean started;
Object nextElementRequest = "<Next Element Request>";
BlockingQueue<Object> requestQueue = new ArrayBlockingQueue<Object>(1);
@SuppressWarnings("serial")
class LostInterestException extends RuntimeException {
}
public void run() {
started = true;
try {
debug("waiting for next request");
if (null == requestQueue.poll(LOST_INTEREST_TIME_OUT, TimeUnit.MILLISECONDS))
throw new LostInterestException();
iterate();
yieldQueue.offer(endOfQueue, LOST_INTEREST_TIME_OUT, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
uncheck(e);
} catch (LostInterestException e) {
current = endOfQueue;
debug("client lost interest");
} catch (RuntimeException e) {
try {
exception[0] = e;
yieldQueue.put(exception);
} catch (InterruptedException e1) {
throw uncheck(e1);
}
}
}
public void debug(String msg) {
if (debug)
out.println(msg);
}
public boolean hasNext() {
try {
if (!started)
e.execute(this);
if (current == endOfQueue)
return false;
debug("requesting element");
requestQueue.offer(nextElementRequest);
current = yieldQueue.take();
if (current == nullElement)
current = null;
debug("got element");
return current != endOfQueue;
} catch (InterruptedException e) {
throw uncheck(e);
}
}
public Object next() {
if (current == noElement)
hasNext();
if (current == exception)
throw exception[0];
if (current == endOfQueue)
throw new NoSuchElementException();
Object result = current;
current = noElement;
return result;
}
public void remove() {
throw new UnsupportedOperationException();
}
public void enque(Object o) throws InterruptedException {
debug("offering element");
if (o == null)
o = nullElement;
if (!yieldQueue.offer(o, LOST_INTEREST_TIME_OUT, TimeUnit.MILLISECONDS))
throw new LostInterestException();
debug("waiting for next request");
if (null == requestQueue.poll(LOST_INTEREST_TIME_OUT, TimeUnit.MILLISECONDS))
throw new LostInterestException();
}
public abstract void iterate() throws InterruptedException;
public static class QueueIterable implements Iterable<Object> {
QueueIterator iterator;
public QueueIterable(QueueIterator iterator) {
this.iterator = iterator;
}
public Iterator<Object> iterator() {
return iterator;
}
}
public static void main(String[] args) {
final Iterable<? extends Object> iterable = asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
class ForLoopQIterator extends QueueIterator {
public void iterate() throws InterruptedException {
for (Object o : iterable)
enque(o);
}
}
for (Iterator<?> i = new ForLoopQIterator(); i.hasNext();) {
Object next = i.next();
System.out.println(next);
if (next == (Integer) 5)
break;
}
QueueIterator i = new ForLoopQIterator();
try {
while (true)
System.out.println(i.next());
} catch (NoSuchElementException done) {
}
for (Object o : new QueueIterable(new ForLoopQIterator())) {
System.out.println(o);
if (o == (Integer) 5)
break;
}
}
}