15 |
|
*/ |
16 |
|
|
17 |
|
package java.util.concurrent; |
18 |
+ |
import java.util.AbstractList; |
19 |
|
import java.util.Arrays; |
20 |
|
import java.util.Collection; |
21 |
< |
import java.util.List; |
22 |
< |
import java.util.AbstractList; |
21 |
> |
import java.util.Collections; |
22 |
> |
import java.util.ConcurrentModificationException; |
23 |
|
import java.util.Iterator; |
24 |
+ |
import java.util.List; |
25 |
|
import java.util.ListIterator; |
24 |
– |
import java.util.RandomAccess; |
26 |
|
import java.util.NoSuchElementException; |
27 |
< |
import java.util.ConcurrentModificationException; |
27 |
> |
import java.util.RandomAccess; |
28 |
|
import java.util.Spliterator; |
29 |
+ |
import java.util.concurrent.locks.ReentrantLock; |
30 |
+ |
import java.util.function.Consumer; |
31 |
|
import java.util.stream.Stream; |
32 |
|
import java.util.stream.Streams; |
30 |
– |
import java.util.function.Consumer; |
31 |
– |
import java.util.concurrent.locks.ReentrantLock; |
33 |
|
|
34 |
|
/** |
35 |
|
* A thread-safe variant of {@link java.util.ArrayList} in which all mutative |
983 |
|
return new COWIterator<E>(elements, index); |
984 |
|
} |
985 |
|
|
986 |
+ |
Spliterator<E> spliterator() { |
987 |
+ |
return Collections.arraySnapshotSpliterator |
988 |
+ |
(getArray(), Spliterator.IMMUTABLE | Spliterator.ORDERED); |
989 |
+ |
} |
990 |
+ |
|
991 |
|
public Stream<E> stream() { |
992 |
< |
int flags = Streams.STREAM_IS_ORDERED | Streams.STREAM_IS_SIZED; |
993 |
< |
Object[] a = getArray(); |
988 |
< |
int n = a.length; |
989 |
< |
return Streams.stream |
990 |
< |
(() -> new COWSpliterator<E>(a, 0, n), flags); |
992 |
> |
return Streams.stream(spliterator()); |
993 |
> |
|
994 |
|
} |
995 |
|
public Stream<E> parallelStream() { |
996 |
< |
int flags = Streams.STREAM_IS_ORDERED | Streams.STREAM_IS_SIZED; |
994 |
< |
Object[] a = getArray(); |
995 |
< |
int n = a.length; |
996 |
< |
return Streams.parallelStream |
997 |
< |
(() -> new COWSpliterator<E>(a, 0, n), flags); |
996 |
> |
return Streams.parallelStream(spliterator()); |
997 |
|
} |
998 |
|
|
999 |
|
static final class COWIterator<E> implements ListIterator<E> { |
1267 |
|
} |
1268 |
|
} |
1269 |
|
|
1270 |
< |
public Stream<E> stream() { |
1272 |
< |
int flags = Streams.STREAM_IS_ORDERED | Streams.STREAM_IS_SIZED; |
1270 |
> |
Spliterator<E> spliterator() { |
1271 |
|
int lo = offset; |
1272 |
|
int hi = offset + size; |
1273 |
|
Object[] a = expectedArray; |
1275 |
|
throw new ConcurrentModificationException(); |
1276 |
|
if (lo < 0 || hi > a.length) |
1277 |
|
throw new IndexOutOfBoundsException(); |
1278 |
< |
return Streams.stream |
1279 |
< |
(() -> new COWSpliterator<E>(a, lo, hi), flags); |
1278 |
> |
return Collections.arraySnapshotSpliterator |
1279 |
> |
(a, lo, hi, Spliterator.IMMUTABLE | Spliterator.ORDERED); |
1280 |
|
} |
1281 |
|
|
1282 |
< |
public Stream<E> parallelStream() { |
1283 |
< |
int flags = Streams.STREAM_IS_ORDERED | Streams.STREAM_IS_SIZED; |
1286 |
< |
int lo = offset; |
1287 |
< |
int hi = offset + size; |
1288 |
< |
Object[] a = expectedArray; |
1289 |
< |
if (l.getArray() != a) |
1290 |
< |
throw new ConcurrentModificationException(); |
1291 |
< |
if (lo < 0 || hi > a.length) |
1292 |
< |
throw new IndexOutOfBoundsException(); |
1293 |
< |
return Streams.parallelStream |
1294 |
< |
(() -> new COWSpliterator<E>(a, lo, hi), flags); |
1282 |
> |
public Stream<E> stream() { |
1283 |
> |
return Streams.stream(spliterator()); |
1284 |
|
} |
1285 |
|
|
1286 |
+ |
public Stream<E> parallelStream() { |
1287 |
+ |
return Streams.parallelStream(spliterator()); |
1288 |
+ |
} |
1289 |
|
} |
1290 |
|
|
1299 |
– |
|
1291 |
|
private static class COWSubListIterator<E> implements ListIterator<E> { |
1292 |
|
private final ListIterator<E> it; |
1293 |
|
private final int offset; |
1342 |
|
} |
1343 |
|
} |
1344 |
|
|
1354 |
– |
/** Index-based split-by-two Spliterator */ |
1355 |
– |
static final class COWSpliterator<E> implements Spliterator<E> { |
1356 |
– |
private final Object[] array; |
1357 |
– |
private int index; // current index, modified on advance/split |
1358 |
– |
private final int fence; // one past last index |
1359 |
– |
|
1360 |
– |
/** Create new spliterator covering the given array and range */ |
1361 |
– |
COWSpliterator(Object[] array, int origin, int fence) { |
1362 |
– |
this.array = array; this.index = origin; this.fence = fence; |
1363 |
– |
} |
1364 |
– |
|
1365 |
– |
public COWSpliterator<E> trySplit() { |
1366 |
– |
int lo = index, mid = (lo + fence) >>> 1; |
1367 |
– |
return (lo >= mid) ? null : |
1368 |
– |
new COWSpliterator<E>(array, lo, index = mid); |
1369 |
– |
} |
1370 |
– |
|
1371 |
– |
public void forEach(Consumer<? super E> block) { |
1372 |
– |
Object[] a; int i, hi; // hoist accesses and checks from loop |
1373 |
– |
if (block == null) |
1374 |
– |
throw new NullPointerException(); |
1375 |
– |
if ((a = array).length >= (hi = fence) && |
1376 |
– |
(i = index) >= 0 && i < hi) { |
1377 |
– |
index = hi; |
1378 |
– |
do { |
1379 |
– |
@SuppressWarnings("unchecked") E e = (E) a[i]; |
1380 |
– |
block.accept(e); |
1381 |
– |
} while (++i < hi); |
1382 |
– |
} |
1383 |
– |
} |
1384 |
– |
|
1385 |
– |
public boolean tryAdvance(Consumer<? super E> block) { |
1386 |
– |
if (index >= 0 && index < fence) { |
1387 |
– |
@SuppressWarnings("unchecked") E e = (E) array[index++]; |
1388 |
– |
block.accept(e); |
1389 |
– |
return true; |
1390 |
– |
} |
1391 |
– |
return false; |
1392 |
– |
} |
1393 |
– |
|
1394 |
– |
public long estimateSize() { return (long)(fence - index); } |
1395 |
– |
public boolean hasExactSize() { return true; } |
1396 |
– |
public boolean hasExactSplits() { return true; } |
1397 |
– |
} |
1398 |
– |
|
1399 |
– |
|
1345 |
|
// Support for resetting lock while deserializing |
1346 |
|
private void resetLock() { |
1347 |
|
UNSAFE.putObjectVolatile(this, lockOffset, new ReentrantLock()); |