Search in sources :

Example 1 with OneToOneConcurrentArrayQueue

use of org.agrona.concurrent.OneToOneConcurrentArrayQueue in project Aeron by real-logic.

the class DriverConductorTest method setUp.

@Before
public void setUp() throws Exception {
    // System GC required in order to ensure that the direct byte buffers get cleaned and avoid OOM.
    System.gc();
    when(mockRawLogFactory.newNetworkPublication(anyString(), anyInt(), anyInt(), anyLong(), anyInt())).thenReturn(LogBufferHelper.newTestLogBuffers(TERM_BUFFER_LENGTH));
    when(mockRawLogFactory.newNetworkedImage(anyString(), anyInt(), anyInt(), anyLong(), eq(TERM_BUFFER_LENGTH))).thenReturn(LogBufferHelper.newTestLogBuffers(TERM_BUFFER_LENGTH));
    when(mockRawLogFactory.newIpcPublication(anyInt(), anyInt(), anyLong(), anyInt())).thenReturn(LogBufferHelper.newTestLogBuffers(TERM_BUFFER_LENGTH));
    currentTimeNs = 0;
    final UnsafeBuffer counterBuffer = new UnsafeBuffer(ByteBuffer.allocateDirect(BUFFER_LENGTH));
    final CountersManager countersManager = new CountersManager(new UnsafeBuffer(ByteBuffer.allocateDirect(BUFFER_LENGTH * 2)), counterBuffer);
    final MediaDriver.Context ctx = new MediaDriver.Context().unicastFlowControlSupplier(Configuration.unicastFlowControlSupplier()).multicastFlowControlSupplier(Configuration.multicastFlowControlSupplier()).toConductorFromReceiverCommandQueue(new OneToOneConcurrentArrayQueue<>(1024)).toConductorFromSenderCommandQueue(new OneToOneConcurrentArrayQueue<>(1024)).errorLog(mockErrorLog).rawLogBuffersFactory(mockRawLogFactory).countersManager(countersManager).nanoClock(nanoClock).sendChannelEndpointSupplier(Configuration.sendChannelEndpointSupplier()).receiveChannelEndpointSupplier(Configuration.receiveChannelEndpointSupplier()).congestControlSupplier(Configuration.congestionControlSupplier());
    ctx.toDriverCommands(fromClientCommands);
    ctx.clientProxy(mockClientProxy);
    ctx.countersValuesBuffer(counterBuffer);
    final SystemCounters mockSystemCounters = mock(SystemCounters.class);
    ctx.systemCounters(mockSystemCounters);
    when(mockSystemCounters.get(any())).thenReturn(mockErrorCounter);
    ctx.epochClock(new SystemEpochClock());
    ctx.receiverProxy(receiverProxy);
    ctx.senderProxy(senderProxy);
    ctx.fromReceiverDriverConductorProxy(fromReceiverConductorProxy);
    ctx.fromSenderDriverConductorProxy(fromSenderConductorProxy);
    ctx.clientLivenessTimeoutNs(CLIENT_LIVENESS_TIMEOUT_NS);
    ctx.receiveChannelEndpointThreadLocals(new ReceiveChannelEndpointThreadLocals(ctx));
    driverProxy = new DriverProxy(fromClientCommands);
    driverConductor = new DriverConductor(ctx);
    doAnswer(closeChannelEndpointAnswer).when(receiverProxy).closeReceiveChannelEndpoint(any());
}
Also used : OneToOneConcurrentArrayQueue(org.agrona.concurrent.OneToOneConcurrentArrayQueue) SystemCounters(io.aeron.driver.status.SystemCounters) UnsafeBuffer(org.agrona.concurrent.UnsafeBuffer) DriverProxy(io.aeron.DriverProxy) CountersManager(org.agrona.concurrent.status.CountersManager) SystemEpochClock(org.agrona.concurrent.SystemEpochClock) ReceiveChannelEndpointThreadLocals(io.aeron.driver.media.ReceiveChannelEndpointThreadLocals) Before(org.junit.Before)

Example 2 with OneToOneConcurrentArrayQueue

