private void consumeBatchToCursor(long cursor, EventHandler<Object> handler) { for (long curr = _consumer.get() + 1; curr <= cursor; curr++) { try { MutableObject mo = _buffer.get(curr); Object o = mo.o; mo.setObject(null); if (o == FLUSH_CACHE) { Object c = null; while (true) { c = _cache.poll(); if (c == null) break; else handler.onEvent(c, curr, true); } } else if (o == INTERRUPT) { throw new InterruptedException("Disruptor processing interrupted"); } else { handler.onEvent(o, curr, curr == cursor); } } catch (Exception e) { throw new RuntimeException(e); } } // TODO: only set this if the consumer cursor has changed? _consumer.set(cursor); }
@Override public long waitFor( long sequence, Sequence cursor, Sequence dependentSequence, SequenceBarrier barrier) throws AlertException, InterruptedException { long availableSequence; long startTime = 0; int counter = SPIN_TRIES; do { if ((availableSequence = dependentSequence.get()) >= sequence) { return availableSequence; } if (0 == --counter) { if (0 == startTime) { startTime = System.nanoTime(); } else { long timeDelta = System.nanoTime() - startTime; if (timeDelta > yieldTimeoutNanos) { return lockingStrategy.waitOnLock(sequence, cursor, dependentSequence, barrier); } else if (timeDelta > spinTimeoutNanos) { Thread.yield(); } } counter = SPIN_TRIES; } } while (true); }
@Override public long waitOnLock( long sequence, Sequence cursorSequence, Sequence dependentSequence, SequenceBarrier barrier) throws AlertException, InterruptedException { long availableSequence; lock.lock(); try { while ((availableSequence = cursorSequence.get()) < sequence) { barrier.checkAlert(); processorNotifyCondition.await(); } } finally { lock.unlock(); } while ((availableSequence = dependentSequence.get()) < sequence) { barrier.checkAlert(); } return availableSequence; }
public void consumeBatchWhenAvailable(EventHandler<Object> handler) { try { final long nextSequence = _consumer.get() + 1; final long availableSequence = _barrier.waitFor(nextSequence, 10, TimeUnit.MILLISECONDS); if (availableSequence >= nextSequence) { consumeBatchToCursor(availableSequence, handler); } } catch (AlertException e) { throw new RuntimeException(e); } catch (InterruptedException e) { throw new RuntimeException(e); } }
/** * It is ok to have another thread rerun this method after a halt(). * * @throws IllegalStateException if this object instance is already running in a thread */ @Override public void run() { if (!running.compareAndSet(false, true)) { throw new IllegalStateException("Thread is already running"); } sequenceBarrier.clearAlert(); notifyStart(); T event = null; long nextSequence = sequence.get() + 1L; while (true) { try { final long availableSequence = sequenceBarrier.waitFor(nextSequence); while (nextSequence <= availableSequence) { event = dataProvider.get(nextSequence); eventHandler.onEvent(event, nextSequence, nextSequence == availableSequence); nextSequence++; } sequence.set(availableSequence); } catch (final TimeoutException e) { notifyTimeout(sequence.get()); } catch (final AlertException ex) { if (!running.get()) { break; } } catch (final Throwable ex) { exceptionHandler.handleEventException(ex, nextSequence, event); sequence.set(nextSequence); nextSequence++; } } notifyShutdown(); running.set(false); }
public long waitOnLock( final long sequence, Sequence cursorSequence, final Sequence dependentSequence, final SequenceBarrier barrier) throws AlertException, InterruptedException { long availableSequence; while ((availableSequence = dependentSequence.get()) < sequence) { LockSupport.parkNanos(1); } return availableSequence; }
public long readPos() { return _consumer.get(); }