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);
}
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);
}
}
}
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()));
}
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));
}
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()));
}
Aggregations