Example #1
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 #2
0
  @Test
  public void shouldWaitForWorkCompleteWhereCompleteWorkThresholdIsAhead() throws Exception {
    final long expectedNumberMessages = 10;
    final long expectedWorkSequence = 9;
    fillRingBuffer(expectedNumberMessages);

    final Sequence sequence1 = new Sequence(expectedNumberMessages);
    final Sequence sequence2 = new Sequence(expectedWorkSequence);
    final Sequence sequence3 = new Sequence(expectedNumberMessages);

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

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

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

    SequenceBarrier sequenceBarrier =
        ringBuffer.newBarrier(
            eventProcessor1.getSequence(),
            eventProcessor2.getSequence(),
            eventProcessor3.getSequence());

    long completedWorkSequence = sequenceBarrier.waitFor(expectedWorkSequence);
    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);
  }
Example #4
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]);
  }
    @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;
    }
Example #6
0
  /**
   * 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);
  }
Example #7
0
  @Test
  public void shouldSetAndClearAlertStatus() {
    SequenceBarrier sequenceBarrier = ringBuffer.newBarrier();

    assertFalse(sequenceBarrier.isAlerted());

    sequenceBarrier.alert();
    assertTrue(sequenceBarrier.isAlerted());

    sequenceBarrier.clearAlert();
    assertFalse(sequenceBarrier.isAlerted());
  }
Example #8
0
 @Override
 public void halt() {
   running.set(false);
   sequenceBarrier.alert();
 }