diff --git a/README.md b/README.md
index 8e94b11..efc8187 100644
--- a/README.md
+++ b/README.md
@@ -14,8 +14,8 @@ repositories {
}
dependencies {
- compile 'dev.tommyjs:futur-api:2.4.0'
- compile 'dev.tommyjs:futur-lazy:2.4.0'
+ compile 'dev.tommyjs:futur-api:2.5.0'
+ compile 'dev.tommyjs:futur-lazy:2.5.0'
}
```
### Gradle DSL
@@ -25,8 +25,8 @@ repositories {
}
dependencies {
- implementation("dev.tommyjs:futur-api:2.4.0")
- implementation("dev.tommyjs:futur-lazy:2.4.0")
+ implementation("dev.tommyjs:futur-api:2.5.0")
+ implementation("dev.tommyjs:futur-lazy:2.5.0")
}
```
### Maven
@@ -42,12 +42,12 @@ dependencies {
dev.tommyjs
futur-api
- 2.4.0
+ 2.5.0
dev.tommyjs
futur-lazy
- 2.4.0
+ 2.5.0
```
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
index ffd6e04..88740aa 100644
--- a/build.gradle
+++ b/build.gradle
@@ -14,7 +14,7 @@ nexusPublishing {
subprojects {
group = 'dev.tommyjs'
- version = '2.4.1'
+ version = '2.5.0'
apply plugin: 'java-library'
apply plugin: 'com.github.johnrengelman.shadow'
@@ -48,8 +48,8 @@ subprojects {
}
java {
- sourceCompatibility = JavaVersion.VERSION_22
- targetCompatibility = JavaVersion.VERSION_22
+ sourceCompatibility = JavaVersion.VERSION_23
+ targetCompatibility = JavaVersion.VERSION_23
withSourcesJar()
}
}
\ No newline at end of file
diff --git a/futur-api/src/main/java/dev/tommyjs/futur/executor/ExecutorImpl.java b/futur-api/src/main/java/dev/tommyjs/futur/executor/ExecutorImpl.java
new file mode 100644
index 0000000..dbed16d
--- /dev/null
+++ b/futur-api/src/main/java/dev/tommyjs/futur/executor/ExecutorImpl.java
@@ -0,0 +1,31 @@
+package dev.tommyjs.futur.executor;
+
+import org.jetbrains.annotations.NotNull;
+
+import java.util.concurrent.Executor;
+
+class ExecutorImpl implements PromiseExecutor {
+
+ private final Executor executor;
+
+ public ExecutorImpl(@NotNull Executor executor) {
+ this.executor = executor;
+ }
+
+ @Override
+ public @NotNull Void run(@NotNull Runnable task) {
+ executor.execute(task);
+ return null;
+ }
+
+ @Override
+ public boolean cancel(@NotNull Void task) {
+ return false;
+ }
+
+ @Override
+ public @NotNull PromiseScheduler> scheduler() {
+ return PromiseScheduler.getDefault();
+ }
+
+}
diff --git a/futur-api/src/main/java/dev/tommyjs/futur/executor/ExecutorServiceImpl.java b/futur-api/src/main/java/dev/tommyjs/futur/executor/ExecutorServiceImpl.java
index acefe38..98867fb 100644
--- a/futur-api/src/main/java/dev/tommyjs/futur/executor/ExecutorServiceImpl.java
+++ b/futur-api/src/main/java/dev/tommyjs/futur/executor/ExecutorServiceImpl.java
@@ -2,31 +2,30 @@ package dev.tommyjs.futur.executor;
import org.jetbrains.annotations.NotNull;
+import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
class ExecutorServiceImpl implements PromiseExecutor> {
- private final ScheduledExecutorService service;
+ private final ExecutorService executor;
- public ExecutorServiceImpl(@NotNull ScheduledExecutorService service) {
- this.service = service;
+ public ExecutorServiceImpl(@NotNull ExecutorService executor) {
+ this.executor = executor;
}
@Override
- public Future> run(@NotNull Runnable task) {
- return service.submit(task);
+ public @NotNull Future> run(@NotNull Runnable task) {
+ return executor.submit(task);
}
@Override
- public Future> run(@NotNull Runnable task, long delay, @NotNull TimeUnit unit) {
- return service.schedule(task, delay, unit);
- }
-
- @Override
- public boolean cancel(Future> task) {
+ public boolean cancel(@NotNull Future> task) {
return task.cancel(true);
}
+ @Override
+ public @NotNull PromiseScheduler> scheduler() {
+ return PromiseScheduler.getDefault();
+ }
+
}
diff --git a/futur-api/src/main/java/dev/tommyjs/futur/executor/PromiseExecutor.java b/futur-api/src/main/java/dev/tommyjs/futur/executor/PromiseExecutor.java
index 1143ec2..8389e19 100644
--- a/futur-api/src/main/java/dev/tommyjs/futur/executor/PromiseExecutor.java
+++ b/futur-api/src/main/java/dev/tommyjs/futur/executor/PromiseExecutor.java
@@ -2,9 +2,9 @@ package dev.tommyjs.futur.executor;
import org.jetbrains.annotations.NotNull;
+import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
/**
* An executor that can run tasks and schedule tasks to run in the future.
@@ -42,11 +42,21 @@ public interface PromiseExecutor {
/**
* Creates a new {@link PromiseExecutor} that runs tasks on the given executor service.
*
- * @param service the executor service
+ * @param executor the executor service
* @return the new executor
*/
- static PromiseExecutor> of(@NotNull ScheduledExecutorService service) {
- return new ExecutorServiceImpl(service);
+ static PromiseExecutor> of(@NotNull ScheduledExecutorService executor) {
+ return new ScheduledExecutorImpl(executor);
+ }
+
+ /**
+ * Creates a new {@link PromiseExecutor} that runs tasks on the given executor service.
+ *
+ * @param executor the executor service
+ * @return the new executor
+ */
+ static PromiseExecutor> of(@NotNull ExecutorService executor) {
+ return new ExecutorServiceImpl(executor);
}
/**
@@ -56,18 +66,7 @@ public interface PromiseExecutor {
* @return the task
* @throws Exception if scheduling the task failed
*/
- T run(@NotNull Runnable task) throws Exception;
-
- /**
- * Runs the given task after the given delay.
- *
- * @param task the task
- * @param delay the delay
- * @param unit the time unit
- * @return the task
- * @throws Exception if scheduling the task failed
- */
- T run(@NotNull Runnable task, long delay, @NotNull TimeUnit unit) throws Exception;
+ @NotNull T run(@NotNull Runnable task) throws Exception;
/**
* Cancels the given task if possible. This may interrupt the task mid-execution.
@@ -76,6 +75,8 @@ public interface PromiseExecutor {
* @return {@code true} if the task was cancelled. {@code false} if the task was already completed
* or could not be cancelled.
*/
- boolean cancel(T task);
+ boolean cancel(@NotNull T task);
+
+ @NotNull PromiseScheduler> scheduler();
}
diff --git a/futur-api/src/main/java/dev/tommyjs/futur/executor/PromiseScheduler.java b/futur-api/src/main/java/dev/tommyjs/futur/executor/PromiseScheduler.java
new file mode 100644
index 0000000..dbffd5a
--- /dev/null
+++ b/futur-api/src/main/java/dev/tommyjs/futur/executor/PromiseScheduler.java
@@ -0,0 +1,36 @@
+package dev.tommyjs.futur.executor;
+
+import org.jetbrains.annotations.NotNull;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * A scheduler for running tasks after a delay.
+ */
+public interface PromiseScheduler {
+
+ static @NotNull PromiseScheduler> getDefault() {
+ return PromiseSchedulerDefault.INSTANCE;
+ }
+
+ /**
+ * Runs the given task after the given delay.
+ *
+ * @param task the task
+ * @param delay the delay
+ * @param unit the time unit
+ * @return the task
+ * @throws Exception if scheduling the task failed
+ */
+ @NotNull T schedule(@NotNull Runnable task, long delay, @NotNull TimeUnit unit) throws Exception;
+
+ /**
+ * Cancels the given task if possible. This may interrupt the task mid-execution.
+ *
+ * @param task the task
+ * @return {@code true} if the task was cancelled. {@code false} if the task was already completed
+ * or could not be cancelled.
+ */
+ boolean cancel(@NotNull T task);
+
+}
diff --git a/futur-api/src/main/java/dev/tommyjs/futur/executor/PromiseSchedulerDefault.java b/futur-api/src/main/java/dev/tommyjs/futur/executor/PromiseSchedulerDefault.java
new file mode 100644
index 0000000..950ff5b
--- /dev/null
+++ b/futur-api/src/main/java/dev/tommyjs/futur/executor/PromiseSchedulerDefault.java
@@ -0,0 +1,27 @@
+package dev.tommyjs.futur.executor;
+
+import org.jetbrains.annotations.NotNull;
+
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+
+class PromiseSchedulerDefault implements PromiseScheduler> {
+
+ static final PromiseSchedulerDefault INSTANCE = new PromiseSchedulerDefault();
+
+ private final ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(
+ Thread.ofPlatform().name("promise-scheduler").daemon(true).factory());
+
+ @Override
+ public @NotNull ScheduledFuture> schedule(@NotNull Runnable task, long delay, @NotNull TimeUnit unit) {
+ return executor.schedule(task, delay, unit);
+ }
+
+ @Override
+ public boolean cancel(@NotNull ScheduledFuture> task) {
+ return task.cancel(true);
+ }
+
+}
diff --git a/futur-api/src/main/java/dev/tommyjs/futur/executor/ScheduledExecutorImpl.java b/futur-api/src/main/java/dev/tommyjs/futur/executor/ScheduledExecutorImpl.java
new file mode 100644
index 0000000..0f90f1e
--- /dev/null
+++ b/futur-api/src/main/java/dev/tommyjs/futur/executor/ScheduledExecutorImpl.java
@@ -0,0 +1,37 @@
+package dev.tommyjs.futur.executor;
+
+import org.jetbrains.annotations.NotNull;
+
+import java.util.concurrent.Future;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+class ScheduledExecutorImpl implements PromiseExecutor>, PromiseScheduler> {
+
+ private final ScheduledExecutorService executor;
+
+ public ScheduledExecutorImpl(@NotNull ScheduledExecutorService executor) {
+ this.executor = executor;
+ }
+
+ @Override
+ public @NotNull Future> run(@NotNull Runnable task) {
+ return executor.submit(task);
+ }
+
+ @Override
+ public @NotNull Future> schedule(@NotNull Runnable task, long delay, @NotNull TimeUnit unit) {
+ return executor.schedule(task, delay, unit);
+ }
+
+ @Override
+ public boolean cancel(@NotNull Future> task) {
+ return task.cancel(true);
+ }
+
+ @Override
+ public @NotNull PromiseScheduler> scheduler() {
+ return this;
+ }
+
+}
diff --git a/futur-api/src/main/java/dev/tommyjs/futur/executor/VirtualThreadImpl.java b/futur-api/src/main/java/dev/tommyjs/futur/executor/VirtualThreadImpl.java
index 397efc3..044b74b 100644
--- a/futur-api/src/main/java/dev/tommyjs/futur/executor/VirtualThreadImpl.java
+++ b/futur-api/src/main/java/dev/tommyjs/futur/executor/VirtualThreadImpl.java
@@ -4,15 +4,15 @@ import org.jetbrains.annotations.NotNull;
import java.util.concurrent.TimeUnit;
-class VirtualThreadImpl implements PromiseExecutor {
+class VirtualThreadImpl implements PromiseExecutor, PromiseScheduler {
@Override
- public Thread run(@NotNull Runnable task) {
+ public @NotNull Thread run(@NotNull Runnable task) {
return Thread.ofVirtual().start(task);
}
@Override
- public Thread run(@NotNull Runnable task, long delay, @NotNull TimeUnit unit) {
+ public @NotNull Thread schedule(@NotNull Runnable task, long delay, @NotNull TimeUnit unit) {
return Thread.ofVirtual().start(() -> {
try {
Thread.sleep(unit.toMillis(delay));
@@ -24,7 +24,7 @@ class VirtualThreadImpl implements PromiseExecutor {
}
@Override
- public boolean cancel(Thread task) {
+ public boolean cancel(@NotNull Thread task) {
if (task.isAlive()) {
task.interrupt();
return true;
@@ -33,4 +33,9 @@ class VirtualThreadImpl implements PromiseExecutor {
}
}
+ @Override
+ public @NotNull PromiseScheduler scheduler() {
+ return this;
+ }
+
}
\ No newline at end of file
diff --git a/futur-api/src/main/java/dev/tommyjs/futur/function/FunctionAdapter.java b/futur-api/src/main/java/dev/tommyjs/futur/function/FunctionAdapter.java
new file mode 100644
index 0000000..33905e5
--- /dev/null
+++ b/futur-api/src/main/java/dev/tommyjs/futur/function/FunctionAdapter.java
@@ -0,0 +1,25 @@
+package dev.tommyjs.futur.function;
+
+import org.jetbrains.annotations.NotNull;
+
+public final class FunctionAdapter {
+
+ public static @NotNull ExceptionalFunction adapt(@NotNull ExceptionalConsumer consumer) {
+ return (value) -> {
+ consumer.accept(value);
+ return null;
+ };
+ }
+
+ public static @NotNull ExceptionalFunction adapt(@NotNull ExceptionalRunnable runnable) {
+ return (_) -> {
+ runnable.run();
+ return null;
+ };
+ }
+
+ public static @NotNull ExceptionalFunction adapt(@NotNull ExceptionalSupplier supplier) {
+ return (_) -> supplier.get();
+ }
+
+}
diff --git a/futur-api/src/main/java/dev/tommyjs/futur/promise/AbstractPromise.java b/futur-api/src/main/java/dev/tommyjs/futur/promise/AbstractPromise.java
index 1cdfb28..2ff169e 100644
--- a/futur-api/src/main/java/dev/tommyjs/futur/promise/AbstractPromise.java
+++ b/futur-api/src/main/java/dev/tommyjs/futur/promise/AbstractPromise.java
@@ -1,23 +1,25 @@
package dev.tommyjs.futur.promise;
-import dev.tommyjs.futur.function.ExceptionalConsumer;
-import dev.tommyjs.futur.function.ExceptionalFunction;
-import dev.tommyjs.futur.function.ExceptionalRunnable;
-import dev.tommyjs.futur.function.ExceptionalSupplier;
+import dev.tommyjs.futur.executor.PromiseExecutor;
+import dev.tommyjs.futur.executor.PromiseScheduler;
+import dev.tommyjs.futur.function.*;
import dev.tommyjs.futur.util.PromiseUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
-import java.util.concurrent.*;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.RejectedExecutionException;
+import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
-public abstract class AbstractPromise implements Promise {
+public abstract class AbstractPromise implements Promise {
- public abstract @NotNull AbstractPromiseFactory getFactory();
+ public abstract @NotNull AbstractPromiseFactory getFactory();
protected abstract @NotNull Promise addAnyListener(@NotNull PromiseListener listener);
@@ -37,7 +39,7 @@ public abstract class AbstractPromise implements Promise {
try {
return supplier.get();
} catch (Error error) {
- // Rethrow error so the Thread can shut down
+ // Rethrow error so the Thread can shut down or whatever
throw error;
} catch (Throwable e) {
return handler.apply(e);
@@ -49,7 +51,7 @@ public abstract class AbstractPromise implements Promise {
runnable.run();
} catch (Error error) {
handler.accept(error);
- // Rethrow error so the Thread can shut down
+ // Rethrow error so the Thread can shut down or whatever
throw error;
} catch (Throwable e) {
handler.accept(e);
@@ -104,16 +106,20 @@ public abstract class AbstractPromise implements Promise {
protected T joinCompletionChecked() throws ExecutionException {
PromiseCompletion completion = getCompletion();
- assert completion != null;
- if (completion.isSuccess()) return completion.getResult();
- throw new ExecutionException(completion.getException());
+ if (completion == null) {
+ throw new IllegalStateException("Promise is not completed yet.");
+ }
+
+ return completion.getChecked();
}
protected T joinCompletionUnchecked() {
PromiseCompletion completion = getCompletion();
- assert completion != null;
- if (completion.isSuccess()) return completion.getResult();
- throw new CompletionException(completion.getException());
+ if (completion == null) {
+ throw new IllegalStateException("Promise is not completed yet.");
+ }
+
+ return completion.get();
}
@Override
@@ -205,184 +211,190 @@ public abstract class AbstractPromise implements Promise {
);
}
+ private @NotNull Promise thenApply(@NotNull ExceptionalFunction task, @NotNull PromiseExecutor executor) {
+ CompletablePromise promise = createLinked();
+ addDirectListener(
+ res -> runCompleter(promise, () -> {
+ Runnable runnable = createCompleter(res, promise, task);
+ F future = executor.run(runnable);
+ promise.addDirectListener(_ -> executor.cancel(future));
+ }),
+ promise::completeExceptionally
+ );
+
+ return promise;
+ }
+
+ private @NotNull Promise thenApplyDelayed(
+ @NotNull ExceptionalFunction task, long delay,
+ @NotNull TimeUnit unit, @NotNull PromiseScheduler scheduler
+ ) {
+ CompletablePromise promise = createLinked();
+ addDirectListener(
+ res -> runCompleter(promise, () -> {
+ Runnable runnable = createCompleter(res, promise, task);
+ F future = scheduler.schedule(runnable, delay, unit);
+ promise.addDirectListener(_ -> scheduler.cancel(future));
+ }),
+ promise::completeExceptionally
+ );
+
+ return promise;
+ }
+
+ private @NotNull Promise thenCompose(
+ @NotNull ExceptionalFunction> task,
+ @NotNull PromiseExecutor> executor
+ ) {
+ CompletablePromise promise = createLinked();
+ thenApply(task, executor).addDirectListener(
+ nestedPromise -> {
+ if (nestedPromise == null) {
+ promise.complete(null);
+ } else {
+ PromiseUtil.propagateCompletion(nestedPromise, promise);
+ PromiseUtil.propagateCancel(promise, nestedPromise);
+ }
+ },
+ promise::completeExceptionally
+ );
+
+ return promise;
+ }
+
@Override
public @NotNull Promise thenRunSync(@NotNull ExceptionalRunnable task) {
- return thenApplySync(_ -> {
- task.run();
- return null;
- });
+ return thenApply(FunctionAdapter.adapt(task), getFactory().getSyncExecutor());
}
@Override
public @NotNull Promise thenRunDelayedSync(@NotNull ExceptionalRunnable task, long delay, @NotNull TimeUnit unit) {
- return thenApplyDelayedSync(_ -> {
- task.run();
- return null;
- }, delay, unit);
+ return thenApplyDelayed(FunctionAdapter.adapt(task), delay, unit, getFactory().getSyncExecutor().scheduler());
}
@Override
public @NotNull Promise thenConsumeSync(@NotNull ExceptionalConsumer task) {
- return thenApplySync(result -> {
- task.accept(result);
- return null;
- });
+ return thenApply(FunctionAdapter.adapt(task), getFactory().getSyncExecutor());
}
@Override
public @NotNull Promise thenConsumeDelayedSync(@NotNull ExceptionalConsumer task, long delay, @NotNull TimeUnit unit) {
- return thenApplyDelayedSync(result -> {
- task.accept(result);
- return null;
- }, delay, unit);
+ return thenApplyDelayed(FunctionAdapter.adapt(task), delay, unit, getFactory().getSyncExecutor().scheduler());
}
@Override
public @NotNull Promise thenSupplySync(@NotNull ExceptionalSupplier task) {
- return thenApplySync(_ -> task.get());
+ return thenApply(FunctionAdapter.adapt(task), getFactory().getSyncExecutor());
}
@Override
public @NotNull Promise thenSupplyDelayedSync(@NotNull ExceptionalSupplier task, long delay, @NotNull TimeUnit unit) {
- return thenApplyDelayedSync(_ -> task.get(), delay, unit);
+ return thenApplyDelayed(FunctionAdapter.adapt(task), delay, unit, getFactory().getSyncExecutor().scheduler());
}
@Override
public @NotNull Promise thenApplySync(@NotNull ExceptionalFunction task) {
- CompletablePromise promise = createLinked();
- addDirectListener(
- res -> runCompleter(promise, () -> {
- Runnable runnable = createCompleter(res, promise, task);
- FS future = getFactory().getSyncExecutor().run(runnable);
- promise.addDirectListener(_ -> getFactory().getSyncExecutor().cancel(future));
- }),
- promise::completeExceptionally
- );
-
- return promise;
+ return thenApply(task, getFactory().getSyncExecutor());
}
@Override
public @NotNull Promise thenApplyDelayedSync(@NotNull ExceptionalFunction task, long delay, @NotNull TimeUnit unit) {
- CompletablePromise promise = createLinked();
- addDirectListener(
- res -> runCompleter(promise, () -> {
- Runnable runnable = createCompleter(res, promise, task);
- FS future = getFactory().getSyncExecutor().run(runnable, delay, unit);
- promise.addDirectListener(_ -> getFactory().getSyncExecutor().cancel(future));
- }),
- promise::completeExceptionally
- );
-
- return promise;
+ return thenApplyDelayed(task, delay, unit, getFactory().getSyncExecutor().scheduler());
}
@Override
public @NotNull Promise thenComposeSync(@NotNull ExceptionalFunction> task) {
- CompletablePromise promise = createLinked();
- thenApplySync(task).addDirectListener(
- nestedPromise -> {
- if (nestedPromise == null) {
- promise.complete(null);
- } else {
- PromiseUtil.propagateCompletion(nestedPromise, promise);
- PromiseUtil.propagateCancel(promise, nestedPromise);
- }
- },
- promise::completeExceptionally
- );
-
- return promise;
+ return thenCompose(task, getFactory().getSyncExecutor());
}
@Override
public @NotNull Promise thenRunAsync(@NotNull ExceptionalRunnable task) {
- return thenApplyAsync(_ -> {
- task.run();
- return null;
- });
+ return thenApply(FunctionAdapter.adapt(task), getFactory().getAsyncExecutor());
}
@Override
public @NotNull Promise thenRunDelayedAsync(@NotNull ExceptionalRunnable task, long delay, @NotNull TimeUnit unit) {
- return thenApplyDelayedAsync(_ -> {
- task.run();
- return null;
- }, delay, unit);
+ return thenApplyDelayed(FunctionAdapter.adapt(task), delay, unit, getFactory().getAsyncExecutor().scheduler());
}
@Override
public @NotNull Promise thenConsumeAsync(@NotNull ExceptionalConsumer task) {
- return thenApplyAsync(result -> {
- task.accept(result);
- return null;
- });
+ return thenApply(FunctionAdapter.adapt(task), getFactory().getAsyncExecutor());
}
@Override
public @NotNull Promise thenConsumeDelayedAsync(@NotNull ExceptionalConsumer task, long delay, @NotNull TimeUnit unit) {
- return thenApplyDelayedAsync(result -> {
- task.accept(result);
- return null;
- }, delay, unit);
+ return thenApplyDelayed(FunctionAdapter.adapt(task), delay, unit, getFactory().getAsyncExecutor().scheduler());
}
@Override
public @NotNull Promise thenSupplyAsync(@NotNull ExceptionalSupplier task) {
- return thenApplyAsync(_ -> task.get());
+ return thenApply(FunctionAdapter.adapt(task), getFactory().getAsyncExecutor());
}
@Override
public @NotNull Promise thenSupplyDelayedAsync(@NotNull ExceptionalSupplier task, long delay, @NotNull TimeUnit unit) {
- return thenApplyDelayedAsync(_ -> task.get(), delay, unit);
+ return thenApplyDelayed(FunctionAdapter.adapt(task), delay, unit, getFactory().getAsyncExecutor().scheduler());
}
@Override
public @NotNull Promise thenApplyAsync(@NotNull ExceptionalFunction task) {
- CompletablePromise promise = createLinked();
- addDirectListener(
- (res) -> runCompleter(promise, () -> {
- Runnable runnable = createCompleter(res, promise, task);
- FA future = getFactory().getAsyncExecutor().run(runnable);
- promise.addDirectListener(_ -> getFactory().getAsyncExecutor().cancel(future));
- }),
- promise::completeExceptionally
- );
-
- return promise;
+ return thenApply(task, getFactory().getAsyncExecutor());
}
@Override
public @NotNull Promise thenApplyDelayedAsync(@NotNull ExceptionalFunction task, long delay, @NotNull TimeUnit unit) {
- CompletablePromise promise = createLinked();
- addDirectListener(
- res -> runCompleter(promise, () -> {
- Runnable runnable = createCompleter(res, promise, task);
- FA future = getFactory().getAsyncExecutor().run(runnable, delay, unit);
- promise.addDirectListener(_ -> getFactory().getAsyncExecutor().cancel(future));
- }),
- promise::completeExceptionally
- );
-
- return promise;
+ return thenApplyDelayed(task, delay, unit, getFactory().getAsyncExecutor().scheduler());
}
@Override
public @NotNull Promise thenComposeAsync(@NotNull ExceptionalFunction> task) {
- CompletablePromise promise = createLinked();
- thenApplyAsync(task).addDirectListener(
- nestedPromise -> {
- if (nestedPromise == null) {
- promise.complete(null);
- } else {
- PromiseUtil.propagateCompletion(nestedPromise, promise);
- PromiseUtil.propagateCancel(promise, nestedPromise);
- }
- },
- promise::completeExceptionally
- );
+ return thenCompose(task, getFactory().getAsyncExecutor());
+ }
- return promise;
+ @Override
+ public @NotNull Promise thenRunVirtual(@NotNull ExceptionalRunnable task) {
+ return thenApply(FunctionAdapter.adapt(task), getFactory().getVirtualExecutor());
+ }
+
+ @Override
+ public @NotNull Promise thenRunDelayedVirtual(@NotNull ExceptionalRunnable task, long delay, @NotNull TimeUnit unit) {
+ return thenApplyDelayed(FunctionAdapter.adapt(task), delay, unit, getFactory().getVirtualExecutor().scheduler());
+ }
+
+ @Override
+ public @NotNull Promise thenConsumeVirtual(@NotNull ExceptionalConsumer task) {
+ return thenApply(FunctionAdapter.adapt(task), getFactory().getVirtualExecutor());
+ }
+
+ @Override
+ public @NotNull Promise thenConsumeDelayedVirtual(@NotNull ExceptionalConsumer task, long delay, @NotNull TimeUnit unit) {
+ return thenApplyDelayed(FunctionAdapter.adapt(task), delay, unit, getFactory().getVirtualExecutor().scheduler());
+ }
+
+ @Override
+ public @NotNull Promise thenSupplyVirtual(@NotNull ExceptionalSupplier task) {
+ return thenApply(FunctionAdapter.adapt(task), getFactory().getVirtualExecutor());
+ }
+
+ @Override
+ public @NotNull Promise thenSupplyDelayedVirtual(@NotNull ExceptionalSupplier task, long delay, @NotNull TimeUnit unit) {
+ return thenApplyDelayed(FunctionAdapter.adapt(task), delay, unit, getFactory().getVirtualExecutor().scheduler());
+ }
+
+ @Override
+ public @NotNull Promise thenApplyVirtual(@NotNull ExceptionalFunction task) {
+ return thenApply(task, getFactory().getVirtualExecutor());
+ }
+
+ @Override
+ public @NotNull Promise thenApplyDelayedVirtual(@NotNull ExceptionalFunction task, long delay, @NotNull TimeUnit unit) {
+ return thenApplyDelayed(task, delay, unit, getFactory().getVirtualExecutor().scheduler());
+ }
+
+ @Override
+ public @NotNull Promise thenComposeVirtual(@NotNull ExceptionalFunction> task) {
+ return thenCompose(task, getFactory().getVirtualExecutor());
}
@Override
@@ -491,25 +503,6 @@ public abstract class AbstractPromise implements Promise {
);
}
- @Override
- public @NotNull CompletableFuture toFuture() {
- return useCompletion(
- () -> {
- CompletableFuture future = new CompletableFuture<>();
- addDirectListener(future::complete, future::completeExceptionally);
- future.whenComplete((_, e) -> {
- if (e instanceof CancellationException) {
- cancel();
- }
- });
-
- return future;
- },
- CompletableFuture::completedFuture,
- CompletableFuture::failedFuture
- );
- }
-
private static class DeferredExecutionException extends ExecutionException {
}
diff --git a/futur-api/src/main/java/dev/tommyjs/futur/promise/AbstractPromiseFactory.java b/futur-api/src/main/java/dev/tommyjs/futur/promise/AbstractPromiseFactory.java
index 7ce84d1..3d78691 100644
--- a/futur-api/src/main/java/dev/tommyjs/futur/promise/AbstractPromiseFactory.java
+++ b/futur-api/src/main/java/dev/tommyjs/futur/promise/AbstractPromiseFactory.java
@@ -14,22 +14,28 @@ import java.util.*;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.Future;
-public abstract class AbstractPromiseFactory implements PromiseFactory {
+public abstract class AbstractPromiseFactory implements PromiseFactory {
+
+ private static final PromiseExecutor> VIRTUAL = PromiseExecutor.virtualThreaded();
public abstract @NotNull Logger getLogger();
- public abstract @NotNull PromiseExecutor getSyncExecutor();
+ public abstract @NotNull PromiseExecutor> getSyncExecutor();
- public abstract @NotNull PromiseExecutor getAsyncExecutor();
+ public abstract @NotNull PromiseExecutor> getAsyncExecutor();
+
+ public @NotNull PromiseExecutor> getVirtualExecutor() {
+ return VIRTUAL;
+ }
@Override
public @NotNull Promise wrap(@NotNull CompletionStage completion, @Nullable Future future) {
CompletablePromise promise = unresolved();
completion.whenComplete((v, e) -> {
- if (e != null) {
- promise.completeExceptionally(e);
- } else {
+ if (e == null) {
promise.complete(v);
+ } else {
+ promise.completeExceptionally(e);
}
});
diff --git a/futur-api/src/main/java/dev/tommyjs/futur/promise/AsyncPromiseListener.java b/futur-api/src/main/java/dev/tommyjs/futur/promise/AsyncPromiseListener.java
index 799b6be..eb3974b 100644
--- a/futur-api/src/main/java/dev/tommyjs/futur/promise/AsyncPromiseListener.java
+++ b/futur-api/src/main/java/dev/tommyjs/futur/promise/AsyncPromiseListener.java
@@ -5,4 +5,5 @@ package dev.tommyjs.futur.promise;
* executed asynchronously by the {@link PromiseFactory} that created the completed promise.
*/
public interface AsyncPromiseListener extends PromiseListener {
+
}
diff --git a/futur-api/src/main/java/dev/tommyjs/futur/promise/BasePromise.java b/futur-api/src/main/java/dev/tommyjs/futur/promise/BasePromise.java
index 45c8c48..e630fe2 100644
--- a/futur-api/src/main/java/dev/tommyjs/futur/promise/BasePromise.java
+++ b/futur-api/src/main/java/dev/tommyjs/futur/promise/BasePromise.java
@@ -1,5 +1,6 @@
package dev.tommyjs.futur.promise;
+import dev.tommyjs.futur.executor.PromiseScheduler;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -13,7 +14,7 @@ import java.util.concurrent.*;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
@SuppressWarnings({"FieldMayBeFinal"})
-public abstract class BasePromise extends AbstractPromise implements CompletablePromise {
+public abstract class BasePromise extends AbstractPromise implements CompletablePromise {
private static final VarHandle COMPLETION_HANDLE;
private static final VarHandle LISTENERS_HANDLE;
@@ -48,10 +49,10 @@ public abstract class BasePromise extends AbstractPromise
callListeners(cmp);
}
- protected Promise completeExceptionallyDelayed(Throwable e, long delay, TimeUnit unit) {
+ protected Promise completeExceptionallyDelayed(Throwable e, long delay, TimeUnit unit, PromiseScheduler scheduler) {
runCompleter(this, () -> {
- FA future = getFactory().getAsyncExecutor().run(() -> completeExceptionally(e), delay, unit);
- addDirectListener(_ -> getFactory().getAsyncExecutor().cancel(future));
+ F future = scheduler.schedule(() -> completeExceptionally(e), delay, unit);
+ addDirectListener(_ -> scheduler.cancel(future));
});
return this;
@@ -125,16 +126,21 @@ public abstract class BasePromise extends AbstractPromise
return joinCompletionUnchecked();
}
+ @Override
+ public T getNow() {
+ return joinCompletionUnchecked();
+ }
+
@Override
public @NotNull Promise timeout(long time, @NotNull TimeUnit unit) {
Exception e = new CancellationException("Promise timed out after " + time + " " + unit.toString().toLowerCase());
- return completeExceptionallyDelayed(e, time, unit);
+ return completeExceptionallyDelayed(e, time, unit, PromiseScheduler.getDefault());
}
@Override
public @NotNull Promise maxWaitTime(long time, @NotNull TimeUnit unit) {
Exception e = new TimeoutException("Promise stopped waiting after " + time + " " + unit.toString().toLowerCase());
- return completeExceptionallyDelayed(e, time, unit);
+ return completeExceptionallyDelayed(e, time, unit, PromiseScheduler.getDefault());
}
@Override
@@ -162,6 +168,40 @@ public abstract class BasePromise extends AbstractPromise
return completion;
}
+ @Override
+ public @NotNull CompletableFuture toFuture() {
+ return useCompletion(
+ () -> {
+ CompletableFuture future = new CompletableFuture<>();
+ addDirectListener(future::complete, future::completeExceptionally);
+ future.whenComplete((result, error) -> {
+ if (error == null) {
+ complete(result);
+ } else {
+ completeExceptionally(error);
+ }
+ });
+
+ return future;
+ },
+ CompletableFuture::completedFuture,
+ CompletableFuture::failedFuture
+ );
+ }
+
+ @Override
+ public @NotNull CompletionStage toCompletionStage() {
+ return useCompletion(
+ () -> {
+ CompletableFuture future = new CompletableFuture<>();
+ addDirectListener(future::complete, future::completeExceptionally);
+ return future;
+ },
+ CompletableFuture::completedStage,
+ CompletableFuture::failedStage
+ );
+ }
+
private static final class Sync extends AbstractQueuedSynchronizer {
private Sync() {
diff --git a/futur-api/src/main/java/dev/tommyjs/futur/promise/CompletedPromise.java b/futur-api/src/main/java/dev/tommyjs/futur/promise/CompletedPromise.java
index d13fa2c..74602ce 100644
--- a/futur-api/src/main/java/dev/tommyjs/futur/promise/CompletedPromise.java
+++ b/futur-api/src/main/java/dev/tommyjs/futur/promise/CompletedPromise.java
@@ -2,11 +2,9 @@ package dev.tommyjs.futur.promise;
import org.jetbrains.annotations.NotNull;
-import java.util.concurrent.CancellationException;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeUnit;
+import java.util.concurrent.*;
-public abstract class CompletedPromise extends AbstractPromise {
+public abstract class CompletedPromise extends AbstractPromise {
private static final PromiseCompletion> EMPTY = new PromiseCompletion<>();
@@ -59,6 +57,11 @@ public abstract class CompletedPromise extends AbstractPromise getCompletion() {
return completion;
@@ -69,4 +72,19 @@ public abstract class CompletedPromise extends AbstractPromise toFuture() {
+ if (completion.isSuccess()) {
+ return CompletableFuture.completedFuture(completion.result());
+ }
+
+ assert completion.exception() != null;
+ return CompletableFuture.failedFuture(completion.exception());
+ }
+
+ @Override
+ public @NotNull CompletionStage toCompletionStage() {
+ return toFuture();
+ }
+
}
diff --git a/futur-api/src/main/java/dev/tommyjs/futur/promise/Promise.java b/futur-api/src/main/java/dev/tommyjs/futur/promise/Promise.java
index f4628ce..cf31667 100644
--- a/futur-api/src/main/java/dev/tommyjs/futur/promise/Promise.java
+++ b/futur-api/src/main/java/dev/tommyjs/futur/promise/Promise.java
@@ -309,6 +309,116 @@ public interface Promise {
*/
@NotNull Promise thenComposeAsync(@NotNull ExceptionalFunction> task);
+ /**
+ * Chains a task to be executed after this promise completes.
+ * The task will be executed in a virtual thread, immediately after this promise completes.
+ * Cancelling the returned promise will cancel this promise, and consequently any previous promises
+ * in the chain.
+ *
+ * @param task the task to execute
+ * @return a new promise that completes after the task is executed
+ */
+ @NotNull Promise thenRunVirtual(@NotNull ExceptionalRunnable task);
+
+ /**
+ * Chains a task to be executed after this promise completes.
+ * The task will be executed in a virtual thread after the specified delay after this
+ * promise completes. Cancelling the returned promise will cancel this promise, and consequently
+ * any previous promises in the chain.
+ *
+ * @param task the task to execute
+ * @param delay the amount of time to wait before executing the task
+ * @param unit the time unit of the delay
+ * @return a new promise that completes after the task is executed
+ */
+ @NotNull Promise thenRunDelayedVirtual(@NotNull ExceptionalRunnable task, long delay, @NotNull TimeUnit unit);
+
+ /**
+ * Chains a task to be executed after this promise completes. The task will be executed
+ * in a virtual thread immediately after this promise completes, and will be passed
+ * the result of this promise. Cancelling the returned promise will cancel this
+ * promise, and consequently any previous promises in the chain.
+ *
+ * @param task the task to execute
+ * @return a new promise that completes after the task is executed
+ */
+ @NotNull Promise thenConsumeVirtual(@NotNull ExceptionalConsumer task);
+
+ /**
+ * Chains a task to be executed after this promise completes. The task will be executed
+ * in a virtual thread after the specified delay after this promise completes,
+ * and will be passed the result of this promise. Cancelling the returned promise
+ * will cancel this promise, and consequently any previous promises in the chain.
+ *
+ * @param task the task to execute
+ * @param delay the amount of time to wait before executing the task
+ * @param unit the time unit of the delay
+ * @return a new promise that completes after the task is executed
+ */
+ @NotNull Promise thenConsumeDelayedVirtual(@NotNull ExceptionalConsumer task, long delay, @NotNull TimeUnit unit);
+
+ /**
+ * Chains a task to be executed after this promise completes. The task will be executed
+ * in a virtual thread immediately after this promise completes, and will supply a value
+ * to the next promise in the chain. Cancelling the returned promise will
+ * cancel this promise, and consequently any previous promises in the chain.
+ *
+ * @param task the task to execute
+ * @return a new promise that completes, after the task is executed, with the task result
+ */
+ @NotNull Promise thenSupplyVirtual(@NotNull ExceptionalSupplier task);
+
+ /**
+ * Chains a task to be executed after this promise completes. The task will be executed
+ * in a virtual thread after the specified delay after this promise completes,
+ * and will supply a value to the next promise in the chain. Cancelling the returned promise
+ * will cancel this promise, and consequently any previous promises in the chain.
+ *
+ * @param task the task to execute
+ * @param delay the amount of time to wait before executing the task
+ * @param unit the time unit of the delay
+ * @return a new promise that completes, after the task is executed, with the task result
+ */
+ @NotNull Promise thenSupplyDelayedVirtual(@NotNull ExceptionalSupplier task, long delay, @NotNull TimeUnit unit);
+
+ /**
+ * Chains a task to be executed after this promise completes. The task will be executed
+ * in a virtual thread immediately after this promise completes, and will apply the specified
+ * function to the result of this promise in order to supply a value to the next promise
+ * in the chain. Cancelling the returned promise will cancel this promise, and consequently
+ * any previous promises in the chain.
+ *
+ * @param task the task to execute
+ * @return a new promise that completes, after the task is executed, with the task result
+ */
+ @NotNull Promise thenApplyVirtual(@NotNull ExceptionalFunction task);
+
+ /**
+ * Chains a task to be executed after this promise completes. The task will be executed
+ * in a virtual thread after the specified delay after this promise completes, and will apply
+ * the specified function to the result of this promise in order to supply a value to the next
+ * promise in the chain. Cancelling the returned promise will cancel this promise,
+ * and consequently any previous promises in the chain.
+ *
+ * @param task the task to execute
+ * @param delay the amount of time to wait before executing the task
+ * @param unit the time unit of the delay
+ * @return a new promise that completes, after the task is executed, with the task result
+ */
+ @NotNull Promise thenApplyDelayedVirtual(@NotNull ExceptionalFunction task, long delay, @NotNull TimeUnit unit);
+
+ /**
+ * Chains a task to be executed after this promise completes. The task will be executed
+ * in a virtual thread immediately after this promise completes, and will compose the next
+ * promise in the chain from the result of this promise. Cancelling the returned
+ * promise will cancel this promise, and consequently any previous promises in the chain.
+ *
+ * @param task the task to execute
+ * @return a new promise that completes, once this promise and the promise returned by the task are
+ * complete, with the result of the task promise
+ */
+ @NotNull Promise thenComposeVirtual(@NotNull ExceptionalFunction> task);
+
/**
* Adds a listener to this promise that will populate the specified reference with the result of this
* promise upon successful completion. The reference will not be populated if this promise completes
@@ -592,6 +702,18 @@ public interface Promise {
*/
@Nullable PromiseCompletion getCompletion();
+ /**
+ * This method does not block and will return the result immediately if available.
+ * Get result and throws a {@link CompletionException} if the promise completed exceptionally.
+ * If the promise has not completed yet, it will throw an {@link IllegalStateException}.
+ *
+ * @return the result of the promise
+ * @throws IllegalStateException if the promise has not completed yet
+ * @throws CancellationException if the promise was cancelled
+ * @throws CompletionException if the promise completed exceptionally
+ */
+ T getNow();
+
/**
* Returns whether this promise has completed.
*
@@ -601,10 +723,18 @@ public interface Promise {
/**
* Converts this promise to a {@link CompletableFuture}. The returned future will complete with the
- * result of this promise when it completes.
+ * result of this promise and the promise will complete with the result of the future.
*
- * @return a future that will complete with the result of this promise
+ * @return a future linked to this promise
*/
@NotNull CompletableFuture toFuture();
+ /**
+ * Converts this promise to a {@link CompletionStage}.
+ * The returned stage will complete with the result of this promise.
+ *
+ * @return a completion stage linked to this promise result
+ */
+ @NotNull CompletionStage toCompletionStage();
+
}
diff --git a/futur-api/src/main/java/dev/tommyjs/futur/promise/PromiseCompletion.java b/futur-api/src/main/java/dev/tommyjs/futur/promise/PromiseCompletion.java
index 7ca6e9f..9628a7e 100644
--- a/futur-api/src/main/java/dev/tommyjs/futur/promise/PromiseCompletion.java
+++ b/futur-api/src/main/java/dev/tommyjs/futur/promise/PromiseCompletion.java
@@ -4,14 +4,13 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.concurrent.CancellationException;
+import java.util.concurrent.CompletionException;
+import java.util.concurrent.ExecutionException;
/**
* Represents the result of a {@link Promise}, containing either an optional result or an exception.
*/
-public class PromiseCompletion {
-
- private @Nullable T result;
- private @Nullable Throwable exception;
+public record PromiseCompletion(@Nullable T result, @Nullable Throwable exception) {
/**
* Creates a new successful completion.
@@ -19,7 +18,7 @@ public class PromiseCompletion {
* @param result the result
*/
public PromiseCompletion(@Nullable T result) {
- this.result = result;
+ this(result, null);
}
/**
@@ -28,14 +27,14 @@ public class PromiseCompletion {
* @param exception the exception
*/
public PromiseCompletion(@NotNull Throwable exception) {
- this.exception = exception;
+ this(null, exception);
}
/**
* Creates a new successful completion with a result of {@code null}.
*/
public PromiseCompletion() {
- this((T) null);
+ this(null, null);
}
/**
@@ -65,11 +64,6 @@ public class PromiseCompletion {
return exception instanceof CancellationException;
}
- @Deprecated
- public boolean wasCanceled() {
- return wasCancelled();
- }
-
/**
* Gets the result of the completion.
*
@@ -88,4 +82,26 @@ public class PromiseCompletion {
return exception;
}
+ /**
+ * Gets the result or throws a {@link CompletionException} if the completion was exceptional.
+ *
+ * @return the result of the completion
+ * @throws CompletionException if the completion was exceptional
+ */
+ public T get() {
+ if (isSuccess()) return getResult();
+ throw new CompletionException(getException());
+ }
+
+ /**
+ * Gets the result or throws an {@link ExecutionException} if the completion was exceptional.
+ *
+ * @return the result of the completion
+ * @throws ExecutionException if the completion was exceptional
+ */
+ public T getChecked() throws ExecutionException {
+ if (isSuccess()) return getResult();
+ throw new ExecutionException(getException());
+ }
+
}
diff --git a/futur-api/src/main/java/dev/tommyjs/futur/promise/PromiseFactory.java b/futur-api/src/main/java/dev/tommyjs/futur/promise/PromiseFactory.java
index 94ba74b..ff569d3 100644
--- a/futur-api/src/main/java/dev/tommyjs/futur/promise/PromiseFactory.java
+++ b/futur-api/src/main/java/dev/tommyjs/futur/promise/PromiseFactory.java
@@ -31,7 +31,7 @@ public interface PromiseFactory {
*/
static @NotNull PromiseFactory of(@NotNull Logger logger, @NotNull PromiseExecutor> syncExecutor,
@NotNull PromiseExecutor> asyncExecutor) {
- return new PromiseFactoryImpl<>(logger, syncExecutor, asyncExecutor);
+ return new PromiseFactoryImpl(logger, syncExecutor, asyncExecutor);
}
/**
@@ -42,7 +42,7 @@ public interface PromiseFactory {
* @return the new promise factory
*/
static @NotNull PromiseFactory of(@NotNull Logger logger, @NotNull PromiseExecutor> executor) {
- return new PromiseFactoryImpl<>(logger, executor, executor);
+ return new PromiseFactoryImpl(logger, executor, executor);
}
/**
diff --git a/futur-api/src/main/java/dev/tommyjs/futur/promise/PromiseFactoryImpl.java b/futur-api/src/main/java/dev/tommyjs/futur/promise/PromiseFactoryImpl.java
index 7604aeb..6450ba1 100644
--- a/futur-api/src/main/java/dev/tommyjs/futur/promise/PromiseFactoryImpl.java
+++ b/futur-api/src/main/java/dev/tommyjs/futur/promise/PromiseFactoryImpl.java
@@ -5,16 +5,16 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
-public class PromiseFactoryImpl extends AbstractPromiseFactory {
+public class PromiseFactoryImpl extends AbstractPromiseFactory {
private final @NotNull Logger logger;
- private final @NotNull PromiseExecutor syncExecutor;
- private final @NotNull PromiseExecutor asyncExecutor;
+ private final @NotNull PromiseExecutor> syncExecutor;
+ private final @NotNull PromiseExecutor> asyncExecutor;
public PromiseFactoryImpl(
@NotNull Logger logger,
- @NotNull PromiseExecutor syncExecutor,
- @NotNull PromiseExecutor asyncExecutor
+ @NotNull PromiseExecutor> syncExecutor,
+ @NotNull PromiseExecutor> asyncExecutor
) {
this.logger = logger;
this.syncExecutor = syncExecutor;
@@ -47,25 +47,25 @@ public class PromiseFactoryImpl extends AbstractPromiseFactory {
}
@Override
- public @NotNull PromiseExecutor getSyncExecutor() {
+ public @NotNull PromiseExecutor> getSyncExecutor() {
return syncExecutor;
}
@Override
- public @NotNull PromiseExecutor getAsyncExecutor() {
+ public @NotNull PromiseExecutor> getAsyncExecutor() {
return asyncExecutor;
}
- private class PromiseImpl extends BasePromise {
+ private class PromiseImpl extends BasePromise {
@Override
- public @NotNull AbstractPromiseFactory getFactory() {
+ public @NotNull AbstractPromiseFactory getFactory() {
return PromiseFactoryImpl.this;
}
}
- private class CompletedPromiseImpl extends CompletedPromise {
+ private class CompletedPromiseImpl extends CompletedPromise {
public CompletedPromiseImpl(@Nullable T result) {
super(new PromiseCompletion<>(result));
@@ -80,7 +80,7 @@ public class PromiseFactoryImpl extends AbstractPromiseFactory {
}
@Override
- public @NotNull AbstractPromiseFactory getFactory() {
+ public @NotNull AbstractPromiseFactory getFactory() {
return PromiseFactoryImpl.this;
}
diff --git a/futur-api/src/test/java/dev/tommyjs/futur/PromiseTests.java b/futur-api/src/test/java/dev/tommyjs/futur/PromiseTests.java
index 5f3a8ca..8cbabbd 100644
--- a/futur-api/src/test/java/dev/tommyjs/futur/PromiseTests.java
+++ b/futur-api/src/test/java/dev/tommyjs/futur/PromiseTests.java
@@ -245,14 +245,14 @@ public final class PromiseTests {
@Test
public void testImmediate1() {
var promise = promises.start().thenSupply(() -> 10);
- assert promise.isCompleted() && promise instanceof CompletedPromise,?,?>;
+ assert promise.isCompleted() && promise instanceof CompletedPromise;
}
@Test
public void testImmediate2() {
var resolved = promises.resolve(10);
var promise = promises.start().thenCompose(_ -> resolved);
- assert promise.isCompleted() && promise instanceof CompletedPromise,?,?>;
+ assert promise.isCompleted() && promise instanceof CompletedPromise;
}
}
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index cea7a79..e3f5343 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,5 @@
-distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME