use of java8.util.function.Predicate in project streamsupport by stefan-zobel.
the class CompletableFutureTest method testMinimalCompletionStage_minimality.
/**
* Minimal completion stages throw UOE for most non-CompletionStage methods
*/
public void testMinimalCompletionStage_minimality() {
if (!testImplementationDetails)
return;
Function<Method, String> toSignature = method -> method.getName() + Arrays.toString(method.getParameterTypes());
Predicate<Method> isNotStatic = method -> (method.getModifiers() & Modifier.STATIC) == 0;
List<Method> minimalMethods = RefStreams.of(Object.class, CompletionStage.class).flatMap(klazz -> RefStreams.of(klazz.getMethods())).filter(isNotStatic).collect(Collectors.toList());
// Methods from CompletableFuture permitted NOT to throw UOE
String[] signatureWhitelist = { "newIncompleteFuture[]", "defaultExecutor[]", "minimalCompletionStage[]", "copy[]" };
Set<String> permittedMethodSignatures = RefStreams.concat(StreamSupport.stream(minimalMethods).map(toSignature), RefStreams.of(signatureWhitelist)).collect(Collectors.toSet());
List<Method> allMethods = RefStreams.of(CompletableFuture.class.getMethods()).filter(isNotStatic).filter(method -> !permittedMethodSignatures.contains(toSignature.apply(method))).collect(Collectors.toList());
List<CompletionStage<Integer>> stages = new ArrayList<CompletionStage<Integer>>();
CompletionStage<Integer> min = new CompletableFuture<Integer>().minimalCompletionStage();
stages.add(min);
stages.add(min.thenApply(x -> x));
stages.add(CompletableFuture.completedStage(1));
stages.add(CompletableFuture.failedStage(new CFException()));
List<Method> bugs = new ArrayList<>();
for (Method method : allMethods) {
Class<?>[] parameterTypes = method.getParameterTypes();
Object[] args = new Object[parameterTypes.length];
// Manufacture boxed primitives for primitive params
for (int i = 0; i < args.length; i++) {
Class<?> type = parameterTypes[i];
if (type == boolean.class)
args[i] = false;
else if (type == int.class)
args[i] = 0;
else if (type == long.class)
args[i] = 0L;
}
for (CompletionStage<Integer> stage : stages) {
try {
method.invoke(stage, args);
bugs.add(method);
} catch (java.lang.reflect.InvocationTargetException expected) {
if (!(expected.getCause() instanceof UnsupportedOperationException)) {
bugs.add(method);
// expected.getCause().printStackTrace();
}
} catch (Exception bad) {
throw new Error(bad);
}
}
}
if (!bugs.isEmpty())
throw new Error("Methods did not throw UOE: " + bugs);
}
use of java8.util.function.Predicate in project streamsupport by stefan-zobel.
the class ForkJoinPool method tryCompensate.
/**
* Tries to decrement counts (sometimes implicitly) and possibly
* arrange for a compensating worker in preparation for blocking:
* If not all core workers yet exist, creates one, else if any are
* unreleased (possibly including caller) releases one, else if
* fewer than the minimum allowed number of workers running,
* checks to see that they are all active, and if so creates an
* extra worker unless over maximum limit and policy is to
* saturate. Most of these steps can fail due to interference, in
* which case 0 is returned so caller will retry. A negative
* return value indicates that the caller doesn't need to
* re-adjust counts when later unblocked.
*
* @return 1: block then adjust, -1: block without adjust, 0 : retry
*/
private int tryCompensate(WorkQueue w) {
int t, n, sp;
long c = ctl;
WorkQueue[] ws = workQueues;
if ((t = (short) (c >>> TC_SHIFT)) >= 0) {
if (ws == null || (n = ws.length) <= 0 || w == null)
// disabled
return 0;
else if ((sp = (int) c) != 0) {
// replace or release
WorkQueue v = ws[sp & (n - 1)];
int wp = w.phase;
long uc = UC_MASK & ((wp < 0) ? c + RC_UNIT : c);
int np = sp & ~UNSIGNALLED;
if (v != null) {
int vp = v.phase;
Thread vt = v.owner;
long nc = ((long) v.stackPred & SP_MASK) | uc;
if (vp == sp && U.compareAndSwapLong(this, CTL, c, nc)) {
v.phase = np;
if (v.source < 0)
LockSupport.unpark(vt);
return (wp < 0) ? -1 : 1;
}
}
return 0;
} else if (// reduce parallelism
(int) (c >> RC_SHIFT) - (short) (bounds & SMASK) > 0) {
long nc = ((RC_MASK & (c - RC_UNIT)) | (~RC_MASK & c));
return U.compareAndSwapLong(this, CTL, c, nc) ? 1 : 0;
} else {
// validate
int md = mode, pc = md & SMASK, tc = pc + t, bc = 0;
boolean unstable = false;
for (int i = 1; i < n; i += 2) {
WorkQueue q;
Thread wt;
Thread.State ts;
if ((q = ws[i]) != null) {
if (q.source == 0) {
unstable = true;
break;
} else {
--tc;
if ((wt = q.owner) != null && ((ts = wt.getState()) == Thread.State.BLOCKED || ts == Thread.State.WAITING))
// worker is blocking
++bc;
}
}
}
if (unstable || tc != 0 || ctl != c)
// inconsistent
return 0;
else if (t + pc >= MAX_CAP || t >= (bounds >>> SWIDTH)) {
Predicate<? super ForkJoinPool> sat;
if ((sat = saturate) != null && sat.test(this))
return -1;
else if (bc < pc) {
// lagging
// for retry spins
Thread.yield();
return 0;
} else
throw new RejectedExecutionException("Thread limit exceeded replacing blocked worker");
}
}
}
// expand pool
long nc = ((c + TC_UNIT) & TC_MASK) | (c & ~TC_MASK);
return U.compareAndSwapLong(this, CTL, c, nc) && createWorker() ? 1 : 0;
}
use of java8.util.function.Predicate in project streamsupport by stefan-zobel.
the class Collection8Test method testRemoveIf.
@SuppressWarnings({ "rawtypes", "unchecked" })
@Test(dataProvider = "Source")
public void testRemoveIf(String description, Supplier<CollectionImplementation> sci) {
CollectionImplementation impl = sci.get();
if (CopyOnWriteArrayList.class.equals(impl.klazz()) || CopyOnWriteArraySet.class.equals(impl.klazz())) {
return;
}
Collection c = impl.emptyCollection();
boolean ordered = Spliterators.spliterator(c).hasCharacteristics(Spliterator.ORDERED);
ThreadLocalRandom rnd = ThreadLocalRandom.current();
int n = rnd.nextInt(6);
for (int i = 0; i < n; i++) c.add(impl.makeElement(i));
AtomicReference threwAt = new AtomicReference<>(null);
List<?> orig = rnd.nextBoolean() ? new ArrayList<>(c) : Arrays.asList(c.toArray());
// Merely creating an iterator can change ArrayBlockingQueue behavior
Iterator<?> it = rnd.nextBoolean() ? c.iterator() : null;
ArrayList survivors = new ArrayList<>();
ArrayList accepts = new ArrayList<>();
ArrayList rejects = new ArrayList<>();
Predicate randomPredicate = e -> {
assertNull(threwAt.get());
switch(rnd.nextInt(3)) {
case 0:
accepts.add(e);
return true;
case 1:
rejects.add(e);
return false;
case 2:
threwAt.set(e);
throw new ArithmeticException();
default:
throw new AssertionError();
}
};
try {
try {
boolean modified = Iterables.removeIf(c, randomPredicate);
assertNull(threwAt.get());
assertEquals(modified, accepts.size() > 0);
assertEquals(modified, rejects.size() != n);
assertEquals(accepts.size() + rejects.size(), n);
if (ordered) {
assertEquals(rejects, Arrays.asList(c.toArray()));
} else {
assertEquals(new HashSet<>(rejects), new HashSet<>(Arrays.asList(c.toArray())));
}
} catch (ArithmeticException ok) {
assertNotNull(threwAt.get());
assertTrue(c.contains(threwAt.get()));
}
if (it != null && impl.isConcurrent())
// check for weakly consistent iterator
while (it.hasNext()) assertTrue(orig.contains(it.next()));
switch(rnd.nextInt(4)) {
case 0:
survivors.addAll(c);
break;
case 1:
survivors.addAll(Arrays.asList(c.toArray()));
break;
case 2:
Iterables.forEach(c, survivors::add);
break;
case 3:
for (Object e : c) survivors.add(e);
break;
}
assertTrue(orig.containsAll(accepts));
assertTrue(orig.containsAll(rejects));
assertTrue(orig.containsAll(survivors));
assertTrue(orig.containsAll(c));
assertTrue(c.containsAll(rejects));
assertTrue(c.containsAll(survivors));
assertTrue(survivors.containsAll(rejects));
if (threwAt.get() == null) {
assertEquals(n - accepts.size(), c.size());
for (Object x : accepts) assertFalse(c.contains(x));
} else {
// Two acceptable behaviors: entire removeIf call is one
// transaction, or each element processed is one transaction.
assertTrue(n == c.size() || n == c.size() + accepts.size());
int k = 0;
for (Object x : accepts) if (c.contains(x))
k++;
assertTrue(k == accepts.size() || k == 0);
}
} catch (Throwable ex) {
System.err.println(impl.klazz());
// c is at risk of corruption if we got here, so be lenient
try {
System.err.printf("c=%s%n", c);
} catch (Throwable t) {
t.printStackTrace();
}
System.err.printf("n=%d%n", n);
System.err.printf("orig=%s%n", orig);
System.err.printf("accepts=%s%n", accepts);
System.err.printf("rejects=%s%n", rejects);
System.err.printf("survivors=%s%n", survivors);
System.err.printf("threwAt=%s%n", threwAt.get());
throw ex;
}
}
use of java8.util.function.Predicate in project streamsupport by stefan-zobel.
the class Collection8Test method testRandomElementRemovalDuringTraversal.
/**
* Some elements randomly disappear in the middle of traversal.
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
@Test(dataProvider = "Source")
public void testRandomElementRemovalDuringTraversal(String description, Supplier<CollectionImplementation> sci) {
CollectionImplementation impl = sci.get();
if (CopyOnWriteArrayList.class.equals(impl.klazz()) || CopyOnWriteArraySet.class.equals(impl.klazz())) {
return;
}
if (HAS_JAVA8_SPLITERATOR_BUG && (LinkedBlockingDeque.class.equals(impl.klazz())) || LinkedBlockingQueue.class.equals(impl.klazz())) {
// https://bugs.openjdk.java.net/browse/JDK-8171051
return;
}
Collection c = impl.emptyCollection();
ThreadLocalRandom rnd = ThreadLocalRandom.current();
int n = rnd.nextInt(6);
ArrayList copy = new ArrayList();
for (int i = 0; i < n; i++) {
Object x = impl.makeElement(i);
copy.add(x);
c.add(x);
}
ArrayList iterated = new ArrayList();
ArrayList spliterated = new ArrayList();
ArrayList removed = new ArrayList();
Spliterator<?> s = Spliterators.spliterator(c);
Iterator<?> it = c.iterator();
if (!(s.hasCharacteristics(Spliterator.CONCURRENT) || s.hasCharacteristics(Spliterator.IMMUTABLE)))
return;
for (int i = rnd.nextInt(n + 1); --i >= 0; ) {
assertTrue(s.tryAdvance(e -> {
}));
if (rnd.nextBoolean())
assertTrue(it.hasNext());
it.next();
}
// TODO: many more removal methods
if (rnd.nextBoolean()) {
for (Iterator<?> z = c.iterator(); z.hasNext(); ) {
Object e = z.next();
if (rnd.nextBoolean()) {
try {
z.remove();
} catch (UnsupportedOperationException ok) {
return;
}
removed.add(e);
}
}
} else {
Predicate randomlyRemove = e -> {
if (rnd.nextBoolean()) {
removed.add(e);
return true;
} else
return false;
};
Iterables.removeIf(c, randomlyRemove);
}
s.forEachRemaining(spliterated::add);
while (it.hasNext()) iterated.add(it.next());
assertTrue(copy.containsAll(iterated));
assertTrue(copy.containsAll(spliterated));
assertTrue(copy.containsAll(removed));
if (s.hasCharacteristics(Spliterator.CONCURRENT)) {
ArrayList<?> iteratedAndRemoved = new ArrayList<>(iterated);
ArrayList<?> spliteratedAndRemoved = new ArrayList<>(spliterated);
iteratedAndRemoved.retainAll(removed);
spliteratedAndRemoved.retainAll(removed);
assertTrue(iteratedAndRemoved.size() <= 1);
assertTrue(spliteratedAndRemoved.size() <= 1);
if (testImplementationDetails && !(c instanceof java.util.concurrent.ArrayBlockingQueue))
assertTrue(spliteratedAndRemoved.isEmpty());
}
}
Aggregations