Search in sources :

Example 1 with ManyToOneConcurrentArrayQueue

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

the class MergeLatestOperator method subscribe.

@Override
public StreamSubscription subscribe(Consumer<? super IN> onNext, Consumer<? super Throwable> onError, Runnable onComplete) {
    ManyToOneConcurrentArrayQueue<IN> data = new ManyToOneConcurrentArrayQueue<IN>(1024 * operators.length);
    List<StreamSubscription> subs = new ArrayList<>(operators.length);
    AtomicInteger completed = new AtomicInteger(0);
    AtomicInteger index = new AtomicInteger(0);
    StreamSubscription sub = new StreamSubscription() {

        LongConsumer work = n -> {
            while (requested.get() > 0) {
                if (completed.get() == subs.size() && data.size() == 0) {
                    onComplete.run();
                    return;
                }
                long sent = 0;
                long reqCycle = requested.get();
                for (long k = 0; k < reqCycle; k++) {
                    if (!isOpen)
                        return;
                    int toUse = index.incrementAndGet() - 1;
                    if (toUse + 1 >= subs.size()) {
                        index.set(0);
                    }
                    if (subs.get(toUse).isOpen) {
                        subs.get(toUse).request(1l);
                    } else
                        k--;
                    IN fromQ = nilsafeOut(data.poll());
                    if (fromQ != null) {
                        onNext.accept(fromQ);
                        requested.decrementAndGet();
                        sent++;
                    }
                    if (completed.get() == subs.size() && data.size() == 0) {
                        onComplete.run();
                        return;
                    }
                }
                while (sent < reqCycle && isOpen && !(completed.get() == subs.size() && data.size() == 0)) {
                    IN fromQ = nilsafeOut(data.poll());
                    if (fromQ != null) {
                        onNext.accept(fromQ);
                        requested.decrementAndGet();
                        sent++;
                    }
                }
                if (completed.get() == subs.size() && data.size() == 0) {
                    onComplete.run();
                    return;
                }
            }
        };

        @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;
            }
            super.singleActiveRequest(n, work);
        }

        @Override
        public void cancel() {
            super.cancel();
        }
    };
    for (int i = 0; i < operators.length; i++) {
        int current = i;
        subs.add(operators[current].subscribe(e -> {
            try {
                while (!data.offer((IN) nilsafeIn(e))) {
                }
            } catch (Throwable t) {
                onError.accept(t);
            } finally {
            }
        }, onError, () -> {
            completed.incrementAndGet();
        }));
    }
    return sub;
}
Also used : ManyToOneConcurrentArrayQueue(org.agrona.concurrent.ManyToOneConcurrentArrayQueue) Consumer(java.util.function.Consumer) List(java.util.List) Queue(com.oath.cyclops.async.adapters.Queue) ManyToOneConcurrentArrayQueue(org.agrona.concurrent.ManyToOneConcurrentArrayQueue) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) ArrayList(java.util.ArrayList) LongConsumer(java.util.function.LongConsumer) ArrayList(java.util.ArrayList) LongConsumer(java.util.function.LongConsumer) AtomicInteger(java.util.concurrent.atomic.AtomicInteger)

Example 2 with ManyToOneConcurrentArrayQueue

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

the class ZippingLatestOperator method subscribe.

