/* Copyright (c) 2013 Boundless and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Distribution License v1.0 * which accompanies this distribution, and is available at * https://www.eclipse.org/org/documents/edl-v10.html * * Contributors: * Gabriel Roldan (Boundless) - initial implementation */ package org.locationtech.geogig.osm.internal; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; import java.util.concurrent.TimeUnit; import javax.annotation.concurrent.ThreadSafe; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.base.Throwables; import com.google.common.collect.AbstractIterator; @ThreadSafe class QueueIterator<T> extends AbstractIterator<T> { private static final Logger LOGGER = LoggerFactory.getLogger(QueueIterator.class); private BlockingQueue<T> queue; private int timeout; private TimeUnit timeoutUnit; private volatile boolean finish; private boolean cancel; public QueueIterator(int queueCapacity, int timeout, TimeUnit timeoutUnit) { this.timeout = timeout; this.timeoutUnit = timeoutUnit; queue = new ArrayBlockingQueue<T>(queueCapacity); } public void cancel() { this.cancel = true; this.finish = true; this.queue.clear(); } public void noMoreInput() { this.finish = true; } public void put(T elem) { try { while (!finish && !cancel && !queue.offer(elem, timeout, timeoutUnit)) { LOGGER.debug("queue.offer timed out after {} {}. retrying...", timeout, timeoutUnit); } } catch (InterruptedException e) { throw Throwables.propagate(e); } } @Override protected T computeNext() { try { T next = null; while (!finish && !cancel && (next = queue.poll(timeout, timeoutUnit)) == null) { LOGGER.debug("queue.poll timed out after {} {}. retrying...", timeout, timeoutUnit); } if (cancel) { return endOfData(); } if (finish && next == null && !queue.isEmpty()) { next = queue.poll(timeout, timeoutUnit); } return next == null ? endOfData() : next; } catch (InterruptedException e) { return endOfData(); } } }