6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24 /*
25 * @test
26 * @enablePreview
27 * @run testng TestSpliterator
28 */
29
30 import java.lang.foreign.*;
31
32 import java.lang.invoke.VarHandle;
33 import java.util.LinkedList;
34 import java.util.List;
35 import java.util.Spliterator;
36 import java.util.concurrent.CountedCompleter;
37 import java.util.concurrent.RecursiveTask;
38 import java.util.concurrent.atomic.AtomicLong;
39 import java.util.stream.LongStream;
40
41 import org.testng.annotations.*;
42
43 import static org.testng.Assert.*;
44
45 public class TestSpliterator {
46
47 static final VarHandle INT_HANDLE = ValueLayout.JAVA_INT.arrayElementVarHandle();
48
49 final static int CARRIER_SIZE = 4;
50
51 @Test(dataProvider = "splits")
52 public void testSum(int size, int threshold) {
53 SequenceLayout layout = MemoryLayout.sequenceLayout(size, ValueLayout.JAVA_INT);
54
55 //setup
56 try (Arena arena = Arena.ofShared()) {
57 MemorySegment segment = arena.allocate(layout);;
58 for (int i = 0; i < layout.elementCount(); i++) {
59 INT_HANDLE.set(segment, (long) i, i);
60 }
61 long expected = LongStream.range(0, layout.elementCount()).sum();
62 //serial
63 long serial = sum(0, segment);
64 assertEquals(serial, expected);
65 //parallel counted completer
66 long parallelCounted = new SumSegmentCounted(null, segment.spliterator(layout.elementLayout()), threshold).invoke();
67 assertEquals(parallelCounted, expected);
68 //parallel recursive action
69 long parallelRecursive = new SumSegmentRecursive(segment.spliterator(layout.elementLayout()), threshold).invoke();
70 assertEquals(parallelRecursive, expected);
71 //parallel stream
72 long streamParallel = segment.elements(layout.elementLayout()).parallel()
73 .reduce(0L, TestSpliterator::sumSingle, Long::sum);
74 assertEquals(streamParallel, expected);
75 }
76 }
77
78 @Test
79 public void testSumSameThread() {
80 SequenceLayout layout = MemoryLayout.sequenceLayout(1024, ValueLayout.JAVA_INT);
81
82 //setup
83 Arena scope = Arena.ofAuto();
84 MemorySegment segment = scope.allocate(layout);
85 for (int i = 0; i < layout.elementCount(); i++) {
86 INT_HANDLE.set(segment, (long) i, i);
87 }
88 long expected = LongStream.range(0, layout.elementCount()).sum();
89
90 //check that a segment w/o ACQUIRE access mode can still be used from same thread
91 AtomicLong spliteratorSum = new AtomicLong();
92 segment.spliterator(layout.elementLayout())
93 .forEachRemaining(s -> spliteratorSum.addAndGet(sumSingle(0L, s)));
94 assertEquals(spliteratorSum.get(), expected);
95 }
96
97 @Test(expectedExceptions = IllegalArgumentException.class)
98 public void testBadSpliteratorElementSizeTooBig() {
99 Arena scope = Arena.ofAuto();
100 scope.allocate(2, 1)
101 .spliterator(ValueLayout.JAVA_INT);
102 }
103
104 @Test(expectedExceptions = IllegalArgumentException.class)
105 public void testBadStreamElementSizeTooBig() {
106 Arena scope = Arena.ofAuto();
143 .spliterator(MemoryLayout.sequenceLayout(0, ValueLayout.JAVA_INT));
144 }
145
146 @Test(expectedExceptions = IllegalArgumentException.class)
147 public void testBadStreamElementSizeZero() {
148 Arena scope = Arena.ofAuto();
149 scope.allocate(7, 1)
150 .elements(MemoryLayout.sequenceLayout(0, ValueLayout.JAVA_INT));
151 }
152
153 @Test(expectedExceptions = IllegalArgumentException.class)
154 public void testHyperAligned() {
155 Arena scope = Arena.ofAuto();
156 MemorySegment segment = scope.allocate(8, 1);
157 // compute an alignment constraint (in bytes) which exceed that of the native segment
158 long bigByteAlign = Long.lowestOneBit(segment.address()) << 1;
159 segment.elements(MemoryLayout.sequenceLayout(2, ValueLayout.JAVA_INT.withByteAlignment(bigByteAlign)));
160 }
161
162 static long sumSingle(long acc, MemorySegment segment) {
163 return acc + (int)INT_HANDLE.get(segment, 0L);
164 }
165
166 static long sum(long start, MemorySegment segment) {
167 long sum = start;
168 int length = (int)segment.byteSize();
169 for (int i = 0 ; i < length / CARRIER_SIZE ; i++) {
170 sum += (int)INT_HANDLE.get(segment, (long)i);
171 }
172 return sum;
173 }
174
175 static class SumSegmentCounted extends CountedCompleter<Long> {
176
177 final long threshold;
178 long localSum = 0;
179 List<SumSegmentCounted> children = new LinkedList<>();
180
181 private Spliterator<MemorySegment> segmentSplitter;
182
183 SumSegmentCounted(SumSegmentCounted parent, Spliterator<MemorySegment> segmentSplitter, long threshold) {
184 super(parent);
185 this.segmentSplitter = segmentSplitter;
186 this.threshold = threshold;
187 }
188
189 @Override
190 public void compute() {
|
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24 /*
25 * @test
26 * @run testng TestSpliterator
27 */
28
29 import java.lang.foreign.*;
30
31 import java.lang.invoke.VarHandle;
32 import java.util.LinkedList;
33 import java.util.List;
34 import java.util.Spliterator;
35 import java.util.concurrent.CountedCompleter;
36 import java.util.concurrent.RecursiveTask;
37 import java.util.concurrent.atomic.AtomicLong;
38 import java.util.stream.LongStream;
39
40 import org.testng.annotations.*;
41
42 import static org.testng.Assert.*;
43
44 public class TestSpliterator {
45
46 final static int CARRIER_SIZE = 4;
47
48 @Test(dataProvider = "splits")
49 public void testSum(int size, int threshold) {
50 SequenceLayout layout = MemoryLayout.sequenceLayout(size, ValueLayout.JAVA_INT);
51
52 //setup
53 try (Arena arena = Arena.ofShared()) {
54 MemorySegment segment = arena.allocate(layout);;
55 for (int i = 0; i < layout.elementCount(); i++) {
56 segment.setAtIndex(ValueLayout.JAVA_INT, i, i);
57 }
58 long expected = LongStream.range(0, layout.elementCount()).sum();
59 //serial
60 long serial = sum(0, segment);
61 assertEquals(serial, expected);
62 //parallel counted completer
63 long parallelCounted = new SumSegmentCounted(null, segment.spliterator(layout.elementLayout()), threshold).invoke();
64 assertEquals(parallelCounted, expected);
65 //parallel recursive action
66 long parallelRecursive = new SumSegmentRecursive(segment.spliterator(layout.elementLayout()), threshold).invoke();
67 assertEquals(parallelRecursive, expected);
68 //parallel stream
69 long streamParallel = segment.elements(layout.elementLayout()).parallel()
70 .reduce(0L, TestSpliterator::sumSingle, Long::sum);
71 assertEquals(streamParallel, expected);
72 }
73 }
74
75 @Test
76 public void testSumSameThread() {
77 SequenceLayout layout = MemoryLayout.sequenceLayout(1024, ValueLayout.JAVA_INT);
78
79 //setup
80 Arena scope = Arena.ofAuto();
81 MemorySegment segment = scope.allocate(layout);
82 for (int i = 0; i < layout.elementCount(); i++) {
83 segment.setAtIndex(ValueLayout.JAVA_INT, i, i);
84 }
85 long expected = LongStream.range(0, layout.elementCount()).sum();
86
87 //check that a segment w/o ACQUIRE access mode can still be used from same thread
88 AtomicLong spliteratorSum = new AtomicLong();
89 segment.spliterator(layout.elementLayout())
90 .forEachRemaining(s -> spliteratorSum.addAndGet(sumSingle(0L, s)));
91 assertEquals(spliteratorSum.get(), expected);
92 }
93
94 @Test(expectedExceptions = IllegalArgumentException.class)
95 public void testBadSpliteratorElementSizeTooBig() {
96 Arena scope = Arena.ofAuto();
97 scope.allocate(2, 1)
98 .spliterator(ValueLayout.JAVA_INT);
99 }
100
101 @Test(expectedExceptions = IllegalArgumentException.class)
102 public void testBadStreamElementSizeTooBig() {
103 Arena scope = Arena.ofAuto();
140 .spliterator(MemoryLayout.sequenceLayout(0, ValueLayout.JAVA_INT));
141 }
142
143 @Test(expectedExceptions = IllegalArgumentException.class)
144 public void testBadStreamElementSizeZero() {
145 Arena scope = Arena.ofAuto();
146 scope.allocate(7, 1)
147 .elements(MemoryLayout.sequenceLayout(0, ValueLayout.JAVA_INT));
148 }
149
150 @Test(expectedExceptions = IllegalArgumentException.class)
151 public void testHyperAligned() {
152 Arena scope = Arena.ofAuto();
153 MemorySegment segment = scope.allocate(8, 1);
154 // compute an alignment constraint (in bytes) which exceed that of the native segment
155 long bigByteAlign = Long.lowestOneBit(segment.address()) << 1;
156 segment.elements(MemoryLayout.sequenceLayout(2, ValueLayout.JAVA_INT.withByteAlignment(bigByteAlign)));
157 }
158
159 static long sumSingle(long acc, MemorySegment segment) {
160 return acc + segment.getAtIndex(ValueLayout.JAVA_INT, 0);
161 }
162
163 static long sum(long start, MemorySegment segment) {
164 long sum = start;
165 int length = (int)segment.byteSize();
166 for (int i = 0 ; i < length / CARRIER_SIZE ; i++) {
167 sum += segment.getAtIndex(ValueLayout.JAVA_INT, i);
168 }
169 return sum;
170 }
171
172 static class SumSegmentCounted extends CountedCompleter<Long> {
173
174 final long threshold;
175 long localSum = 0;
176 List<SumSegmentCounted> children = new LinkedList<>();
177
178 private Spliterator<MemorySegment> segmentSplitter;
179
180 SumSegmentCounted(SumSegmentCounted parent, Spliterator<MemorySegment> segmentSplitter, long threshold) {
181 super(parent);
182 this.segmentSplitter = segmentSplitter;
183 this.threshold = threshold;
184 }
185
186 @Override
187 public void compute() {
|