• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

amaembo / streamex / #677

02 Nov 2024 08:50AM UTC coverage: 99.673%. Remained the same
#677

push

amaembo
Optimize imports

5786 of 5805 relevant lines covered (99.67%)

1.0 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

97.94
/src/main/java/one/util/streamex/OrderedCancellableSpliterator.java
1
/*
2
 * Copyright 2015, 2024 StreamEx contributors
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *     http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
package one.util.streamex;
17

18
import java.util.ArrayDeque;
19
import java.util.Spliterator;
20
import java.util.function.*;
21

22
import static one.util.streamex.Internals.CancelException;
23
import static one.util.streamex.Internals.CloneableSpliterator;
24

25
/**
26
 * @author Tagir Valeev
27
 */
28
/* package */final class OrderedCancellableSpliterator<T, A> extends CloneableSpliterator<A, OrderedCancellableSpliterator<T, A>> {
29
    private Spliterator<T> source;
30
    private final Object lock = new Object();
1✔
31
    private final BiConsumer<A, ? super T> accumulator;
32
    private final Predicate<A> cancelPredicate;
33
    private final BinaryOperator<A> combiner;
34
    private final Supplier<A> supplier;
35
    private volatile boolean localCancelled;
36
    private volatile OrderedCancellableSpliterator<T, A> prefix;
37
    private volatile OrderedCancellableSpliterator<T, A> suffix;
38
    private A payload;
39

40
    OrderedCancellableSpliterator(Spliterator<T> source, Supplier<A> supplier, BiConsumer<A, ? super T> accumulator,
41
            BinaryOperator<A> combiner, Predicate<A> cancelPredicate) {
1✔
42
        this.source = source;
1✔
43
        this.supplier = supplier;
1✔
44
        this.accumulator = accumulator;
1✔
45
        this.combiner = combiner;
1✔
46
        this.cancelPredicate = cancelPredicate;
1✔
47
    }
1✔
48

49
    @Override
50
    public boolean tryAdvance(Consumer<? super A> action) {
51
        Spliterator<T> source = this.source;
1✔
52
        if (source == null || localCancelled) {
1✔
53
            this.source = null;
1✔
54
            return false;
1✔
55
        }
56
        A acc = supplier.get();
1✔
57
        try {
58
            source.forEachRemaining(t -> {
1✔
59
                accumulator.accept(acc, t);
1✔
60
                if (cancelPredicate.test(acc)) {
1✔
61
                    cancelSuffix();
1✔
62
                    throw new CancelException();
1✔
63
                }
64
                if (localCancelled) {
1✔
65
                    throw new CancelException();
1✔
66
                }
67
            });
1✔
68
        } catch (CancelException ex) {
1✔
69
            if (localCancelled) {
1✔
70
                return false;
1✔
71
            }
72
        }
1✔
73
        this.source = null;
1✔
74
        A result = acc;
1✔
75
        while (true) {
76
            if (prefix == null && suffix == null) {
1✔
77
                action.accept(result);
1✔
78
                return true;
1✔
79
            }
80
            ArrayDeque<A> res = new ArrayDeque<>();
1✔
81
            res.offer(result);
1✔
82
            synchronized (lock) {
1✔
83
                if (localCancelled)
1✔
84
                    return false;
1✔
85
                OrderedCancellableSpliterator<T, A> s = prefix;
1✔
86
                while (s != null) {
1✔
87
                    if (s.payload == null)
1✔
88
                        break;
1✔
89
                    res.offerFirst(s.payload);
1✔
90
                    s = s.prefix;
1✔
91
                }
92
                prefix = s;
1✔
93
                if (s != null) {
1✔
94
                    s.suffix = this;
1✔
95
                }
96
                s = suffix;
1✔
97
                while (s != null) {
1✔
98
                    if (s.payload == null)
1✔
99
                        break;
1✔
100
                    res.offerLast(s.payload);
1✔
101
                    s = s.suffix;
1✔
102
                }
103
                suffix = s;
1✔
104
                if (s != null) {
1✔
105
                    s.prefix = this;
1✔
106
                }
107
                if (res.size() == 1) {
1✔
108
                    if (prefix == null && suffix == null) {
1✔
109
                        action.accept(result);
×
110
                        return true;
×
111
                    }
112
                    this.payload = result;
1✔
113
                    break;
1✔
114
                }
115
            }
1✔
116
            result = res.pollFirst();
1✔
117
            while (!res.isEmpty()) {
1✔
118
                result = combiner.apply(result, res.pollFirst());
1✔
119
                if (cancelPredicate.test(result)) {
1✔
120
                    cancelSuffix();
1✔
121
                }
122
            }
123
        }
1✔
124
        return false;
1✔
125
    }
126

127
    private void cancelSuffix() {
128
        if (this.suffix == null)
1✔
129
            return;
1✔
130
        synchronized (lock) {
1✔
131
            OrderedCancellableSpliterator<T, A> suffix = this.suffix;
1✔
132
            while (suffix != null && !suffix.localCancelled) {
1✔
133
                suffix.prefix = null;
1✔
134
                suffix.localCancelled = true;
1✔
135
                suffix = suffix.suffix;
1✔
136
            }
137
            this.suffix = null;
1✔
138
        }
1✔
139
    }
1✔
140

141
    @Override
142
    public void forEachRemaining(Consumer<? super A> action) {
143
        tryAdvance(action);
1✔
144
    }
1✔
145

146
    @Override
147
    public Spliterator<A> trySplit() {
148
        if (source == null || localCancelled) {
1✔
149
            source = null;
1✔
150
            return null;
1✔
151
        }
152
        Spliterator<T> prefix = source.trySplit();
1✔
153
        if (prefix == null) {
1✔
154
            return null;
1✔
155
        }
156
        synchronized (lock) {
1✔
157
            OrderedCancellableSpliterator<T, A> result = doClone();
1✔
158
            result.source = prefix;
1✔
159
            this.prefix = result;
1✔
160
            result.suffix = this;
1✔
161
            OrderedCancellableSpliterator<T, A> prefixPrefix = result.prefix;
1✔
162
            if (prefixPrefix != null)
1✔
163
                prefixPrefix.suffix = result;
1✔
164
            return result;
1✔
165
        }
166
    }
167

168
    @Override
169
    public long estimateSize() {
170
        return source == null ? 0 : source.estimateSize();
1✔
171
    }
172

173
    @Override
174
    public int characteristics() {
175
        return source == null ? SIZED : ORDERED;
1✔
176
    }
177
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc