Search in sources :

Example 1 with TerminalNotification

use of io.servicetalk.concurrent.internal.TerminalNotification in project servicetalk by apple.

the class ConnectablePayloadWriter method processClosed.

private void processClosed() throws IOException {
    TerminalNotification currClosed = closed;
    assert currClosed != null;
    processClosed(currClosed);
}
Also used : TerminalNotification(io.servicetalk.concurrent.internal.TerminalNotification)

Example 2 with TerminalNotification

use of io.servicetalk.concurrent.internal.TerminalNotification in project servicetalk by apple.

the class ConnectablePayloadWriter method close0.

private void close0(@Nullable Throwable cause) {
    // Set closed before state, because the Subscriber thread depends upon this ordering in the event it needs to
    // terminate the Subscriber.
    TerminalNotification terminal = cause == null ? complete() : error(cause);
    if (closedUpdater.compareAndSet(this, null, terminal)) {
        // We need to terminate requested or else we may block indefinitely on subsequent calls to write in
        // waitForRequestNDemand.
        requested = REQUESTN_TERMINATED;
        for (; ; ) {
            final Object currState = state;
            if (currState instanceof Subscriber) {
                if (stateUpdater.compareAndSet(this, currState, State.TERMINATED)) {
                    terminal.terminate((Subscriber<?>) currState);
                    break;
                }
            } else if (currState == State.TERMINATED || stateUpdater.compareAndSet(this, currState, State.TERMINATING)) {
                assert currState != State.WAITING_FOR_CONNECTED;
                break;
            }
        }
    } else {
        Object currState = stateUpdater.getAndSet(this, State.TERMINATED);
        if (currState instanceof Subscriber) {
            final TerminalNotification currClosed = closed;
            assert currClosed != null;
            currClosed.terminate((Subscriber<?>) currState);
        }
    }
}
Also used : Subscriber(io.servicetalk.concurrent.PublisherSource.Subscriber) TerminalNotification(io.servicetalk.concurrent.internal.TerminalNotification)

Example 3 with TerminalNotification

use of io.servicetalk.concurrent.internal.TerminalNotification in project servicetalk by apple.

the class PublisherBufferTest method subscriberThrowsFromOnNext.

@Test
void subscriberThrowsFromOnNext() {
    TestPublisher<Integer> tPublisher = new TestPublisher.Builder<Integer>().disableAutoOnSubscribe().build();
    TestPublisher<Accumulator<Integer, Integer>> bPublisher = new TestPublisher.Builder<Accumulator<Integer, Integer>>().disableAutoOnSubscribe().build();
    TestSubscription tSubscription = new TestSubscription();
    TestSubscription bSubscription = new TestSubscription();
    AtomicReference<TerminalNotification> terminal = new AtomicReference<>();
    AtomicInteger onNextCounter = new AtomicInteger();
    toSource(tPublisher.buffer(new TestBufferStrategy(bPublisher, BUFFER_SIZE_HINT))).subscribe(new Subscriber<Integer>() {

        @Override
        public void onSubscribe(Subscription s) {
            s.request(MAX_VALUE);
        }

        @Override
        public void onNext(@Nullable Integer integer) {
            onNextCounter.incrementAndGet();
            throw DELIBERATE_EXCEPTION;
        }

        @Override
        public void onError(Throwable t) {
            terminal.set(error(t));
        }

        @Override
        public void onComplete() {
            terminal.set(complete());
        }
    });
    assertThat(tPublisher.isSubscribed(), is(true));
    tPublisher.onSubscribe(tSubscription);
    assertThat(bPublisher.isSubscribed(), is(true));
    bPublisher.onSubscribe(bSubscription);
    assertThat(tSubscription.requested(), is(0L));
    assertThat(bSubscription.requested(), is(MAX_VALUE));
    bPublisher.onNext(new SumAccumulator());
    assertThat((int) tSubscription.requested(), is(BUFFER_SIZE_HINT));
    tPublisher.onNext(1);
    bPublisher.onNext(new SumAccumulator());
    assertThat(onNextCounter.get(), is(1));
    assertThat(terminal.get().cause(), is(DELIBERATE_EXCEPTION));
    verifyCancelled(tSubscription);
    // Verify that further items are ignored
    terminal.set(null);
    tPublisher.onNext(2);
    bPublisher.onNext(new SumAccumulator());
    tPublisher.onComplete();
    assertThat(onNextCounter.get(), is(1));
    assertThat(terminal.get(), is(nullValue()));
}
Also used : Accumulator(io.servicetalk.concurrent.api.BufferStrategy.Accumulator) TerminalNotification(io.servicetalk.concurrent.internal.TerminalNotification) AtomicReference(java.util.concurrent.atomic.AtomicReference) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) DelayedSubscription(io.servicetalk.concurrent.internal.DelayedSubscription) Subscription(io.servicetalk.concurrent.PublisherSource.Subscription) Test(org.junit.jupiter.api.Test) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest)

