/** @see Sequencer#next(int) */
  @Override
  public long next(int n) {
    if (n < 1) {
      throw new IllegalArgumentException("n must be > 0");
    }

    long nextValue = pad.nextValue;

    long nextSequence = nextValue + n;
    long wrapPoint = nextSequence - bufferSize;
    long cachedGatingSequence = pad.cachedValue;

    if (wrapPoint > cachedGatingSequence || cachedGatingSequence > nextValue) {
      long minSequence;
      while (wrapPoint > (minSequence = Util.getMinimumSequence(gatingSequences, nextValue))) {
        Thread.yield();
        //                LockSupport.parkNanos(1L); // TODO: Use waitStrategy to spin?
      }

      pad.cachedValue = minSequence;
    }

    pad.nextValue = nextSequence;

    return nextSequence;
  }
Example #2
0
  @Test
  public void shouldWaitForWorkCompleteWhereAllWorkersAreBlockedOnRingBuffer() throws Exception {
    long expectedNumberMessages = 10;
    fillRingBuffer(expectedNumberMessages);

    final StubEventProcessor[] workers = new StubEventProcessor[3];
    for (int i = 0, size = workers.length; i < size; i++) {
      workers[i] = new StubEventProcessor();
      workers[i].setSequence(expectedNumberMessages - 1);
    }

    final SequenceBarrier sequenceBarrier = ringBuffer.newBarrier(Util.getSequencesFor(workers));

    Runnable runnable =
        new Runnable() {
          public void run() {
            long sequence = ringBuffer.next();
            StubEvent event = ringBuffer.getPreallocated(sequence);
            event.setValue((int) sequence);
            ringBuffer.publish(sequence);

            for (StubEventProcessor stubWorker : workers) {
              stubWorker.setSequence(sequence);
            }
          }
        };

    new Thread(runnable).start();

    long expectedWorkSequence = expectedNumberMessages;
    long completedWorkSequence = sequenceBarrier.waitFor(expectedNumberMessages);
    assertTrue(completedWorkSequence >= expectedWorkSequence);
  }
Example #3
0
  @Test
  public void shouldWaitForWorkCompleteWhereCompleteWorkThresholdIsBehind() throws Exception {
    long expectedNumberMessages = 10;
    fillRingBuffer(expectedNumberMessages);

    final StubEventProcessor[] eventProcessors = new StubEventProcessor[3];
    for (int i = 0, size = eventProcessors.length; i < size; i++) {
      eventProcessors[i] = new StubEventProcessor();
      eventProcessors[i].setSequence(expectedNumberMessages - 2);
    }

    final SequenceBarrier sequenceBarrier =
        ringBuffer.newBarrier(Util.getSequencesFor(eventProcessors));

    Runnable runnable =
        new Runnable() {
          public void run() {
            for (StubEventProcessor stubWorker : eventProcessors) {
              stubWorker.setSequence(stubWorker.getSequence().get() + 1L);
            }
          }
        };

    Thread thread = new Thread(runnable);
    thread.start();
    thread.join();

    long expectedWorkSequence = expectedNumberMessages - 1;
    long completedWorkSequence = sequenceBarrier.waitFor(expectedWorkSequence);
    assertTrue(completedWorkSequence >= expectedWorkSequence);
  }
  /** @see Sequencer#remainingCapacity() */
  @Override
  public long remainingCapacity() {
    long nextValue = pad.nextValue;

    long consumed = Util.getMinimumSequence(gatingSequences, nextValue);
    long produced = nextValue;
    return getBufferSize() - (produced - consumed);
  }
Example #5
0
 static {
   UNSAFE = Util.getUnsafe();
   try {
     VALUE_OFFSET = UNSAFE.objectFieldOffset(Value.class.getDeclaredField("value"));
   } catch (final Exception e) {
     throw new RuntimeException(e);
   }
 }
Example #6
0
  @Test
  public void shouldInterruptDuringBusySpin() throws Exception {
    final long expectedNumberMessages = 10;
    fillRingBuffer(expectedNumberMessages);

    final CountDownLatch latch = new CountDownLatch(3);
    final Sequence sequence1 = new CountDownLatchSequence(8L, latch);
    final Sequence sequence2 = new CountDownLatchSequence(8L, latch);
    final Sequence sequence3 = new CountDownLatchSequence(8L, latch);

    context.checking(
        new Expectations() {
          {
            one(eventProcessor1).getSequence();
            will(returnValue(sequence1));

            one(eventProcessor2).getSequence();
            will(returnValue(sequence2));

            one(eventProcessor3).getSequence();
            will(returnValue(sequence3));
          }
        });

    final SequenceBarrier sequenceBarrier =
        ringBuffer.newBarrier(
            Util.getSequencesFor(eventProcessor1, eventProcessor2, eventProcessor3));

    final boolean[] alerted = {false};
    Thread t =
        new Thread(
            new Runnable() {
              public void run() {
                try {
                  sequenceBarrier.waitFor(expectedNumberMessages - 1);
                } catch (AlertException e) {
                  alerted[0] = true;
                } catch (InterruptedException e) {
                  // don't care
                }
              }
            });

    t.start();
    latch.await(3, TimeUnit.SECONDS);
    sequenceBarrier.alert();
    t.join();

    assertTrue("Thread was not interrupted", alerted[0]);
  }
  /** @see Sequencer#hasAvailableCapacity(int) */
  @Override
  public boolean hasAvailableCapacity(final int requiredCapacity) {
    long nextValue = pad.nextValue;

    long wrapPoint = (nextValue + requiredCapacity) - bufferSize;
    long cachedGatingSequence = pad.cachedValue;

    if (wrapPoint > cachedGatingSequence || cachedGatingSequence > nextValue) {
      long minSequence = Util.getMinimumSequence(gatingSequences, nextValue);
      pad.cachedValue = minSequence;

      if (wrapPoint > minSequence) {
        return false;
      }
    }

    return true;
  }
Example #8
0
 public long remainingCapacity() {
   long l1 = Util.getMinimumSequence(this.gatingSequences);
   long l2 = this.cursor.get();
   return getBufferSize() - (l2 - l1);
 }