use of org.agrona.concurrent.OneToOneConcurrentArrayQueue in project cyclops by aol.

the class ZippingOperator method subscribeAll.

@Override
public void subscribeAll(Consumer<? super R> onNext, Consumer<? super Throwable> onError, Runnable onCompleteDs) {
    OneToOneConcurrentArrayQueue<T1> leftQ = new OneToOneConcurrentArrayQueue<T1>(1024);
    OneToOneConcurrentArrayQueue<T2> rightQ = new OneToOneConcurrentArrayQueue<T2>(1024);
    StreamSubscription[] rightSub = { null };
    // left & right compelte can be merged into single integer
    AtomicBoolean leftComplete = new AtomicBoolean(false);
    AtomicBoolean rightComplete = new AtomicBoolean(false);
    AtomicLong leftActive = new AtomicLong(0);
    AtomicLong rightActive = new AtomicLong(0);
    AtomicBoolean completing = new AtomicBoolean(false);
    // 1st bit for left, 2 bit for right pushing
    AtomicInteger status = new AtomicInteger(0);
    rightSub[0] = right.subscribe(e -> {
        if (completing.get())
            return;
        try {
            if (!leftQ.isEmpty()) {
                R value = fn.apply(leftQ.poll(), (T2) e);
                onNext.accept(value);
                leftActive.decrementAndGet();
            } else {
                if (status.compareAndSet(0, 2) && leftQ.isEmpty()) {
                    rightActive.incrementAndGet();
                    rightQ.offer((T2) e);
                    status.set(0);
                } else {
                    status.compareAndSet(2, 0);
                    while (leftQ.isEmpty()) {
                        // VALUE IS COMING
                        if (leftComplete.get() && leftQ.isEmpty()) {
                            handleComplete(completing, onCompleteDs);
                            return;
                        }
                        LockSupport.parkNanos(0);
                    }
                    R value = fn.apply(leftQ.poll(), (T2) e);
                    onNext.accept(value);
                    leftActive.decrementAndGet();
                }
            }
        } catch (Throwable t) {
            onError.accept(t);
        }
        if ((leftComplete.get() && leftQ.isEmpty()) || (rightComplete.get() && rightQ.isEmpty())) {
            rightSub[0].cancel();
            handleComplete(completing, onCompleteDs);
        }
    }, e -> {
        onError.accept(e);
    }, () -> {
        rightComplete.set(true);
        if (rightActive.get() == 0 || leftComplete.get()) {
            rightSub[0].cancel();
            handleComplete(completing, onCompleteDs);
        }
    });
    left.subscribeAll(e -> {
        if (completing.get())
            return;
        try {
            if (!rightQ.isEmpty()) {
                R value = fn.apply((T1) e, rightQ.poll());
                onNext.accept(value);
                rightActive.decrementAndGet();
                /**
                 * request more / next!
                 */
                rightSub[0].request(1);
            } else {
                if (status.compareAndSet(0, 1) && rightQ.isEmpty()) {
                    leftActive.incrementAndGet();
                    leftQ.offer((T1) e);
                    status.set(0);
                } else {
                    status.compareAndSet(1, 0);
                    while (rightQ.isEmpty()) {
                        // VALUE IS COMING
                        if (rightComplete.get() && rightQ.isEmpty()) {
                            handleComplete(completing, onCompleteDs);
                            return;
                        }
                        LockSupport.parkNanos(0);
                    }
                    R value = fn.apply((T1) e, rightQ.poll());
                    onNext.accept(value);
                    rightActive.decrementAndGet();
                }
            }
        } catch (Throwable t) {
            onError.accept(t);
        }
        if ((rightComplete.get() && rightQ.isEmpty()) || (leftComplete.get() && leftQ.isEmpty())) {
            rightSub[0].cancel();
            handleComplete(completing, onCompleteDs);
        }
    }, e -> {
        onError.accept(e);
    }, () -> {
        leftComplete.set(true);
        if (leftActive.get() == 0 || rightComplete.get()) {
            if (rightSub[0] != null)
                rightSub[0].cancel();
            handleComplete(completing, onCompleteDs);
        }
    });
    rightSub[0].request(Long.MAX_VALUE);
}
Also used : LockSupport(java.util.concurrent.locks.LockSupport) Consumer(java.util.function.Consumer) AtomicLong(java.util.concurrent.atomic.AtomicLong) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) BiFunction(java.util.function.BiFunction) OneToOneConcurrentArrayQueue(org.agrona.concurrent.OneToOneConcurrentArrayQueue) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) AllArgsConstructor(lombok.AllArgsConstructor) LongConsumer(java.util.function.LongConsumer) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) OneToOneConcurrentArrayQueue(org.agrona.concurrent.OneToOneConcurrentArrayQueue) AtomicLong(java.util.concurrent.atomic.AtomicLong) AtomicInteger(java.util.concurrent.atomic.AtomicInteger)