Example 4 with TerminalNotification

use of io.servicetalk.concurrent.internal.TerminalNotification in project servicetalk by apple.

the class PublisherBufferTest method originalSourceIsRetriedIfSubscriberThrows.

@Test
void originalSourceIsRetriedIfSubscriberThrows() {
    TestPublisher<Accumulator<Integer, Integer>> bPublisher = new TestPublisher<>();
    DelayedSubscription bSubscription = new DelayedSubscription();
    AtomicReference<TerminalNotification> terminal = new AtomicReference<>();
    BlockingQueue<Integer> items = new LinkedBlockingDeque<>();
    BlockingQueue<Integer> buffers = new LinkedBlockingDeque<>();
    AtomicInteger counter = new AtomicInteger();
    toSource(defer(() -> from(counter.incrementAndGet())).whenOnNext(items::add).retry((i, t) -> i < 3 && t == DELIBERATE_EXCEPTION).buffer(new TestBufferStrategy(bPublisher, 1))).subscribe(new Subscriber<Integer>() {

        @Override
        public void onSubscribe(Subscription s) {
            bSubscription.delayedSubscription(s);
            bSubscription.request(1);
        }

        @Override
        public void onNext(@Nullable Integer integer) {
            assert integer != null;
            buffers.add(integer);
            throw DELIBERATE_EXCEPTION;
        }

        @Override
        public void onError(Throwable t) {
            terminal.set(error(t));
        }

        @Override
        public void onComplete() {
            terminal.set(complete());
        }
    });
    // it will generate a new boundary on each accumulation
    bPublisher.onNext(new SumAccumulator(bPublisher));
    assertThat(items, hasSize(1));
    assertThat(items, contains(1));
    assertThat(buffers, hasSize(1));
    assertThat(buffers, contains(1));
    bSubscription.request(MAX_VALUE);
    assertThat(items, hasSize(3));
    assertThat(items, contains(1, 2, 3));
    assertThat(buffers, hasSize(3));
    assertThat(buffers, contains(1, 2, 3));
    assertThat(terminal.get().cause(), is(DELIBERATE_EXCEPTION));
}
Also used : Accumulator(io.servicetalk.concurrent.api.BufferStrategy.Accumulator) Publisher.never(io.servicetalk.concurrent.api.Publisher.never) TerminalNotification.complete(io.servicetalk.concurrent.internal.TerminalNotification.complete) MAX_VALUE(java.lang.Long.MAX_VALUE) AtomicReference(java.util.concurrent.atomic.AtomicReference) Subscriber(io.servicetalk.concurrent.PublisherSource.Subscriber) TerminalNotification(io.servicetalk.concurrent.internal.TerminalNotification) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Matchers.nullValue(org.hamcrest.Matchers.nullValue) DelayedSubscription(io.servicetalk.concurrent.internal.DelayedSubscription) Matchers.hasSize(org.hamcrest.Matchers.hasSize) MatcherAssert.assertThat(org.hamcrest.MatcherAssert.assertThat) Publisher.from(io.servicetalk.concurrent.api.Publisher.from) DELIBERATE_EXCEPTION(io.servicetalk.concurrent.internal.DeliberateException.DELIBERATE_EXCEPTION) Publisher.defer(io.servicetalk.concurrent.api.Publisher.defer) Nullable(javax.annotation.Nullable) Accumulator(io.servicetalk.concurrent.api.BufferStrategy.Accumulator) ValueSource(org.junit.jupiter.params.provider.ValueSource) TestPublisherSubscriber(io.servicetalk.concurrent.test.internal.TestPublisherSubscriber) Matchers.empty(org.hamcrest.Matchers.empty) BlockingQueue(java.util.concurrent.BlockingQueue) MILLISECONDS(java.util.concurrent.TimeUnit.MILLISECONDS) Subscription(io.servicetalk.concurrent.PublisherSource.Subscription) SourceAdapters.toSource(io.servicetalk.concurrent.api.SourceAdapters.toSource) TerminalNotification.error(io.servicetalk.concurrent.internal.TerminalNotification.error) Test(org.junit.jupiter.api.Test) Matchers.instanceOf(org.hamcrest.Matchers.instanceOf) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest) Matchers.contains(org.hamcrest.Matchers.contains) Matchers.sameInstance(org.hamcrest.Matchers.sameInstance) Matcher(org.hamcrest.Matcher) LinkedBlockingDeque(java.util.concurrent.LinkedBlockingDeque) Matchers.is(org.hamcrest.Matchers.is) LinkedBlockingDeque(java.util.concurrent.LinkedBlockingDeque) TerminalNotification(io.servicetalk.concurrent.internal.TerminalNotification) AtomicReference(java.util.concurrent.atomic.AtomicReference) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) DelayedSubscription(io.servicetalk.concurrent.internal.DelayedSubscription) DelayedSubscription(io.servicetalk.concurrent.internal.DelayedSubscription) Subscription(io.servicetalk.concurrent.PublisherSource.Subscription) Test(org.junit.jupiter.api.Test) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest)

