@Test public void shouldIndicateNoAvailableCapacity() { sequencer.addGatingSequences(gatingSequence); long sequence = sequencer.next(BUFFER_SIZE); sequencer.publish(sequence - (BUFFER_SIZE - 1), sequence); assertFalse(sequencer.hasAvailableCapacity(1)); }
/** * Resets the cursor to a specific value. This can be applied at any time, but it is worth not that it is a racy thing to do and should only be used in * controlled circumstances. E.g. during initialisation. * * @param sequence The sequence to reset too. * @throws IllegalStateException If any gating sequences have already been specified. */ public void resetTo(long sequence) { sequencer.claim(sequence); sequencer.publish(sequence); }
RingBufferFields( EventFactory<E> eventFactory, Sequencer sequencer) { this.sequencer = sequencer; this.bufferSize = sequencer.getBufferSize(); if (bufferSize < 1) { throw new IllegalArgumentException("bufferSize must not be less than 1"); } if (Integer.bitCount(bufferSize) != 1) { throw new IllegalArgumentException("bufferSize must be a power of 2"); } this.indexMask = bufferSize - 1; this.entries = new Object[sequencer.getBufferSize() + 2 * BUFFER_PAD]; fill(eventFactory); }
@Test(expected = InsufficientCapacityException.class) public void shouldThrowInsufficientCapacityExceptionWhenSequencerIsFull() throws Exception { sequencer.addGatingSequences(gatingSequence); for (int i = 0; i < BUFFER_SIZE; i++) { sequencer.next(); } sequencer.tryNext(); }
@Test public void shouldHoldUpPublisherWhenBufferIsFull() throws InterruptedException { sequencer.addGatingSequences(gatingSequence); long sequence = sequencer.next(BUFFER_SIZE); sequencer.publish(sequence - (BUFFER_SIZE - 1), sequence); final CountDownLatch waitingLatch = new CountDownLatch(1); final CountDownLatch doneLatch = new CountDownLatch(1); final long expectedFullSequence = Sequencer.INITIAL_CURSOR_VALUE + sequencer.getBufferSize(); assertThat(sequencer.getCursor(), is(expectedFullSequence)); executor.submit( new Runnable() { @Override public void run() { waitingLatch.countDown(); long next = sequencer.next(); sequencer.publish(next); doneLatch.countDown(); } }); waitingLatch.await(); assertThat(sequencer.getCursor(), is(expectedFullSequence)); gatingSequence.set(Sequencer.INITIAL_CURSOR_VALUE + 1L); doneLatch.await(); assertThat(sequencer.getCursor(), is(expectedFullSequence + 1L)); }
/** * The same functionality as {@link RingBuffer#next()}, but allows the caller to claim * the next n sequences. * * @param n number of slots to claim * @return sequence number of the highest slot claimed * @see Sequencer#next(int) */ @Override public long next(int n) { return sequencer.next(n); }
@Test public void shouldCalculateRemainingCapacity() throws Exception { sequencer.addGatingSequences(gatingSequence); assertThat(sequencer.remainingCapacity(), is((long) BUFFER_SIZE)); for (int i = 1; i < BUFFER_SIZE; i++) { sequencer.next(); assertThat(sequencer.remainingCapacity(), is((long) BUFFER_SIZE - i)); } }
@Test public void shouldTryNext() throws Exception { sequencer.addGatingSequences(gatingSequence); for (int i = 0; i < BUFFER_SIZE; i++) { sequencer.publish(sequencer.tryNext()); } try { sequencer.tryNext(); fail("Should of thrown: " + InsufficientCapacityException.class.getSimpleName()); } catch (InsufficientCapacityException e) { // No-op } }
@Test public void shouldNotBeAvailableUntilPublished() throws Exception { long next = sequencer.next(6); for (int i = 0; i <= 5; i++) { assertThat(sequencer.isAvailable(i), is(false)); } sequencer.publish(next - (6 - 1), next); for (int i = 0; i <= 5; i++) { assertThat(sequencer.isAvailable(i), is(true)); } assertThat(sequencer.isAvailable(6), is(false)); }
final long availableSequence = sequencer.getHighestPublishedSequence(nextSequence, gatingSequence.get()); else if (sequencer.getCursor() >= nextSequence)
/** * Publish the specified sequence. This action marks this particular * message as being available to be read. * * @param sequence the sequence to publish. */ @Override public void publish(long sequence) { sequencer.publish(sequence); }
@Test public void shouldWaitOnPublication() throws Exception { SequenceBarrier barrier = sequencer.newBarrier(); long next = sequencer.next(10); long lo = next - (10 - 1); long mid = next - 5; for (long l = lo; l < mid; l++) { sequencer.publish(l); } assertThat(barrier.waitFor(-1), is(mid - 1)); for (long l = mid; l <= next; l++) { sequencer.publish(l); } assertThat(barrier.waitFor(-1), is(next)); }
@Test public void shouldOnlyAllowMessagesToBeAvailableIfSpecificallyPublished() throws Exception { publisher.publish(3); publisher.publish(5); assertThat(publisher.isAvailable(0), is(false)); assertThat(publisher.isAvailable(1), is(false)); assertThat(publisher.isAvailable(2), is(false)); assertThat(publisher.isAvailable(3), is(true)); assertThat(publisher.isAvailable(4), is(false)); assertThat(publisher.isAvailable(5), is(true)); assertThat(publisher.isAvailable(6), is(false)); } }
/** * Add the specified gating sequences to this instance of the Disruptor. They will * safely and atomically added to the list of gating sequences. * * @param gatingSequences The sequences to add. */ public void addGatingSequences(Sequence... gatingSequences) { sequencer.addGatingSequences(gatingSequences); }
/** * Sets the cursor to a specific sequence and returns the preallocated entry that is stored there. This * can cause a data race and should only be done in controlled circumstances, e.g. during initialisation. * * @param sequence The sequence to claim. * @return The preallocated event. */ public E claimAndGetPreallocated(long sequence) { sequencer.claim(sequence); return get(sequence); }
/** * Get the remaining capacity for this ringBuffer. * * @return The number of slots remaining. */ public long remainingCapacity() { return sequencer.remainingCapacity(); }
/** * Create a new SequenceBarrier to be used by an EventProcessor to track which messages * are available to be read from the ring buffer given a list of sequences to track. * * @param sequencesToTrack the additional sequences to track * @return A sequence barrier that will track the specified sequences. * @see SequenceBarrier */ public SequenceBarrier newBarrier(Sequence... sequencesToTrack) { return sequencer.newBarrier(sequencesToTrack); }
/** * Get the current cursor value for the ring buffer. The actual value received * will depend on the type of {@link Sequencer} that is being used. * * @see MultiProducerSequencer * @see SingleProducerSequencer */ @Override public long getCursor() { return sequencer.getCursor(); }