AbstractParallelCollector.java

1
/*
2
 * Copyright 2014-2026 Grzegorz Piwowarek, https://4comprehension.com/
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
 * https://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 com.pivovarit.collectors;
17
18
import java.lang.ref.Cleaner;
19
import java.util.ArrayList;
20
import java.util.Collections;
21
import java.util.List;
22
import java.util.Set;
23
import java.util.concurrent.CompletableFuture;
24
import java.util.concurrent.atomic.AtomicInteger;
25
import java.util.function.BiConsumer;
26
import java.util.function.BinaryOperator;
27
import java.util.function.Function;
28
import java.util.function.Supplier;
29
import java.util.stream.Collector;
30
31
/**
32
 * @author Grzegorz Piwowarek
33
 */
34
sealed abstract class AbstractParallelCollector<T, A, R>
35
  implements Collector<T, List<CompletableFuture<A>>, R>
36
  permits AsyncParallelCollector, AsyncParallelStreamingCollector {
37
38
    protected final Dispatcher<A> dispatcher;
39
    protected final Function<? super T, ? extends A> task;
40
41
    private volatile Cleaner.Cleanable terminationGuard;
42
43
    private final AtomicInteger traversals = new AtomicInteger();
44
45
    private volatile boolean finished;
46
47
    protected AbstractParallelCollector(Function<? super T, ? extends A> task, Dispatcher<A> dispatcher) {
48
        this.task = task;
49
        this.dispatcher = dispatcher;
50
    }
51
52
    abstract Function<List<CompletableFuture<A>>, R> finalizer();
53
54
    @Override
55
    public final Supplier<List<CompletableFuture<A>>> supplier() {
56 1 1. supplier : replaced return value with null for com/pivovarit/collectors/AbstractParallelCollector::supplier → KILLED
        return () -> {
57 1 1. lambda$supplier$0 : negated conditional → KILLED
            if (finished) {
58
                throw new IllegalStateException("collector was already used and cannot be reused");
59
            }
60
            traversals.incrementAndGet();
61
            var container = new ArrayList<CompletableFuture<A>>();
62
            terminationGuard = dispatcher.registerTerminationGuard(container);
63 1 1. lambda$supplier$0 : replaced return value with Collections.emptyList for com/pivovarit/collectors/AbstractParallelCollector::lambda$supplier$0 → KILLED
            return container;
64
        };
65
    }
66
67
    @Override
68
    public final BiConsumer<List<CompletableFuture<A>>, T> accumulator() {
69 1 1. accumulator : replaced return value with null for com/pivovarit/collectors/AbstractParallelCollector::accumulator → KILLED
        return (acc, e) -> {
70 1 1. lambda$accumulator$0 : negated conditional → TIMED_OUT
            if (!dispatcher.wasStarted()) {
71 1 1. lambda$accumulator$0 : removed call to com/pivovarit/collectors/Dispatcher::start → TIMED_OUT
                dispatcher.start();
72
            }
73 1 1. lambda$accumulator$1 : replaced return value with null for com/pivovarit/collectors/AbstractParallelCollector::lambda$accumulator$1 → KILLED
            acc.add(dispatcher.submit(() -> task.apply(e)));
74
        };
75
    }
76
77
    @Override
78
    public BinaryOperator<List<CompletableFuture<A>>> combiner() {
79 1 1. combiner : replaced return value with null for com/pivovarit/collectors/AbstractParallelCollector::combiner → KILLED
        return (left, right) -> {
80
            throw new UnsupportedOperationException("using parallel stream with parallel collectors is not supported");
81
        };
82
    }
83
84
    @Override
85
    public final Function<List<CompletableFuture<A>>, R> finisher() {
86 1 1. finisher : replaced return value with null for com/pivovarit/collectors/AbstractParallelCollector::finisher → KILLED
        return list -> {
87
            finished = true;
88 1 1. lambda$finisher$0 : removed call to com/pivovarit/collectors/Dispatcher::stop → SURVIVED
            dispatcher.stop();
89 1 1. lambda$finisher$0 : negated conditional → SURVIVED
            if (terminationGuard != null) {
90 1 1. lambda$finisher$0 : removed call to java/lang/ref/Cleaner$Cleanable::clean → SURVIVED
                terminationGuard.clean();
91
            }
92 2 1. lambda$finisher$0 : negated conditional → KILLED
2. lambda$finisher$0 : changed conditional boundary → KILLED
            if (traversals.get() > 1) {
93
                throw new IllegalStateException("collector was already used and cannot be reused");
94
            }
95 1 1. lambda$finisher$0 : replaced return value with null for com/pivovarit/collectors/AbstractParallelCollector::lambda$finisher$0 → KILLED
            return finalizer().apply(list);
96
        };
97
    }
98
99
    @Override
100
    public Set<Characteristics> characteristics() {
101
        return Collections.emptySet();
102
    }
103
}