@Override
public StreamSubscription subscribe(Consumer<? super R> onNext, Consumer<? super Throwable> onError, Runnable onComplete) {
    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);
    AtomicReference<Tuple2<T1, T2>> nextValue = new AtomicReference<>(Tuple.tuple((T1) UNSET, (T2) UNSET));
    AtomicBoolean completing = new AtomicBoolean(false);
    AtomicInteger completed = new AtomicInteger(0);
    AtomicInteger index = new AtomicInteger(0);
    ManyToOneConcurrentArrayQueue<R> data = new ManyToOneConcurrentArrayQueue<R>(1024);
    List<StreamSubscription> subs = new ArrayList<>(2);
    StreamSubscription sub = new StreamSubscription() {

        LongConsumer work = n -> {
            while (requested.get() > 0) {
                if (completed.get() == 2 && data.size() == 0) {
                    onComplete.run();
                    return;
                }
                long sent = 0;
                long reqCycle = requested.get();
                for (long k = 0; k < reqCycle; k++) {
                    if (!isOpen)
                        return;
                    int toUse = index.incrementAndGet() - 1;
                    if (toUse + 1 >= subs.size()) {
                        index.set(0);
                    }
                    if (subs.get(toUse).isOpen) {
                        subs.get(toUse).request(1l);
                    } else
                        k--;
                    R fromQ = nilsafeOut(data.poll());
                    if (fromQ != null) {
                        onNext.accept(fromQ);
                        requested.decrementAndGet();
                        sent++;
                    }
                    if (completed.get() == subs.size() && data.size() == 0) {
                        onComplete.run();
                        return;
                    }
                }
                while (sent < reqCycle && isOpen && !(completed.get() == subs.size() && data.size() == 0)) {
                    R fromQ = nilsafeOut(data.poll());
                    if (fromQ != null) {
                        onNext.accept(fromQ);
                        requested.decrementAndGet();
                        sent++;
                    }
                }
                if (completed.get() == subs.size() && data.size() == 0) {
                    onComplete.run();
                    return;
                }
            }
        };

        @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 {
            boolean set = false;
            while (!set) {
                Tuple2<T1, T2> local = nextValue.get();
                Tuple2<T1, T2> updated = local.map1(__ -> (T1) e);
                set = nextValue.compareAndSet(local, updated);
                if (set) {
                    if (updated._2() != UNSET) {
                        while (!data.offer((R) nilsafeIn(applyFn(updated)))) {
                        }
                    }
                }
            }
        } catch (Throwable t) {
            onError.accept(t);
        }
    }, e -> {
        onError.accept(e);
        leftSub[0].request(1l);
    }, () -> {
        completed.incrementAndGet();
    });
    rightSub[0] = right.subscribe(e -> {
        if (!sub.isOpen)
            return;
        try {
            boolean set = false;
            while (!set) {
                Tuple2<T1, T2> local = nextValue.get();
                Tuple2<T1, T2> updated = local.map2(__ -> (T2) e);
                set = nextValue.compareAndSet(local, updated);
                if (set) {
                    if (updated._1() != UNSET) {
                        while (!data.offer((R) nilsafeIn(applyFn(updated)))) {
                        }
                    }
                }
            }
        } catch (Throwable t) {
            onError.accept(t);
        }
    }, e -> {
        onError.accept(e);
        rightSub[0].request(1l);
    }, () -> {
        completed.incrementAndGet();
    });
    subs.add(leftSub[0]);
    subs.add(rightSub[0]);
    return sub;
}
Also used : ManyToOneConcurrentArrayQueue(org.agrona.concurrent.ManyToOneConcurrentArrayQueue) Tuple2(cyclops.data.tuple.Tuple2) BiFunction(java.util.function.BiFunction) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) AtomicReference(java.util.concurrent.atomic.AtomicReference) ArrayList(java.util.ArrayList) LongConsumer(java.util.function.LongConsumer) Consumer(java.util.function.Consumer) List(java.util.List) Queue(com.oath.cyclops.async.adapters.Queue) Tuple(cyclops.data.tuple.Tuple) ManyToOneConcurrentArrayQueue(org.agrona.concurrent.ManyToOneConcurrentArrayQueue) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) AllArgsConstructor(lombok.AllArgsConstructor) ArrayList(java.util.ArrayList) AtomicReference(java.util.concurrent.atomic.AtomicReference) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) LongConsumer(java.util.function.LongConsumer) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Tuple2(cyclops.data.tuple.Tuple2)

Example 3 with ManyToOneConcurrentArrayQueue

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

the class ZippingLatestOperator method subscribeAll.