Example 3 with OneToOneConcurrentArrayQueue

use of org.agrona.concurrent.OneToOneConcurrentArrayQueue in project cyclops by aol.

the class ZippingOperator method subscribe.

@Override
public StreamSubscription subscribe(Consumer<? super R> onNext, Consumer<? super Throwable> onError, Runnable onComplete) {
    OneToOneConcurrentArrayQueue<T1> leftQ = new OneToOneConcurrentArrayQueue<T1>(1024);
    OneToOneConcurrentArrayQueue<T2> rightQ = new OneToOneConcurrentArrayQueue<T2>(1024);
    StreamSubscription[] leftSub = { null };
    StreamSubscription[] rightSub = { null };
    // left & right compelte can be merged into single integer
    AtomicBoolean leftComplete = new AtomicBoolean(false);
    AtomicBoolean rightComplete = new AtomicBoolean(false);
    AtomicLong leftActive = new AtomicLong(0);
    AtomicLong rightActive = new AtomicLong(0);
    AtomicBoolean completing = new AtomicBoolean(false);
    // 1st bit for left, 2 bit for right pushing
    AtomicInteger status = new AtomicInteger(0);
    StreamSubscription sub = new StreamSubscription() {

        LongConsumer work = n -> {
            leftSub[0].request(1);
            rightSub[0].request(1);
        };

        @Override
        public void request(long n) {
            if (n <= 0) {
                onError.accept(new IllegalArgumentException("3.9 While the Subscription is not cancelled, Subscription.request(long n) MUST throw a java.lang.IllegalArgumentException if the argument is <= 0."));
                return;
            }
            this.singleActiveRequest(n, work);
        }

        @Override
        public void cancel() {
            if (leftSub[0] != null)
                leftSub[0].cancel();
            if (rightSub[0] != null)
                rightSub[0].cancel();
            super.cancel();
        }
    };
    leftSub[0] = left.subscribe(e -> {
        if (!sub.isOpen)
            return;
        try {
            if (!rightQ.isEmpty()) {
                R value = fn.apply((T1) e, rightQ.poll());
                sub.requested.decrementAndGet();
                onNext.accept(value);
                rightActive.decrementAndGet();
                if (sub.requested.get() > 1) {
                    leftSub[0].request(1);
                    rightSub[0].request(1);
                }
            /**
             * request more / next!
             */
            } else {
                if (status.compareAndSet(0, 1) && rightQ.isEmpty()) {
                    leftActive.incrementAndGet();
                    leftQ.offer((T1) e);
                    status.set(0);
                } else {
                    status.compareAndSet(1, 0);
                    while (rightQ.isEmpty()) {
                        // VALUE IS COMING - RIGHT IS ADDING TO Q
                        if (rightComplete.get() && rightQ.isEmpty()) {
                            handleComplete(completing, onComplete);
                            return;
                        }
                        LockSupport.parkNanos(0);
                    }
                    R value = fn.apply((T1) e, rightQ.poll());
                    sub.requested.decrementAndGet();
                    onNext.accept(value);
                    if (sub.requested.get() > 1) {
                        leftSub[0].request(1);
                        rightSub[0].request(1);
                    }
                    rightActive.decrementAndGet();
                }
            }
        } catch (Throwable t) {
            onError.accept(t);
        }
        if ((rightComplete.get() && rightQ.isEmpty()) || (leftComplete.get() && leftQ.isEmpty())) {
            leftSub[0].cancel();
            handleComplete(completing, onComplete);
        }
    }, e -> {
        onError.accept(e);
        leftSub[0].request(1l);
    }, () -> {
        leftComplete.set(true);
        if (leftActive.get() == 0 || rightComplete.get()) {
            if (rightSub[0] != null)
                rightSub[0].cancel();
            handleComplete(completing, onComplete);
        }
    });
    rightSub[0] = right.subscribe(e -> {
        if (!sub.isOpen)
            return;
        try {
            if (!leftQ.isEmpty()) {
                R value = fn.apply(leftQ.poll(), (T2) e);
                sub.requested.decrementAndGet();
                onNext.accept(value);
                leftActive.decrementAndGet();
                if (sub.requested.get() > 1) {
                    leftSub[0].request(1l);
                    rightSub[0].request(1);
                }
            } else {
                if (status.compareAndSet(0, 2) && leftQ.isEmpty()) {
                    rightActive.incrementAndGet();
                    rightQ.offer((T2) e);
                    status.set(0);
                } else {
                    status.compareAndSet(2, 0);
                    while (leftQ.isEmpty()) {
                        // VALUE IS COMING  - LEFT IS ADDING TO Q
                        if (leftComplete.get() && leftQ.isEmpty()) {
                            handleComplete(completing, onComplete);
                            return;
                        }
                        LockSupport.parkNanos(0);
                    }
                    R value = fn.apply(leftQ.poll(), (T2) e);
                    sub.requested.decrementAndGet();
                    onNext.accept(value);
                    if (sub.requested.get() > 1) {
                        leftSub[0].request(1);
                        rightSub[0].request(1);
                    }
                    leftActive.decrementAndGet();
                }
            }
        } catch (Throwable t) {
            onError.accept(t);
        }
        if ((leftComplete.get() && leftQ.isEmpty()) || (rightComplete.get() && rightQ.isEmpty())) {
            rightSub[0].cancel();
            handleComplete(completing, onComplete);
        }
    }, e -> {
        onError.accept(e);
        rightSub[0].request(1l);
    }, () -> {
        rightComplete.set(true);
        if (rightActive.get() == 0 || leftComplete.get()) {
            if (leftSub[0] != null)
                leftSub[0].cancel();
            handleComplete(completing, onComplete);
        }
    });
    return sub;
}
Also used : LockSupport(java.util.concurrent.locks.LockSupport) Consumer(java.util.function.Consumer) AtomicLong(java.util.concurrent.atomic.AtomicLong) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) BiFunction(java.util.function.BiFunction) OneToOneConcurrentArrayQueue(org.agrona.concurrent.OneToOneConcurrentArrayQueue) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) AllArgsConstructor(lombok.AllArgsConstructor) LongConsumer(java.util.function.LongConsumer) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) OneToOneConcurrentArrayQueue(org.agrona.concurrent.OneToOneConcurrentArrayQueue) AtomicLong(java.util.concurrent.atomic.AtomicLong) LongConsumer(java.util.function.LongConsumer) AtomicInteger(java.util.concurrent.atomic.AtomicInteger)

Aggregations

OneToOneConcurrentArrayQueue (org.agrona.concurrent.OneToOneConcurrentArrayQueue)3 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)2 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)2 AtomicLong (java.util.concurrent.atomic.AtomicLong)2 LockSupport (java.util.concurrent.locks.LockSupport)2 BiFunction (java.util.function.BiFunction)2 Consumer (java.util.function.Consumer)2 LongConsumer (java.util.function.LongConsumer)2 AllArgsConstructor (lombok.AllArgsConstructor)2 DriverProxy (io.aeron.DriverProxy)1 ReceiveChannelEndpointThreadLocals (io.aeron.driver.media.ReceiveChannelEndpointThreadLocals)1 SystemCounters (io.aeron.driver.status.SystemCounters)1 SystemEpochClock (org.agrona.concurrent.SystemEpochClock)1 UnsafeBuffer (org.agrona.concurrent.UnsafeBuffer)1 CountersManager (org.agrona.concurrent.status.CountersManager)1 Before (org.junit.Before)1