Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* The MIT License
*
* Copyright (c) 2009 The Broad Institute
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package picard.util;
import htsjdk.samtools.util.CloseableIterator;
import java.util.NoSuchElementException;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
/**
* Wrapper around a CloseableIterator that reads in a separate thread, for cases in which that might be
* efficient.
*/
public class AsyncIterator implements CloseableIterator {
private static volatile int threadsCreated = 0; // Just used for thread naming.
public static final int DEFAULT_QUEUE_SIZE = 2000;
private final AtomicBoolean isClosed = new AtomicBoolean(false);
private final BlockingQueue queue;
private final Thread reader;
private final ReaderRunnable readerRunnable;
private final AtomicReference ex = new AtomicReference(null);
private T theNext = null;
private final CloseableIterator underlyingIterator;
public AsyncIterator(final CloseableIterator underlyingIterator,
final int queueSize,
final String threadNamePrefix) {
this.underlyingIterator = underlyingIterator;
this.queue = new ArrayBlockingQueue(queueSize);
this.readerRunnable = new ReaderRunnable();
this.reader = new Thread(readerRunnable, threadNamePrefix + threadsCreated++);
this.reader.setDaemon(true);
this.reader.start();
getNext();
}
/**
* Set theNext to the next item to be returned, or null if there are no more items.
*/
private void getNext() {
assertOpen();
checkAndRethrow();
try {
theNext = null;
while (!this.queue.isEmpty() || !this.readerRunnable.isDone()) {
theNext = this.queue.poll(5, TimeUnit.SECONDS);
checkAndRethrow();
if (theNext != null) break;
}
} catch (InterruptedException ie) { throw new RuntimeException("Interrupted queueing item for writing.", ie); }
checkAndRethrow();
}
public boolean hasNext() {
assertOpen();
return theNext != null;
}
public T next() {
assertOpen();
if (!hasNext()) throw new NoSuchElementException();
final T ret = theNext;
getNext();
return ret;
}
public void remove() {
throw new UnsupportedOperationException();
}
/**
* Stops the thread and then calls synchronouslyClose() to allow implementation to do any one time clean up.
*/
public void close() {
checkAndRethrow();
assertOpen();
this.isClosed.set(true);
try { this.reader.join(); }
catch (InterruptedException ie) { throw new RuntimeException("Interrupted waiting on reader thread.", ie); }
underlyingIterator.close();
checkAndRethrow();
this.queue.clear();
}
private void assertOpen() {
if (this.isClosed.get()) {
throw new RuntimeException("AsyncIterator already closed.");
}
}
/**
* Checks to see if an exception has been raised in the reader thread and if so rethrows it as an Error
* or RuntimeException as appropriate.
*/
private void checkAndRethrow() {
final Throwable t = this.ex.get();
if (t != null) {
if (t instanceof Error) throw (Error) t;
if (t instanceof RuntimeException) throw (RuntimeException) t;
else throw new RuntimeException(t);
}
}
/**
* Small Runnable implementation that simply reads from underlying iterator and stores on the blocking queue.
*/
private class ReaderRunnable implements Runnable {
private final AtomicBoolean readerDone = new AtomicBoolean(false);
public boolean isDone() { return readerDone.get(); }
public void run() {
try {
boolean isEof = false;
while (!isClosed.get() && !isEof) {
try {
if (!underlyingIterator.hasNext()) {
isEof = true;
} else {
final T item = underlyingIterator.next();
// Keep trying to put item on the queue unless close() has been called.
while (!isClosed.get() && !queue.offer(item, 2, TimeUnit.SECONDS)) {
}
}
}
catch (InterruptedException ie) {
/* Do Nothing */
}
}
}
catch (Throwable t) {
ex.compareAndSet(null, t);
} finally {
readerDone.set(true);
}
}
}
}