Search in sources :

Example 1 with Subscription

use of io.servicetalk.concurrent.PublisherSource.Subscription in project servicetalk by apple.

the class ConnectableBufferOutputStreamTest method multiThreadedProducerConsumer.

@Test
void multiThreadedProducerConsumer() throws Exception {
    final Random r = new Random();
    // capture seed to have repeatable tests
    final long seed = r.nextLong();
    r.setSeed(seed);
    // 3% of heap or max of 100 MiB
    final int dataSize = (int) min(getRuntime().maxMemory() * 0.03, 100 * 1024 * 1024);
    LOGGER.info("Test seed = {} – data size = {}", seed, dataSize);
    final AtomicReference<Throwable> error = new AtomicReference<>();
    final byte[] data = new byte[dataSize];
    final byte[] received = new byte[dataSize];
    r.nextBytes(data);
    final Publisher<Buffer> pub = cbos.connect();
    final Thread producerThread = new Thread(() -> {
        int writeIndex = 0;
        try {
            while (writeIndex < dataSize) {
                // write at most 25% of remaining bytes
                final int length = (int) max(1, r.nextInt(dataSize - (writeIndex - 1)) * 0.25);
                LOGGER.debug("Writing {} bytes - writeIndex = {}", length, writeIndex);
                cbos.write(data, writeIndex, length);
                writeIndex += length;
                if (r.nextDouble() < 0.4) {
                    LOGGER.debug("Flushing - writeIndex = {}", writeIndex);
                    cbos.flush();
                }
            }
            LOGGER.debug("Closing - writeIndex = {}", writeIndex);
            cbos.close();
        } catch (Throwable t) {
            error.compareAndSet(null, t);
        }
    });
    final Thread consumerThread = new Thread(() -> {
        try {
            final CountDownLatch consumerDone = new CountDownLatch(1);
            toSource(pub).subscribe(new Subscriber<Buffer>() {

                @Nullable
                private Subscription sub;

                private int writeIndex;

                @Override
                public void onSubscribe(final Subscription s) {
                    sub = s;
                    sub.request(1);
                }

                @Override
                public void onNext(final Buffer buffer) {
                    final int readingBytes = buffer.readableBytes();
                    LOGGER.debug("Reading {} bytes, writeIndex = {}", readingBytes, writeIndex);
                    buffer.readBytes(received, writeIndex, readingBytes);
                    writeIndex += readingBytes;
                    assert sub != null : "Subscription can not be null in onNext.";
                    sub.request(1);
                }

                @Override
                public void onError(final Throwable t) {
                    error.compareAndSet(null, t);
                    consumerDone.countDown();
                }

                @Override
                public void onComplete() {
                    consumerDone.countDown();
                }
            });
            consumerDone.await();
        } catch (Throwable t) {
            error.compareAndSet(null, t);
        }
    });
    producerThread.start();
    consumerThread.start();
    // make sure both threads exit
    producerThread.join();
    // provides visibility for received from consumerThread
    consumerThread.join();
    assertNull(error.get());
    // assertThat() times out
    assertArrayEquals(data, received);
}
Also used : Buffer(io.servicetalk.buffer.api.Buffer) AtomicReference(java.util.concurrent.atomic.AtomicReference) CountDownLatch(java.util.concurrent.CountDownLatch) Random(java.util.Random) Subscription(io.servicetalk.concurrent.PublisherSource.Subscription) Nullable(javax.annotation.Nullable) Test(org.junit.jupiter.api.Test)

Example 2 with Subscription

use of io.servicetalk.concurrent.PublisherSource.Subscription in project servicetalk by apple.

the class InlinePublisherFirstStep method expectSubscriptionConsumed.

@Override
public PublisherStep<T> expectSubscriptionConsumed(Consumer<? super Subscription> consumer) {
    requireNonNull(consumer);
    events.add(new OnSubscriptionEvent() {

        @Override
        void subscription(Subscription subscription) {
            consumer.accept(subscription);
        }

        @Override
        String description() {
            return "expectSubscription(" + consumer + ")";
        }
    });
    return this;
}
Also used : Subscription(io.servicetalk.concurrent.PublisherSource.Subscription) OnSubscriptionEvent(io.servicetalk.concurrent.api.test.InlinePublisherSubscriber.OnSubscriptionEvent)

Example 3 with Subscription

use of io.servicetalk.concurrent.PublisherSource.Subscription in project servicetalk by apple.

the class ConcurrentSubscriptionTest method singleThreadInvalidRequestN.

@Test
void singleThreadInvalidRequestN() {
    Subscription concurrent = ConcurrentSubscription.wrap(subscription);
    final long invalidN = ThreadLocalRandom.current().nextLong(Long.MIN_VALUE, 1);
    concurrent.request(invalidN);
    assertThat("unexpected requested with invalidN: " + invalidN, subscription.requested(), lessThanOrEqualTo(0L));
}
Also used : Subscription(io.servicetalk.concurrent.PublisherSource.Subscription) TestSubscription(io.servicetalk.concurrent.api.TestSubscription) Test(org.junit.jupiter.api.Test)

Example 4 with Subscription

use of io.servicetalk.concurrent.PublisherSource.Subscription in project servicetalk by apple.

the class ConcurrentSubscriptionTest method multiThread.

private void multiThread(final int threads, boolean cancel) throws ExecutionException, InterruptedException {
    ExecutorService executorService = newFixedThreadPool(threads);
    try {
        List<Future<?>> futures = new ArrayList<>(threads);
        Subscription concurrent = ConcurrentSubscription.wrap(subscription);
        CyclicBarrier barrier = new CyclicBarrier(threads);
        for (int i = 0; i < threads; ++i) {
            final int finalI = i;
            futures.add(executorService.submit(() -> {
                try {
                    barrier.await();
                } catch (Exception e) {
                    throw new AssertionError(e);
                }
                concurrent.request(1);
                if (cancel && finalI % 2 == 0) {
                    concurrent.cancel();
                }
            }));
        }
        for (Future<?> f : futures) {
            f.get();
        }
        if (cancel) {
            assertTrue(subscription.isCancelled());
        } else {
            subscription.awaitRequestN(threads);
            assertFalse(subscription.isCancelled());
        }
    } finally {
        executorService.shutdown();
    }
}
Also used : ExecutorService(java.util.concurrent.ExecutorService) ArrayList(java.util.ArrayList) Future(java.util.concurrent.Future) Subscription(io.servicetalk.concurrent.PublisherSource.Subscription) TestSubscription(io.servicetalk.concurrent.api.TestSubscription) ExecutionException(java.util.concurrent.ExecutionException) CyclicBarrier(java.util.concurrent.CyclicBarrier)

Example 5 with Subscription

use of io.servicetalk.concurrent.PublisherSource.Subscription in project servicetalk by apple.

the class ConcurrentSubscriptionTest method multiThreadReentrant.

@Test
void multiThreadReentrant() throws Exception {
    ExecutorService executorService = newFixedThreadPool(1);
    try {
        final ReentrantSubscription reentrantSubscription = new ReentrantSubscription(50);
        final Subscription concurrent = ConcurrentSubscription.wrap(reentrantSubscription);
        CyclicBarrier barrier = new CyclicBarrier(2);
        reentrantSubscription.outerSubscription(concurrent);
        Future<?> f = executorService.submit(() -> {
            try {
                barrier.await();
            } catch (Exception e) {
                throw new AssertionError(e);
            }
            concurrent.request(1);
        });
        barrier.await();
        concurrent.request(1);
        f.get();
        // wait for the expected demand to be delivered.
        reentrantSubscription.innerSubscription.awaitRequestN(reentrantSubscription.reentrantLimit + 1);
    } finally {
        executorService.shutdown();
    }
}
Also used : ExecutorService(java.util.concurrent.ExecutorService) Subscription(io.servicetalk.concurrent.PublisherSource.Subscription) TestSubscription(io.servicetalk.concurrent.api.TestSubscription) ExecutionException(java.util.concurrent.ExecutionException) CyclicBarrier(java.util.concurrent.CyclicBarrier) Test(org.junit.jupiter.api.Test)

Aggregations

Subscription (io.servicetalk.concurrent.PublisherSource.Subscription)181 Test (org.junit.jupiter.api.Test)107 ParameterizedTest (org.junit.jupiter.params.ParameterizedTest)78 CountDownLatch (java.util.concurrent.CountDownLatch)45 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)44 AtomicReference (java.util.concurrent.atomic.AtomicReference)44 TestPublisherSubscriber (io.servicetalk.concurrent.test.internal.TestPublisherSubscriber)38 DELIBERATE_EXCEPTION (io.servicetalk.concurrent.internal.DeliberateException.DELIBERATE_EXCEPTION)31 Nullable (javax.annotation.Nullable)31 TestSubscription (io.servicetalk.concurrent.api.TestSubscription)30 MethodSource (org.junit.jupiter.params.provider.MethodSource)28 ValueSource (org.junit.jupiter.params.provider.ValueSource)28 PublisherSource (io.servicetalk.concurrent.PublisherSource)27 SourceAdapters.toSource (io.servicetalk.concurrent.api.SourceAdapters.toSource)27 MatcherAssert.assertThat (org.hamcrest.MatcherAssert.assertThat)27 Matchers.is (org.hamcrest.Matchers.is)27 Subscriber (io.servicetalk.concurrent.PublisherSource.Subscriber)26 CyclicBarrier (java.util.concurrent.CyclicBarrier)25 ExecutorService (java.util.concurrent.ExecutorService)25 Mockito.mock (org.mockito.Mockito.mock)25