Example 5 with TerminalNotification

use of io.servicetalk.concurrent.internal.TerminalNotification in project servicetalk by apple.

the class PublisherBufferTest method subscriberThrowsFromOnNextBeforeTermination.

@Test
void subscriberThrowsFromOnNextBeforeTermination() {
    TestPublisher<Integer> tPublisher = new TestPublisher<>();
    TestPublisher<Accumulator<Integer, Integer>> bPublisher = new TestPublisher<>();
    TestSubscription bSubscription = new TestSubscription();
    AtomicReference<TerminalNotification> terminal = new AtomicReference<>();
    AtomicInteger onNextCounter = new AtomicInteger();
    toSource(tPublisher.buffer(new TestBufferStrategy(bPublisher, BUFFER_SIZE_HINT))).subscribe(new Subscriber<Integer>() {

        @Override
        public void onSubscribe(Subscription s) {
            s.request(MAX_VALUE);
        }

        @Override
        public void onNext(@Nullable Integer integer) {
            onNextCounter.incrementAndGet();
            throw DELIBERATE_EXCEPTION;
        }

        @Override
        public void onError(Throwable t) {
            terminal.set(error(t));
        }

        @Override
        public void onComplete() {
            terminal.set(complete());
        }
    });
    assertThat(bPublisher.isSubscribed(), is(true));
    bPublisher.onSubscribe(bSubscription);
    assertThat(bSubscription.requested(), is(MAX_VALUE));
    bPublisher.onNext(new SumAccumulator());
    tPublisher.onNext(1);
    tPublisher.onComplete();
    assertThat(onNextCounter.get(), is(1));
    assertThat(terminal.get().cause(), is(DELIBERATE_EXCEPTION));
    verifyCancelled(bSubscription);
    // Verify that further items are ignored
    terminal.set(null);
    tPublisher.onNext(2);
    bPublisher.onNext(new SumAccumulator());
    tPublisher.onComplete();
    assertThat(onNextCounter.get(), is(1));
    assertThat(terminal.get(), is(nullValue()));
}
Also used : Accumulator(io.servicetalk.concurrent.api.BufferStrategy.Accumulator) TerminalNotification(io.servicetalk.concurrent.internal.TerminalNotification) AtomicReference(java.util.concurrent.atomic.AtomicReference) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) DelayedSubscription(io.servicetalk.concurrent.internal.DelayedSubscription) Subscription(io.servicetalk.concurrent.PublisherSource.Subscription) Test(org.junit.jupiter.api.Test) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest)

Aggregations

TerminalNotification (io.servicetalk.concurrent.internal.TerminalNotification)12 Subscription (io.servicetalk.concurrent.PublisherSource.Subscription)7 AtomicReference (java.util.concurrent.atomic.AtomicReference)7 Test (org.junit.jupiter.api.Test)6 DelayedSubscription (io.servicetalk.concurrent.internal.DelayedSubscription)5 LinkedBlockingDeque (java.util.concurrent.LinkedBlockingDeque)5 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)5 Nullable (javax.annotation.Nullable)5 ParameterizedTest (org.junit.jupiter.params.ParameterizedTest)5 Accumulator (io.servicetalk.concurrent.api.BufferStrategy.Accumulator)4 Buffer (io.servicetalk.buffer.api.Buffer)2 PublisherSource (io.servicetalk.concurrent.PublisherSource)2 Subscriber (io.servicetalk.concurrent.PublisherSource.Subscriber)2 LegacyTestSingle (io.servicetalk.concurrent.api.LegacyTestSingle)2 TestSubscription (io.servicetalk.concurrent.api.TestSubscription)2 StreamingHttpResponse (io.servicetalk.http.api.StreamingHttpResponse)2 Matchers.emptyIterable (org.hamcrest.Matchers.emptyIterable)2 Publisher.defer (io.servicetalk.concurrent.api.Publisher.defer)1 Publisher.from (io.servicetalk.concurrent.api.Publisher.from)1 Publisher.never (io.servicetalk.concurrent.api.Publisher.never)1