package org.neo4j.smack.pipeline;
/**
* @author mh
* @since 27.11.11
*/
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicLong;
import com.lmax.disruptor.BusySpinWaitStrategy;
import com.lmax.disruptor.EventFactory;
import com.lmax.disruptor.ExceptionHandler;
import com.lmax.disruptor.MultiThreadedClaimStrategy;
import com.lmax.disruptor.RingBuffer;
import com.lmax.disruptor.SequenceBarrier;
import com.lmax.disruptor.Sequencer;
import com.lmax.disruptor.WorkHandler;
import com.lmax.disruptor.WorkProcessor;
public class RingBufferWorkPipeline<E> {
protected RingBuffer<E> ringBuffer;
private final ExceptionHandler exceptionHandler;
private List<WorkProcessor<E>> processors = new ArrayList<WorkProcessor<E>>();
private ExecutorService workers;
private final List<WorkHandler<E>> handlers = new ArrayList<WorkHandler<E>>();
private final EventFactory<E> eventFactory;
private String nameForThreads;
private int bufferSize;
public RingBufferWorkPipeline(String nameForThreads, final EventFactory<E> eventFactory, final ExceptionHandler exceptionHandler, int bufferSize) {
this.nameForThreads = nameForThreads;
this.eventFactory = eventFactory;
this.exceptionHandler = exceptionHandler;
this.bufferSize = bufferSize;
}
public void start() {
if (handlers.isEmpty()) throw new IllegalStateException("No Handlers configured on Pipeline");
final int numEventProcessors = handlers.size();
workers = Executors.newFixedThreadPool(numEventProcessors, new DaemonThreadFactory(nameForThreads));
ringBuffer = new RingBuffer<E>(
eventFactory,
new MultiThreadedClaimStrategy(bufferSize),
new BusySpinWaitStrategy());
WorkProcessor<E> processor = null;
for (WorkHandler<E> handler : handlers)
{
processor = scheduleEventProcessor(processor, handler);
processors.add(processor);
}
ringBuffer.setGatingSequences(processor.getSequence());
}
private WorkProcessor<E> scheduleEventProcessor(WorkProcessor<E> predecessor, WorkHandler<E> handler)
{
WorkProcessor<E> newProcessor = new WorkProcessor<E>(ringBuffer, barrierFor(predecessor), handler, exceptionHandler, newSequence());
workers.submit(newProcessor);
return newProcessor;
}
private SequenceBarrier barrierFor(WorkProcessor<E> predecessor) {
if (predecessor == null) return ringBuffer.newBarrier();
return ringBuffer.newBarrier(predecessor.getSequence());
}
private AtomicLong newSequence() {
return new AtomicLong(Sequencer.INITIAL_CURSOR_VALUE);
}
public void stop() {
for (WorkProcessor<E> processor : processors) {
processor.halt();
}
workers.shutdown();
}
public RingBuffer<E> getRingBuffer() {
return ringBuffer;
}
public void addHandler(WorkHandler<E> handler)
{
handlers.add(handler);
}
}