@Override
public void subscribeAll(Consumer<? super R> onNext, Consumer<? super Throwable> onError, Runnable onCompleteDs) {
    AtomicBoolean active = new AtomicBoolean(false);
    ManyToOneConcurrentArrayQueue<R> data = new ManyToOneConcurrentArrayQueue<R>(1024);
    AtomicReference<Tuple2<T1, T2>> nextValue = new AtomicReference<>(Tuple.tuple((T1) UNSET, (T2) UNSET));
    // left & right compelte can be merged into single integer
    AtomicBoolean leftComplete = new AtomicBoolean(false);
    AtomicBoolean rightComplete = new AtomicBoolean(false);
    left.subscribeAll(e -> {
        try {
            boolean set = false;
            while (!set) {
                Tuple2<T1, T2> local = nextValue.get();
                Tuple2<T1, T2> updated = local.map1(__ -> (T1) e);
                set = nextValue.compareAndSet(local, updated);
                if (set) {
                    if (updated._2() != UNSET) {
                        if (active.compareAndSet(false, true)) {
                            data.drain(onNext::accept);
                            onNext.accept(applyFn(updated));
                            active.set(false);
                        } else {
                            while (!data.offer(applyFn(updated))) {
                            }
                        }
                    }
                }
            }
        } catch (Throwable t) {
            onError.accept(t);
        }
    }, e -> {
        onError.accept(e);
    }, () -> {
        while (!active.compareAndSet(false, true)) {
        }
        data.drain(onNext::accept);
        if (rightComplete.get()) {
            onCompleteDs.run();
        }
        leftComplete.set(true);
        active.set(false);
    });
    right.subscribeAll(e -> {
        try {
            boolean set = false;
            while (!set) {
                Tuple2<T1, T2> local = nextValue.get();
                Tuple2<T1, T2> updated = local.map2(__ -> (T2) e);
                set = nextValue.compareAndSet(local, updated);
                if (set) {
                    if (updated._1() != UNSET) {
                        if (active.compareAndSet(false, true)) {
                            data.drain(onNext::accept);
                            onNext.accept(applyFn(updated));
                            active.set(false);
                        } else {
                            while (!data.offer(applyFn(updated))) {
                            }
                        }
                    }
                }
            }
        } catch (Throwable t) {
            onError.accept(t);
        }
    }, e -> {
        onError.accept(e);
    }, () -> {
        while (!active.compareAndSet(false, true)) {
        }
        data.drain(onNext::accept);
        if (leftComplete.get()) {
            onCompleteDs.run();
        }
        rightComplete.set(true);
        active.set(false);
    });
}
Also used : ManyToOneConcurrentArrayQueue(org.agrona.concurrent.ManyToOneConcurrentArrayQueue) AtomicReference(java.util.concurrent.atomic.AtomicReference) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) Tuple2(cyclops.data.tuple.Tuple2)

Example 4 with ManyToOneConcurrentArrayQueue

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

the class MergeLatestOperator method subscribeAll.

@Override
public void subscribeAll(Consumer<? super IN> onNext, Consumer<? super Throwable> onError, Runnable onCompleteDs) {
    List<StreamSubscription> subs = new ArrayList<>(operators.length);
    AtomicInteger completed = new AtomicInteger(0);
    AtomicInteger index = new AtomicInteger(0);
    ManyToOneConcurrentArrayQueue<IN> data = new ManyToOneConcurrentArrayQueue<IN>(1024 * operators.length);
    AtomicBoolean wip = new AtomicBoolean(false);
    for (int i = 0; i < operators.length; i++) {
        int current = i;
        operators[current].subscribeAll(e -> {
            try {
                if (wip.compareAndSet(false, true)) {
                    onNext.accept(e);
                    data.drain(x -> onNext.accept(x));
                    wip.set(false);
                } else {
                    data.offer(e);
                }
            } catch (Throwable t) {
                onError.accept(t);
            } finally {
            }
        }, onError, () -> {
            if (completed.incrementAndGet() == operators.length) {
                data.drain(x -> onNext.accept(x));
                onCompleteDs.run();
            }
        });
    }
}
Also used : ManyToOneConcurrentArrayQueue(org.agrona.concurrent.ManyToOneConcurrentArrayQueue) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) ArrayList(java.util.ArrayList)

Aggregations

AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)4 ManyToOneConcurrentArrayQueue (org.agrona.concurrent.ManyToOneConcurrentArrayQueue)4 ArrayList (java.util.ArrayList)3 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)3 Queue (com.oath.cyclops.async.adapters.Queue)2 Tuple2 (cyclops.data.tuple.Tuple2)2 List (java.util.List)2 AtomicReference (java.util.concurrent.atomic.AtomicReference)2 Consumer (java.util.function.Consumer)2 LongConsumer (java.util.function.LongConsumer)2 Tuple (cyclops.data.tuple.Tuple)1 BiFunction (java.util.function.BiFunction)1 AllArgsConstructor (lombok.AllArgsConstructor)1