/* The MIT License (MIT)
* Copyright (c) 2014 Nicholas Wright
* http://opensource.org/licenses/MIT
*/
package com.github.dozedoff.commonj.io;
import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.LinkedBlockingQueue;
public abstract class DataProducer<I, O> {
protected LinkedBlockingQueue<I> input = new LinkedBlockingQueue<>();
protected LinkedBlockingQueue<O> output = new LinkedBlockingQueue<>();
private LinkedList<DataLoader> loaders = new LinkedList<>();
private int threadPriority = Thread.NORM_PRIORITY;
public DataProducer() {
startLoader();
}
public DataProducer(int outputQueueMaxSize) {
output = new LinkedBlockingQueue<>(outputQueueMaxSize);
startLoader();
}
public DataProducer(int inputQueueMaxSize, int outputQueueMaxSize) {
input = new LinkedBlockingQueue<>(inputQueueMaxSize);
output = new LinkedBlockingQueue<>(outputQueueMaxSize);
startLoader();
}
public final void startLoader() {
startLoader(1);
}
public void setThreadPriority(int priority) {
threadPriority = priority;
for (Thread t : loaders) {
t.setPriority(threadPriority);
}
}
public void startLoader(int numberOfLoaders) {
for (int i = 0; i < numberOfLoaders; i++) {
DataLoader loader = new DataLoader();
loaders.add(loader);
loader.setDaemon(true);
loader.setPriority(threadPriority);
loader.start();
}
}
public void stopLoader() {
stopLoader(1);
}
public void stopLoader(int numberOfLoaders) {
for (int i = 0; i < numberOfLoaders; i++) {
if (loaders.size() > 1) {
DataLoader loader = loaders.removeLast();
loader.interrupt();
}
}
}
public void clear() {
input.clear();
output.clear();
outputQueueChanged();
}
public void addToLoad(@SuppressWarnings("unchecked") I... paths) {
List<I> list = Arrays.asList(paths);
input.addAll(list);
}
public void offer(I input) {
this.input.offer(input);
}
public void addToLoad(List<I> paths) {
input.addAll(paths);
}
public O takeData() throws InterruptedException {
O take = output.take();
outputQueueChanged();
return take;
}
public void drainTo(Collection<O> drainTo, int maxElements) throws InterruptedException {
output.drainTo(drainTo, maxElements);
outputQueueChanged();
}
public int availableWork() {
return output.size();
}
public boolean hasWork() {
return (!input.isEmpty()) || (!output.isEmpty());
}
abstract protected void loaderDoWork() throws InterruptedException;
protected void outputQueueChanged() {
};
class DataLoader extends Thread {
public DataLoader() {
this.setName("Data loader");
}
@Override
public void run() {
while (!isInterrupted()) {
try {
loaderDoWork();
outputQueueChanged();
} catch (InterruptedException e) {
interrupt();
}
}
}
}
}