Mutations

56

1.1
Location : supplier
Killed by : com.pivovarit.collectors.LifecycleTest.[engine:junit-jupiter]/[class:com.pivovarit.collectors.LifecycleTest]/[method:shouldRejectReuseAfterEmptyTraversal()]
replaced return value with null for com/pivovarit/collectors/AbstractParallelCollector::supplier → KILLED

57

1.1
Location : lambda$supplier$0
Killed by : com.pivovarit.collectors.LifecycleTest.[engine:junit-jupiter]/[class:com.pivovarit.collectors.LifecycleTest]/[method:shouldRejectReuseAfterEmptyTraversal()]
negated conditional → KILLED

63

1.1
Location : lambda$supplier$0
Killed by : com.pivovarit.collectors.LifecycleTest.[engine:junit-jupiter]/[class:com.pivovarit.collectors.LifecycleTest]/[method:shouldRejectReuseAfterAbortedTraversal()]
replaced return value with Collections.emptyList for com/pivovarit/collectors/AbstractParallelCollector::lambda$supplier$0 → KILLED

69

1.1
Location : accumulator
Killed by : com.pivovarit.collectors.LifecycleTest.[engine:junit-jupiter]/[class:com.pivovarit.collectors.LifecycleTest]/[method:shouldRejectReuseAfterAbortedTraversal()]
replaced return value with null for com/pivovarit/collectors/AbstractParallelCollector::accumulator → KILLED

70

1.1
Location : lambda$accumulator$0
Killed by : none
negated conditional → TIMED_OUT

71

1.1
Location : lambda$accumulator$0
Killed by : none
removed call to com/pivovarit/collectors/Dispatcher::start → TIMED_OUT

73

1.1
Location : lambda$accumulator$1
Killed by : com.pivovarit.collectors.LifecycleTest.[engine:junit-jupiter]/[class:com.pivovarit.collectors.LifecycleTest]/[method:shouldRejectReuseAfterCompletedTraversal()]
replaced return value with null for com/pivovarit/collectors/AbstractParallelCollector::lambda$accumulator$1 → KILLED

79

1.1
Location : combiner
Killed by : com.pivovarit.collectors.test.ParallelismValidationTest.[engine:junit-jupiter]/[class:com.pivovarit.collectors.test.ParallelismValidationTest]/[test-factory:shouldThrowOnParallelStream()]/[dynamic-test:#15]
replaced return value with null for com/pivovarit/collectors/AbstractParallelCollector::combiner → KILLED

86

1.1
Location : finisher
Killed by : com.pivovarit.collectors.LifecycleTest.[engine:junit-jupiter]/[class:com.pivovarit.collectors.LifecycleTest]/[method:shouldRejectReuseAfterEmptyTraversal()]
replaced return value with null for com/pivovarit/collectors/AbstractParallelCollector::finisher → KILLED

88

1.1
Location : lambda$finisher$0
Killed by : none
removed call to com/pivovarit/collectors/Dispatcher::stop → SURVIVED
Covering tests

89

1.1
Location : lambda$finisher$0
Killed by : none
negated conditional → SURVIVED
Covering tests

90

1.1
Location : lambda$finisher$0
Killed by : none
removed call to java/lang/ref/Cleaner$Cleanable::clean → SURVIVED
Covering tests

92

1.1
Location : lambda$finisher$0
Killed by : com.pivovarit.collectors.LifecycleTest.[engine:junit-jupiter]/[class:com.pivovarit.collectors.LifecycleTest]/[method:shouldRejectReuseAfterEmptyTraversal()]
negated conditional → KILLED

2.2
Location : lambda$finisher$0
Killed by : com.pivovarit.collectors.LifecycleTest.[engine:junit-jupiter]/[class:com.pivovarit.collectors.LifecycleTest]/[method:shouldRejectReuseAfterEmptyTraversal()]
changed conditional boundary → KILLED

95

1.1
Location : lambda$finisher$0
Killed by : com.pivovarit.collectors.LifecycleTest.[engine:junit-jupiter]/[class:com.pivovarit.collectors.LifecycleTest]/[method:shouldRejectReuseAfterEmptyTraversal()]
replaced return value with null for com/pivovarit/collectors/AbstractParallelCollector::lambda$finisher$0 → KILLED

Active mutators

Tests examined


Report generated by PIT 1.30.0 support