Search in sources :

Example 1 with Function2

use of co.paralleluniverse.common.util.Function2 in project quasar by puniverse.

the class TransformingChannelTest method testTakeThreadToFibers.

@Test
@SuppressWarnings("null")
public void testTakeThreadToFibers() throws Exception {
    // TODO Reorg to try with blocking channel at least meaningful parts
    assumeThat(mailboxSize, greaterThan(0));
    final Channel<Object> takeSourceCh = newChannel();
    // Test 2 fibers failing immediately on take 0 of 1
    final ReceivePort<Object> take0RP = Channels.take((ReceivePort<Object>) takeSourceCh, 0);
    final SuspendableRunnable take0SR = new SuspendableRunnable() {

        @Override
        public void run() throws SuspendExecution, InterruptedException {
            assertThat(take0RP.receive(), is(nullValue()));
            assertThat(take0RP.tryReceive(), is(nullValue()));
            long start = System.nanoTime();
            assertThat(take0RP.receive(10, TimeUnit.SECONDS), is(nullValue()));
            long end = System.nanoTime();
            // Should be immediate
            assertThat(end - start, lessThan(new Long(5 * 1000 * 1000 * 1000)));
            start = System.nanoTime();
            assertThat(take0RP.receive(new Timeout(10, TimeUnit.SECONDS)), is(nullValue()));
            end = System.nanoTime();
            // Should be immediate
            assertThat(end - start, lessThan(new Long(5 * 1000 * 1000 * 1000)));
        }
    };
    final Fiber take0Of1Fiber1 = new Fiber("take-0-of-1_fiber1", scheduler, take0SR).start();
    final Fiber take0Of1Fiber2 = new Fiber("take-0-of-1_fiber2", scheduler, take0SR).start();
    takeSourceCh.send(new Object());
    take0Of1Fiber1.join();
    take0Of1Fiber2.join();
    // 1 left in source, check and cleanup
    assertThat(takeSourceCh.receive(), is(notNullValue()));
    // Test tryReceive failing immediately when fiber blocked in receive on take 1 of 2
    final ReceivePort<Object> take1Of2RP = Channels.take((ReceivePort<Object>) takeSourceCh, 1);
    final Fiber timeoutSucceedingTake1Of2 = new Fiber("take-1-of-2_timeout_success", scheduler, new SuspendableRunnable() {

        @Override
        public void run() throws SuspendExecution, InterruptedException {
            final long start = System.nanoTime();
            assertThat(take1Of2RP.receive(1, TimeUnit.SECONDS), is(notNullValue()));
            final long end = System.nanoTime();
            assertThat(end - start, lessThan(new Long(500 * 1000 * 1000)));
        }
    }).start();
    // Let the fiber blocks in receive before starting the try
    Thread.sleep(100);
    final Fiber tryFailingTake1Of2 = new Fiber("take-1-of-2_try_fail", scheduler, new SuspendableRunnable() {

        @Override
        public void run() throws SuspendExecution, InterruptedException {
            final long start = System.nanoTime();
            assertThat(take1Of2RP.tryReceive(), is(nullValue()));
            final long end = System.nanoTime();
            // Should be immediate
            assertThat(end - start, lessThan(new Long(500 * 1000 * 1000)));
        }
    }).start();
    Thread.sleep(100);
    // Make messages available
    takeSourceCh.send(new Object());
    takeSourceCh.send(new Object());
    timeoutSucceedingTake1Of2.join();
    tryFailingTake1Of2.join();
    // 1 left in source, check and cleanup
    assertThat(takeSourceCh.receive(), is(notNullValue()));
    // Comprehensive take + contention test:
    //
    // - 1 message available immediately, 2 messages available in a burst on the source after 1s
    // - take 2
    // - 5 fibers competing on the take source (1 in front)
    //
    // - one front fiber receiving with 200ms timeout => immediate success
    // - one more front fiber receiving with 200ms timeout => fail
    // - 3rd fiber taking over, receiving with 200ms timeout => fail
    // - 4th fiber taking over, receiving with 1s timeout => success
    // - 5th fiber asking untimed receive, waiting in monitor, will bail out because of take threshold
    final ReceivePort<Object> take2Of3RPComprehensive = Channels.take((ReceivePort<Object>) takeSourceCh, 2);
    final Function2<Long, Integer, Fiber> take1SRFun = new Function2<Long, Integer, Fiber>() {

        @Override
        public Fiber apply(final Long timeoutMS, final Integer position) {
            return new Fiber("take-1-of-2_comprehensive_receiver_" + (timeoutMS >= 0 ? timeoutMS : "unlimited") + "ms-" + position, scheduler, new SuspendableRunnable() {

                @Override
                public void run() throws SuspendExecution, InterruptedException {
                    final long start = System.nanoTime();
                    final Object res = (timeoutMS >= 0 ? take2Of3RPComprehensive.receive(timeoutMS, TimeUnit.MILLISECONDS) : take2Of3RPComprehensive.receive());
                    final long end = System.nanoTime();
                    switch(position) {
                        case 1:
                            assertThat(res, is(notNullValue()));
                            assertThat(end - start, lessThan(new Long(300 * 1000 * 1000)));
                            break;
                        case 2:
                            assertThat(res, is(nullValue()));
                            assertThat(end - start, greaterThan(new Long(300 * 1000 * 1000)));
                            break;
                        case 3:
                            assertThat(res, is(nullValue()));
                            assertThat(end - start, greaterThan(new Long(200 * 1000 * 1000)));
                            break;
                        case 4:
                            assertThat(res, is(notNullValue()));
                            assertThat(end - start, lessThan(new Long(1000 * 1000 * 1000)));
                            break;
                        case 5:
                            assertThat(res, is(nullValue()));
                            // Should be almost instantaneous
                            assertThat(end - start, lessThan(new Long(1000 * 1000 * 1000)));
                            break;
                        default:
                            fail();
                            break;
                    }
                }
            });
        }
    };
    final Fiber[] competing = new Fiber[5];
    // First front fiber winning first message
    competing[0] = take1SRFun.apply(300l, 1).start();
    // Make 1 message available immediately for the first front fiber to consume
    takeSourceCh.send(new Object());
    Thread.sleep(100);
    // Second front fiber losing (waiting too little for second message)
    competing[1] = take1SRFun.apply(300l, 2).start();
    Thread.sleep(100);
    // First waiter, will fail (not waiting enough)
    competing[2] = take1SRFun.apply(200l, 3).start();
    // First waiter takeover
    Thread.sleep(300);
    // Second waiter, will win second message (waiting enough)
    competing[3] = take1SRFun.apply(1000l, 4).start();
    // Second waiter takeover
    Thread.sleep(300);
    // Third waiter, will try after take threshold and will bail out
    competing[4] = take1SRFun.apply(-1l, 5).start();
    // Make 2 more messages available
    takeSourceCh.send(new Object());
    takeSourceCh.send(new Object());
    // Wait fibers to finsh
    for (final Fiber f : competing) f.join();
    // 1 left in source, check and cleanup
    assertThat(takeSourceCh.receive(), is(notNullValue()));
    // Explicit (and uncoupled from source) closing of TakeSP
    final ReceivePort<Object> take1Of0ExplicitClose = Channels.take((ReceivePort<Object>) takeSourceCh, 1);
    final SuspendableRunnable explicitCloseSR = new SuspendableRunnable() {

        @Override
        public void run() throws SuspendExecution, InterruptedException {
            final long start = System.nanoTime();
            final Object ret = take1Of0ExplicitClose.receive();
            final long end = System.nanoTime();
            assertThat(ret, is(nullValue()));
            assertTrue(take1Of0ExplicitClose.isClosed());
            assertFalse(takeSourceCh.isClosed());
            assertThat(end - start, lessThan(new Long(500 * 1000 * 1000)));
        }
    };
    final Fiber explicitCloseF1 = new Fiber("take-explicit-close-1", scheduler, explicitCloseSR);
    final Fiber explicitCloseF2 = new Fiber("take-explicit-close-2", scheduler, explicitCloseSR);
    Thread.sleep(100);
    take1Of0ExplicitClose.close();
}
Also used : SuspendExecution(co.paralleluniverse.fibers.SuspendExecution) SuspendableRunnable(co.paralleluniverse.strands.SuspendableRunnable) Timeout(co.paralleluniverse.strands.Timeout) Fiber(co.paralleluniverse.fibers.Fiber) Function2(co.paralleluniverse.common.util.Function2) Test(org.junit.Test)

Aggregations

Function2 (co.paralleluniverse.common.util.Function2)1 Fiber (co.paralleluniverse.fibers.Fiber)1 SuspendExecution (co.paralleluniverse.fibers.SuspendExecution)1 SuspendableRunnable (co.paralleluniverse.strands.SuspendableRunnable)1 Timeout (co.paralleluniverse.strands.Timeout)1 Test (org.junit.Test)1