From 1af273f9fb456f6b544b8deef94668a3ea6c11b3 Mon Sep 17 00:00:00 2001 From: jinkshower Date: Tue, 6 Aug 2024 20:42:33 +0900 Subject: [PATCH] Add defensive copy Closes #2935 --- .../io/lettuce/core/internal/Futures.java | 7 +++-- .../core/internal/FuturesUnitTests.java | 30 +++++++++++++++++++ 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/src/main/java/io/lettuce/core/internal/Futures.java b/src/main/java/io/lettuce/core/internal/Futures.java index 8c3fcf69f5..97fff0e0aa 100644 --- a/src/main/java/io/lettuce/core/internal/Futures.java +++ b/src/main/java/io/lettuce/core/internal/Futures.java @@ -21,7 +21,7 @@ private Futures() { } /** - * Create a composite {@link CompletableFuture} is composed from the given {@code stages}. + * Create a composite {@link CompletableFuture} that is composed of the given {@code stages}. * * @param stages must not be {@code null}. * @return the composed {@link CompletableFuture}. @@ -32,10 +32,11 @@ public static CompletableFuture allOf(Collection stage : stages) { + for (CompletionStage stage : copies) { futures[index++] = stage.toCompletableFuture(); } diff --git a/src/test/java/io/lettuce/core/internal/FuturesUnitTests.java b/src/test/java/io/lettuce/core/internal/FuturesUnitTests.java index 1e3ec41789..67c0027ae7 100644 --- a/src/test/java/io/lettuce/core/internal/FuturesUnitTests.java +++ b/src/test/java/io/lettuce/core/internal/FuturesUnitTests.java @@ -3,8 +3,12 @@ import static java.util.concurrent.TimeUnit.SECONDS; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import java.util.ArrayList; +import java.util.List; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionStage; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -56,4 +60,30 @@ void awaitAllShouldSetInterruptedBit() { assertThat(Thread.currentThread().isInterrupted()).isTrue(); } + @Test + void allOfShouldNotThrow() throws InterruptedException { + List> stages = new ArrayList<>(); + + for (int i = 0; i < 50; i++) { + stages.add(new CompletableFuture<>()); + } + + Thread thread1 = new Thread(() -> assertDoesNotThrow(() -> { + for (int i = 0; i < 10; i++) { + Futures.allOf(stages); + } + })); + + Thread thread2 = new Thread(() -> { + for (int i = 0; i < 10; i++) { + stages.remove(0); + } + }); + + thread2.start(); + thread1.start(); + + thread2.join(); + thread1.join(); + } }