/*
# Licensed Materials - Property of IBM
# Copyright IBM Corp. 2016
*/
package com.ibm.streamsx.topology.internal.functional.ops;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import com.ibm.streams.flow.handlers.StreamHandler;
import com.ibm.streams.operator.OperatorContext;
import com.ibm.streams.operator.StreamingData.Punctuation;
class FunctionalQueue<T> implements StreamHandler<T>, Runnable {
private BlockingQueue<T> queue;
private final StreamHandler<T> handler;
private final Thread reader;
FunctionalQueue(OperatorContext context, int size, StreamHandler<T> handler) {
this.queue = new ArrayBlockingQueue<>(size);
this.handler = handler;
reader = context.getThreadFactory().newThread(this);
reader.setDaemon(false);
start();
}
@Override
public void run() {
while (!Thread.interrupted()) {
try {
T tuple = queue.take();
handler.tuple(tuple);
} catch (InterruptedException e) {
return;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
@Override
public synchronized void tuple(T tuple) throws Exception {
queue.put(tuple);
}
/**
* Ensure all tuples seen before the mark
* are processed before the mark.
*/
@Override
public void mark(Punctuation mark) throws Exception {
if (!queue.isEmpty()) {
List<T> drained = new ArrayList<T>(queue.size());
queue.drainTo(drained);
if (!drained.isEmpty()) {
for (T tuple : drained)
handler.tuple(tuple);
}
}
handler.mark(mark);
}
void start() {
reader.start();
}
void stop() {
reader.interrupt();
}
}