From 88c4c2276590a59b795fb62bf8bd55c12ef8a082 Mon Sep 17 00:00:00 2001 From: Henri Tremblay Date: Sat, 2 Jul 2022 00:06:32 -0400 Subject: [PATCH] Pause should not leave open an ExecutorService, using common pool fixes the issue (close #268) --- .../java/org/assertj/swing/timing/Pause.java | 86 ++++++++++--------- 1 file changed, 44 insertions(+), 42 deletions(-) diff --git a/assertj-swing/src/main/java/org/assertj/swing/timing/Pause.java b/assertj-swing/src/main/java/org/assertj/swing/timing/Pause.java index 53e19328..927c6e19 100644 --- a/assertj-swing/src/main/java/org/assertj/swing/timing/Pause.java +++ b/assertj-swing/src/main/java/org/assertj/swing/timing/Pause.java @@ -16,13 +16,14 @@ import static org.assertj.core.util.Preconditions.checkNotNullOrEmpty; import static org.assertj.swing.timing.Timeout.timeout; -import java.util.concurrent.Callable; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.stream.Collectors; +import java.util.stream.Stream; import javax.annotation.Nonnull; @@ -38,7 +39,6 @@ public final class Pause { private static final Timeout DEFAULT_TIMEOUT = timeout(); private static final int SLEEP_INTERVAL = 10; - private static final ExecutorService EXECUTOR_SERVICE = Executors.newCachedThreadPool(); /** * Waits until the given condition is satisfied. @@ -76,36 +76,32 @@ public static void pause(@Nonnull Condition condition, @Nonnull Timeout timeout) public static void pause(@Nonnull final Condition condition, final long timeout) { checkNotNull(condition); try { - Callable task = new Callable() { - @Override - public Object call() { - while (!Thread.currentThread().isInterrupted() && !condition.test()) { - pause(); - } - return condition; - } - }; - performPause(task, timeout, condition); + performPause(timeout, condition); } finally { condition.done(); } } - private static void performPause(Callable task, long timeout, Object value) { - Future futureResult = EXECUTOR_SERVICE.submit(task); + private static void performPause(long timeout, Condition condition) { + AtomicBoolean cancelled = new AtomicBoolean(false); + + Runnable runnable = () -> { + while (!cancelled.get() && !Thread.currentThread().isInterrupted() && !condition.test()) { + pause(); + } + }; + Future future = CompletableFuture.runAsync(runnable); try { - futureResult.get(timeout, TimeUnit.MILLISECONDS); - } catch (TimeoutException ex) { - futureResult.cancel(true); - throw new WaitTimedOutError(String.format("Timed out waiting for %s", - new StandardRepresentation().toStringOf(value))); - } catch (InterruptedException e) { - e.printStackTrace(); + future.get(timeout, TimeUnit.MILLISECONDS); } catch (ExecutionException e) { if (e.getCause() instanceof RuntimeException) { throw (RuntimeException) e.getCause(); } + } catch (InterruptedException e) { e.printStackTrace(); + } catch (TimeoutException e) { + cancelled.set(true); + throw new WaitTimedOutError("Timed out waiting for " + new StandardRepresentation().toStringOf(condition)); } } @@ -152,31 +148,37 @@ public static void pause(@Nonnull final Condition[] conditions, final long timeo for (Condition condition : conditions) { checkNotNull(condition); } + Condition condition = allConditions(conditions); try { - Callable task = new Callable() { - @Override - public Object call() { - while (!Thread.currentThread().isInterrupted() && !areSatisfied(conditions)) { - pause(); - } - return conditions; - } - }; - performPause(task, timeout, conditions); + performPause(timeout, condition); } finally { - for (Condition condition : conditions) { - condition.done(); - } + condition.done(); } } - private static boolean areSatisfied(@Nonnull Condition[] conditions) { - for (Condition condition : conditions) { - if (!condition.test()) { - return false; + private static Condition allConditions(@Nonnull Condition[] conditions) { + String description = Stream.of(conditions) + .map(Condition::toString) + .collect(Collectors.joining("\n", "=>", "")); + return new Condition(description) { + @Override + public boolean test() { + for (Condition condition : conditions) { + if (!condition.test()) { + return false; + } + } + return true; } - } - return true; + + @Override + protected void done() { + for (Condition condition : conditions) { + condition.done(); + } + } + }; + } /**