seperate scheduler and virtual executor promise chain methods

This commit is contained in:
WhatCats
2025-05-28 13:23:23 +02:00
parent a630984cb0
commit fea0575392
21 changed files with 595 additions and 231 deletions

View File

@@ -14,8 +14,8 @@ repositories {
} }
dependencies { dependencies {
compile 'dev.tommyjs:futur-api:2.4.0' compile 'dev.tommyjs:futur-api:2.5.0'
compile 'dev.tommyjs:futur-lazy:2.4.0' compile 'dev.tommyjs:futur-lazy:2.5.0'
} }
``` ```
### Gradle DSL ### Gradle DSL
@@ -25,8 +25,8 @@ repositories {
} }
dependencies { dependencies {
implementation("dev.tommyjs:futur-api:2.4.0") implementation("dev.tommyjs:futur-api:2.5.0")
implementation("dev.tommyjs:futur-lazy:2.4.0") implementation("dev.tommyjs:futur-lazy:2.5.0")
} }
``` ```
### Maven ### Maven
@@ -42,12 +42,12 @@ dependencies {
<dependency> <dependency>
<groupId>dev.tommyjs</groupId> <groupId>dev.tommyjs</groupId>
<artifactId>futur-api</artifactId> <artifactId>futur-api</artifactId>
<version>2.4.0</version> <version>2.5.0</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>dev.tommyjs</groupId> <groupId>dev.tommyjs</groupId>
<artifactId>futur-lazy</artifactId> <artifactId>futur-lazy</artifactId>
<version>2.4.0</version> <version>2.5.0</version>
</dependency> </dependency>
</dependencies> </dependencies>
``` ```

View File

@@ -14,7 +14,7 @@ nexusPublishing {
subprojects { subprojects {
group = 'dev.tommyjs' group = 'dev.tommyjs'
version = '2.4.1' version = '2.5.0'
apply plugin: 'java-library' apply plugin: 'java-library'
apply plugin: 'com.github.johnrengelman.shadow' apply plugin: 'com.github.johnrengelman.shadow'
@@ -48,8 +48,8 @@ subprojects {
} }
java { java {
sourceCompatibility = JavaVersion.VERSION_22 sourceCompatibility = JavaVersion.VERSION_23
targetCompatibility = JavaVersion.VERSION_22 targetCompatibility = JavaVersion.VERSION_23
withSourcesJar() withSourcesJar()
} }
} }

View File

@@ -0,0 +1,31 @@
package dev.tommyjs.futur.executor;
import org.jetbrains.annotations.NotNull;
import java.util.concurrent.Executor;
class ExecutorImpl implements PromiseExecutor<Void> {
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();
}
}

View File

@@ -2,31 +2,30 @@ package dev.tommyjs.futur.executor;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future; import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
class ExecutorServiceImpl implements PromiseExecutor<Future<?>> { class ExecutorServiceImpl implements PromiseExecutor<Future<?>> {
private final ScheduledExecutorService service; private final ExecutorService executor;
public ExecutorServiceImpl(@NotNull ScheduledExecutorService service) { public ExecutorServiceImpl(@NotNull ExecutorService executor) {
this.service = service; this.executor = executor;
} }
@Override @Override
public Future<?> run(@NotNull Runnable task) { public @NotNull Future<?> run(@NotNull Runnable task) {
return service.submit(task); return executor.submit(task);
} }
@Override @Override
public Future<?> run(@NotNull Runnable task, long delay, @NotNull TimeUnit unit) { public boolean cancel(@NotNull Future<?> task) {
return service.schedule(task, delay, unit);
}
@Override
public boolean cancel(Future<?> task) {
return task.cancel(true); return task.cancel(true);
} }
@Override
public @NotNull PromiseScheduler<?> scheduler() {
return PromiseScheduler.getDefault();
}
} }

View File

@@ -2,9 +2,9 @@ package dev.tommyjs.futur.executor;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/** /**
* An executor that can run tasks and schedule tasks to run in the future. * An executor that can run tasks and schedule tasks to run in the future.
@@ -42,11 +42,21 @@ public interface PromiseExecutor<T> {
/** /**
* Creates a new {@link PromiseExecutor} that runs tasks on the given executor service. * 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 * @return the new executor
*/ */
static PromiseExecutor<?> of(@NotNull ScheduledExecutorService service) { static PromiseExecutor<?> of(@NotNull ScheduledExecutorService executor) {
return new ExecutorServiceImpl(service); 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<T> {
* @return the task * @return the task
* @throws Exception if scheduling the task failed * @throws Exception if scheduling the task failed
*/ */
T run(@NotNull Runnable task) throws Exception; @NotNull 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;
/** /**
* Cancels the given task if possible. This may interrupt the task mid-execution. * Cancels the given task if possible. This may interrupt the task mid-execution.
@@ -76,6 +75,8 @@ public interface PromiseExecutor<T> {
* @return {@code true} if the task was cancelled. {@code false} if the task was already completed * @return {@code true} if the task was cancelled. {@code false} if the task was already completed
* or could not be cancelled. * or could not be cancelled.
*/ */
boolean cancel(T task); boolean cancel(@NotNull T task);
@NotNull PromiseScheduler<?> scheduler();
} }

View File

@@ -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<T> {
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);
}

View File

@@ -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<ScheduledFuture<?>> {
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);
}
}

View File

@@ -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<Future<?>>, PromiseScheduler<Future<?>> {
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<Future<?>> scheduler() {
return this;
}
}

View File

@@ -4,15 +4,15 @@ import org.jetbrains.annotations.NotNull;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
class VirtualThreadImpl implements PromiseExecutor<Thread> { class VirtualThreadImpl implements PromiseExecutor<Thread>, PromiseScheduler<Thread> {
@Override @Override
public Thread run(@NotNull Runnable task) { public @NotNull Thread run(@NotNull Runnable task) {
return Thread.ofVirtual().start(task); return Thread.ofVirtual().start(task);
} }
@Override @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(() -> { return Thread.ofVirtual().start(() -> {
try { try {
Thread.sleep(unit.toMillis(delay)); Thread.sleep(unit.toMillis(delay));
@@ -24,7 +24,7 @@ class VirtualThreadImpl implements PromiseExecutor<Thread> {
} }
@Override @Override
public boolean cancel(Thread task) { public boolean cancel(@NotNull Thread task) {
if (task.isAlive()) { if (task.isAlive()) {
task.interrupt(); task.interrupt();
return true; return true;
@@ -33,4 +33,9 @@ class VirtualThreadImpl implements PromiseExecutor<Thread> {
} }
} }
@Override
public @NotNull PromiseScheduler<Thread> scheduler() {
return this;
}
} }

View File

@@ -0,0 +1,25 @@
package dev.tommyjs.futur.function;
import org.jetbrains.annotations.NotNull;
public final class FunctionAdapter {
public static <T, V> @NotNull ExceptionalFunction<T, V> adapt(@NotNull ExceptionalConsumer<T> consumer) {
return (value) -> {
consumer.accept(value);
return null;
};
}
public static <K, V> @NotNull ExceptionalFunction<K, V> adapt(@NotNull ExceptionalRunnable runnable) {
return (_) -> {
runnable.run();
return null;
};
}
public static <K, T> @NotNull ExceptionalFunction<K, T> adapt(@NotNull ExceptionalSupplier<T> supplier) {
return (_) -> supplier.get();
}
}

View File

@@ -1,23 +1,25 @@
package dev.tommyjs.futur.promise; package dev.tommyjs.futur.promise;
import dev.tommyjs.futur.function.ExceptionalConsumer; import dev.tommyjs.futur.executor.PromiseExecutor;
import dev.tommyjs.futur.function.ExceptionalFunction; import dev.tommyjs.futur.executor.PromiseScheduler;
import dev.tommyjs.futur.function.ExceptionalRunnable; import dev.tommyjs.futur.function.*;
import dev.tommyjs.futur.function.ExceptionalSupplier;
import dev.tommyjs.futur.util.PromiseUtil; import dev.tommyjs.futur.util.PromiseUtil;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger; 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.concurrent.atomic.AtomicReference;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Function; import java.util.function.Function;
import java.util.function.Supplier; import java.util.function.Supplier;
public abstract class AbstractPromise<T, FS, FA> implements Promise<T> { public abstract class AbstractPromise<T> implements Promise<T> {
public abstract @NotNull AbstractPromiseFactory<FS, FA> getFactory(); public abstract @NotNull AbstractPromiseFactory getFactory();
protected abstract @NotNull Promise<T> addAnyListener(@NotNull PromiseListener<T> listener); protected abstract @NotNull Promise<T> addAnyListener(@NotNull PromiseListener<T> listener);
@@ -37,7 +39,7 @@ public abstract class AbstractPromise<T, FS, FA> implements Promise<T> {
try { try {
return supplier.get(); return supplier.get();
} catch (Error error) { } catch (Error error) {
// Rethrow error so the Thread can shut down // Rethrow error so the Thread can shut down or whatever
throw error; throw error;
} catch (Throwable e) { } catch (Throwable e) {
return handler.apply(e); return handler.apply(e);
@@ -49,7 +51,7 @@ public abstract class AbstractPromise<T, FS, FA> implements Promise<T> {
runnable.run(); runnable.run();
} catch (Error error) { } catch (Error error) {
handler.accept(error); handler.accept(error);
// Rethrow error so the Thread can shut down // Rethrow error so the Thread can shut down or whatever
throw error; throw error;
} catch (Throwable e) { } catch (Throwable e) {
handler.accept(e); handler.accept(e);
@@ -104,16 +106,20 @@ public abstract class AbstractPromise<T, FS, FA> implements Promise<T> {
protected T joinCompletionChecked() throws ExecutionException { protected T joinCompletionChecked() throws ExecutionException {
PromiseCompletion<T> completion = getCompletion(); PromiseCompletion<T> completion = getCompletion();
assert completion != null; if (completion == null) {
if (completion.isSuccess()) return completion.getResult(); throw new IllegalStateException("Promise is not completed yet.");
throw new ExecutionException(completion.getException()); }
return completion.getChecked();
} }
protected T joinCompletionUnchecked() { protected T joinCompletionUnchecked() {
PromiseCompletion<T> completion = getCompletion(); PromiseCompletion<T> completion = getCompletion();
assert completion != null; if (completion == null) {
if (completion.isSuccess()) return completion.getResult(); throw new IllegalStateException("Promise is not completed yet.");
throw new CompletionException(completion.getException()); }
return completion.get();
} }
@Override @Override
@@ -205,184 +211,190 @@ public abstract class AbstractPromise<T, FS, FA> implements Promise<T> {
); );
} }
private <F, V> @NotNull Promise<V> thenApply(@NotNull ExceptionalFunction<T, V> task, @NotNull PromiseExecutor<F> executor) {
CompletablePromise<V> 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 <F, V> @NotNull Promise<V> thenApplyDelayed(
@NotNull ExceptionalFunction<T, V> task, long delay,
@NotNull TimeUnit unit, @NotNull PromiseScheduler<F> scheduler
) {
CompletablePromise<V> 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 <V> @NotNull Promise<V> thenCompose(
@NotNull ExceptionalFunction<T, Promise<V>> task,
@NotNull PromiseExecutor<?> executor
) {
CompletablePromise<V> 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 @Override
public @NotNull Promise<Void> thenRunSync(@NotNull ExceptionalRunnable task) { public @NotNull Promise<Void> thenRunSync(@NotNull ExceptionalRunnable task) {
return thenApplySync(_ -> { return thenApply(FunctionAdapter.adapt(task), getFactory().getSyncExecutor());
task.run();
return null;
});
} }
@Override @Override
public @NotNull Promise<Void> thenRunDelayedSync(@NotNull ExceptionalRunnable task, long delay, @NotNull TimeUnit unit) { public @NotNull Promise<Void> thenRunDelayedSync(@NotNull ExceptionalRunnable task, long delay, @NotNull TimeUnit unit) {
return thenApplyDelayedSync(_ -> { return thenApplyDelayed(FunctionAdapter.adapt(task), delay, unit, getFactory().getSyncExecutor().scheduler());
task.run();
return null;
}, delay, unit);
} }
@Override @Override
public @NotNull Promise<Void> thenConsumeSync(@NotNull ExceptionalConsumer<T> task) { public @NotNull Promise<Void> thenConsumeSync(@NotNull ExceptionalConsumer<T> task) {
return thenApplySync(result -> { return thenApply(FunctionAdapter.adapt(task), getFactory().getSyncExecutor());
task.accept(result);
return null;
});
} }
@Override @Override
public @NotNull Promise<Void> thenConsumeDelayedSync(@NotNull ExceptionalConsumer<T> task, long delay, @NotNull TimeUnit unit) { public @NotNull Promise<Void> thenConsumeDelayedSync(@NotNull ExceptionalConsumer<T> task, long delay, @NotNull TimeUnit unit) {
return thenApplyDelayedSync(result -> { return thenApplyDelayed(FunctionAdapter.adapt(task), delay, unit, getFactory().getSyncExecutor().scheduler());
task.accept(result);
return null;
}, delay, unit);
} }
@Override @Override
public <V> @NotNull Promise<V> thenSupplySync(@NotNull ExceptionalSupplier<V> task) { public <V> @NotNull Promise<V> thenSupplySync(@NotNull ExceptionalSupplier<V> task) {
return thenApplySync(_ -> task.get()); return thenApply(FunctionAdapter.adapt(task), getFactory().getSyncExecutor());
} }
@Override @Override
public <V> @NotNull Promise<V> thenSupplyDelayedSync(@NotNull ExceptionalSupplier<V> task, long delay, @NotNull TimeUnit unit) { public <V> @NotNull Promise<V> thenSupplyDelayedSync(@NotNull ExceptionalSupplier<V> task, long delay, @NotNull TimeUnit unit) {
return thenApplyDelayedSync(_ -> task.get(), delay, unit); return thenApplyDelayed(FunctionAdapter.adapt(task), delay, unit, getFactory().getSyncExecutor().scheduler());
} }
@Override @Override
public <V> @NotNull Promise<V> thenApplySync(@NotNull ExceptionalFunction<T, V> task) { public <V> @NotNull Promise<V> thenApplySync(@NotNull ExceptionalFunction<T, V> task) {
CompletablePromise<V> promise = createLinked(); return thenApply(task, getFactory().getSyncExecutor());
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;
} }
@Override @Override
public <V> @NotNull Promise<V> thenApplyDelayedSync(@NotNull ExceptionalFunction<T, V> task, long delay, @NotNull TimeUnit unit) { public <V> @NotNull Promise<V> thenApplyDelayedSync(@NotNull ExceptionalFunction<T, V> task, long delay, @NotNull TimeUnit unit) {
CompletablePromise<V> promise = createLinked(); return thenApplyDelayed(task, delay, unit, getFactory().getSyncExecutor().scheduler());
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;
} }
@Override @Override
public <V> @NotNull Promise<V> thenComposeSync(@NotNull ExceptionalFunction<T, Promise<V>> task) { public <V> @NotNull Promise<V> thenComposeSync(@NotNull ExceptionalFunction<T, Promise<V>> task) {
CompletablePromise<V> promise = createLinked(); return thenCompose(task, getFactory().getSyncExecutor());
thenApplySync(task).addDirectListener(
nestedPromise -> {
if (nestedPromise == null) {
promise.complete(null);
} else {
PromiseUtil.propagateCompletion(nestedPromise, promise);
PromiseUtil.propagateCancel(promise, nestedPromise);
}
},
promise::completeExceptionally
);
return promise;
} }
@Override @Override
public @NotNull Promise<Void> thenRunAsync(@NotNull ExceptionalRunnable task) { public @NotNull Promise<Void> thenRunAsync(@NotNull ExceptionalRunnable task) {
return thenApplyAsync(_ -> { return thenApply(FunctionAdapter.adapt(task), getFactory().getAsyncExecutor());
task.run();
return null;
});
} }
@Override @Override
public @NotNull Promise<Void> thenRunDelayedAsync(@NotNull ExceptionalRunnable task, long delay, @NotNull TimeUnit unit) { public @NotNull Promise<Void> thenRunDelayedAsync(@NotNull ExceptionalRunnable task, long delay, @NotNull TimeUnit unit) {
return thenApplyDelayedAsync(_ -> { return thenApplyDelayed(FunctionAdapter.adapt(task), delay, unit, getFactory().getAsyncExecutor().scheduler());
task.run();
return null;
}, delay, unit);
} }
@Override @Override
public @NotNull Promise<Void> thenConsumeAsync(@NotNull ExceptionalConsumer<T> task) { public @NotNull Promise<Void> thenConsumeAsync(@NotNull ExceptionalConsumer<T> task) {
return thenApplyAsync(result -> { return thenApply(FunctionAdapter.adapt(task), getFactory().getAsyncExecutor());
task.accept(result);
return null;
});
} }
@Override @Override
public @NotNull Promise<Void> thenConsumeDelayedAsync(@NotNull ExceptionalConsumer<T> task, long delay, @NotNull TimeUnit unit) { public @NotNull Promise<Void> thenConsumeDelayedAsync(@NotNull ExceptionalConsumer<T> task, long delay, @NotNull TimeUnit unit) {
return thenApplyDelayedAsync(result -> { return thenApplyDelayed(FunctionAdapter.adapt(task), delay, unit, getFactory().getAsyncExecutor().scheduler());
task.accept(result);
return null;
}, delay, unit);
} }
@Override @Override
public <V> @NotNull Promise<V> thenSupplyAsync(@NotNull ExceptionalSupplier<V> task) { public <V> @NotNull Promise<V> thenSupplyAsync(@NotNull ExceptionalSupplier<V> task) {
return thenApplyAsync(_ -> task.get()); return thenApply(FunctionAdapter.adapt(task), getFactory().getAsyncExecutor());
} }
@Override @Override
public <V> @NotNull Promise<V> thenSupplyDelayedAsync(@NotNull ExceptionalSupplier<V> task, long delay, @NotNull TimeUnit unit) { public <V> @NotNull Promise<V> thenSupplyDelayedAsync(@NotNull ExceptionalSupplier<V> task, long delay, @NotNull TimeUnit unit) {
return thenApplyDelayedAsync(_ -> task.get(), delay, unit); return thenApplyDelayed(FunctionAdapter.adapt(task), delay, unit, getFactory().getAsyncExecutor().scheduler());
} }
@Override @Override
public <V> @NotNull Promise<V> thenApplyAsync(@NotNull ExceptionalFunction<T, V> task) { public <V> @NotNull Promise<V> thenApplyAsync(@NotNull ExceptionalFunction<T, V> task) {
CompletablePromise<V> promise = createLinked(); return thenApply(task, getFactory().getAsyncExecutor());
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;
} }
@Override @Override
public <V> @NotNull Promise<V> thenApplyDelayedAsync(@NotNull ExceptionalFunction<T, V> task, long delay, @NotNull TimeUnit unit) { public <V> @NotNull Promise<V> thenApplyDelayedAsync(@NotNull ExceptionalFunction<T, V> task, long delay, @NotNull TimeUnit unit) {
CompletablePromise<V> promise = createLinked(); return thenApplyDelayed(task, delay, unit, getFactory().getAsyncExecutor().scheduler());
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;
} }
@Override @Override
public <V> @NotNull Promise<V> thenComposeAsync(@NotNull ExceptionalFunction<T, Promise<V>> task) { public <V> @NotNull Promise<V> thenComposeAsync(@NotNull ExceptionalFunction<T, Promise<V>> task) {
CompletablePromise<V> promise = createLinked(); return thenCompose(task, getFactory().getAsyncExecutor());
thenApplyAsync(task).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<Void> thenRunVirtual(@NotNull ExceptionalRunnable task) {
return thenApply(FunctionAdapter.adapt(task), getFactory().getVirtualExecutor());
}
@Override
public @NotNull Promise<Void> thenRunDelayedVirtual(@NotNull ExceptionalRunnable task, long delay, @NotNull TimeUnit unit) {
return thenApplyDelayed(FunctionAdapter.adapt(task), delay, unit, getFactory().getVirtualExecutor().scheduler());
}
@Override
public @NotNull Promise<Void> thenConsumeVirtual(@NotNull ExceptionalConsumer<T> task) {
return thenApply(FunctionAdapter.adapt(task), getFactory().getVirtualExecutor());
}
@Override
public @NotNull Promise<Void> thenConsumeDelayedVirtual(@NotNull ExceptionalConsumer<T> task, long delay, @NotNull TimeUnit unit) {
return thenApplyDelayed(FunctionAdapter.adapt(task), delay, unit, getFactory().getVirtualExecutor().scheduler());
}
@Override
public <V> @NotNull Promise<V> thenSupplyVirtual(@NotNull ExceptionalSupplier<V> task) {
return thenApply(FunctionAdapter.adapt(task), getFactory().getVirtualExecutor());
}
@Override
public <V> @NotNull Promise<V> thenSupplyDelayedVirtual(@NotNull ExceptionalSupplier<V> task, long delay, @NotNull TimeUnit unit) {
return thenApplyDelayed(FunctionAdapter.adapt(task), delay, unit, getFactory().getVirtualExecutor().scheduler());
}
@Override
public <V> @NotNull Promise<V> thenApplyVirtual(@NotNull ExceptionalFunction<T, V> task) {
return thenApply(task, getFactory().getVirtualExecutor());
}
@Override
public <V> @NotNull Promise<V> thenApplyDelayedVirtual(@NotNull ExceptionalFunction<T, V> task, long delay, @NotNull TimeUnit unit) {
return thenApplyDelayed(task, delay, unit, getFactory().getVirtualExecutor().scheduler());
}
@Override
public <V> @NotNull Promise<V> thenComposeVirtual(@NotNull ExceptionalFunction<T, Promise<V>> task) {
return thenCompose(task, getFactory().getVirtualExecutor());
} }
@Override @Override
@@ -491,25 +503,6 @@ public abstract class AbstractPromise<T, FS, FA> implements Promise<T> {
); );
} }
@Override
public @NotNull CompletableFuture<T> toFuture() {
return useCompletion(
() -> {
CompletableFuture<T> 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 { private static class DeferredExecutionException extends ExecutionException {
} }

View File

@@ -14,22 +14,28 @@ import java.util.*;
import java.util.concurrent.CompletionStage; import java.util.concurrent.CompletionStage;
import java.util.concurrent.Future; import java.util.concurrent.Future;
public abstract class AbstractPromiseFactory<FS, FA> implements PromiseFactory { public abstract class AbstractPromiseFactory implements PromiseFactory {
private static final PromiseExecutor<?> VIRTUAL = PromiseExecutor.virtualThreaded();
public abstract @NotNull Logger getLogger(); public abstract @NotNull Logger getLogger();
public abstract @NotNull PromiseExecutor<FS> getSyncExecutor(); public abstract @NotNull PromiseExecutor<?> getSyncExecutor();
public abstract @NotNull PromiseExecutor<FA> getAsyncExecutor(); public abstract @NotNull PromiseExecutor<?> getAsyncExecutor();
public @NotNull PromiseExecutor<?> getVirtualExecutor() {
return VIRTUAL;
}
@Override @Override
public <T> @NotNull Promise<T> wrap(@NotNull CompletionStage<T> completion, @Nullable Future<T> future) { public <T> @NotNull Promise<T> wrap(@NotNull CompletionStage<T> completion, @Nullable Future<T> future) {
CompletablePromise<T> promise = unresolved(); CompletablePromise<T> promise = unresolved();
completion.whenComplete((v, e) -> { completion.whenComplete((v, e) -> {
if (e != null) { if (e == null) {
promise.completeExceptionally(e);
} else {
promise.complete(v); promise.complete(v);
} else {
promise.completeExceptionally(e);
} }
}); });

View File

@@ -5,4 +5,5 @@ package dev.tommyjs.futur.promise;
* executed asynchronously by the {@link PromiseFactory} that created the completed promise. * executed asynchronously by the {@link PromiseFactory} that created the completed promise.
*/ */
public interface AsyncPromiseListener<T> extends PromiseListener<T> { public interface AsyncPromiseListener<T> extends PromiseListener<T> {
} }

View File

@@ -1,5 +1,6 @@
package dev.tommyjs.futur.promise; package dev.tommyjs.futur.promise;
import dev.tommyjs.futur.executor.PromiseScheduler;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@@ -13,7 +14,7 @@ import java.util.concurrent.*;
import java.util.concurrent.locks.AbstractQueuedSynchronizer; import java.util.concurrent.locks.AbstractQueuedSynchronizer;
@SuppressWarnings({"FieldMayBeFinal"}) @SuppressWarnings({"FieldMayBeFinal"})
public abstract class BasePromise<T, FS, FA> extends AbstractPromise<T, FS, FA> implements CompletablePromise<T> { public abstract class BasePromise<T> extends AbstractPromise<T> implements CompletablePromise<T> {
private static final VarHandle COMPLETION_HANDLE; private static final VarHandle COMPLETION_HANDLE;
private static final VarHandle LISTENERS_HANDLE; private static final VarHandle LISTENERS_HANDLE;
@@ -48,10 +49,10 @@ public abstract class BasePromise<T, FS, FA> extends AbstractPromise<T, FS, FA>
callListeners(cmp); callListeners(cmp);
} }
protected Promise<T> completeExceptionallyDelayed(Throwable e, long delay, TimeUnit unit) { protected <F> Promise<T> completeExceptionallyDelayed(Throwable e, long delay, TimeUnit unit, PromiseScheduler<F> scheduler) {
runCompleter(this, () -> { runCompleter(this, () -> {
FA future = getFactory().getAsyncExecutor().run(() -> completeExceptionally(e), delay, unit); F future = scheduler.schedule(() -> completeExceptionally(e), delay, unit);
addDirectListener(_ -> getFactory().getAsyncExecutor().cancel(future)); addDirectListener(_ -> scheduler.cancel(future));
}); });
return this; return this;
@@ -125,16 +126,21 @@ public abstract class BasePromise<T, FS, FA> extends AbstractPromise<T, FS, FA>
return joinCompletionUnchecked(); return joinCompletionUnchecked();
} }
@Override
public T getNow() {
return joinCompletionUnchecked();
}
@Override @Override
public @NotNull Promise<T> timeout(long time, @NotNull TimeUnit unit) { public @NotNull Promise<T> timeout(long time, @NotNull TimeUnit unit) {
Exception e = new CancellationException("Promise timed out after " + time + " " + unit.toString().toLowerCase()); 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 @Override
public @NotNull Promise<T> maxWaitTime(long time, @NotNull TimeUnit unit) { public @NotNull Promise<T> maxWaitTime(long time, @NotNull TimeUnit unit) {
Exception e = new TimeoutException("Promise stopped waiting after " + time + " " + unit.toString().toLowerCase()); 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 @Override
@@ -162,6 +168,40 @@ public abstract class BasePromise<T, FS, FA> extends AbstractPromise<T, FS, FA>
return completion; return completion;
} }
@Override
public @NotNull CompletableFuture<T> toFuture() {
return useCompletion(
() -> {
CompletableFuture<T> 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<T> toCompletionStage() {
return useCompletion(
() -> {
CompletableFuture<T> future = new CompletableFuture<>();
addDirectListener(future::complete, future::completeExceptionally);
return future;
},
CompletableFuture::completedStage,
CompletableFuture::failedStage
);
}
private static final class Sync extends AbstractQueuedSynchronizer { private static final class Sync extends AbstractQueuedSynchronizer {
private Sync() { private Sync() {

View File

@@ -2,11 +2,9 @@ package dev.tommyjs.futur.promise;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.concurrent.CancellationException; import java.util.concurrent.*;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
public abstract class CompletedPromise<T, FS, FA> extends AbstractPromise<T, FS, FA> { public abstract class CompletedPromise<T> extends AbstractPromise<T> {
private static final PromiseCompletion<?> EMPTY = new PromiseCompletion<>(); private static final PromiseCompletion<?> EMPTY = new PromiseCompletion<>();
@@ -59,6 +57,11 @@ public abstract class CompletedPromise<T, FS, FA> extends AbstractPromise<T, FS,
return joinCompletionUnchecked(); return joinCompletionUnchecked();
} }
@Override
public T getNow() {
return joinCompletionUnchecked();
}
@Override @Override
public @NotNull PromiseCompletion<T> getCompletion() { public @NotNull PromiseCompletion<T> getCompletion() {
return completion; return completion;
@@ -69,4 +72,19 @@ public abstract class CompletedPromise<T, FS, FA> extends AbstractPromise<T, FS,
return true; return true;
} }
@Override
public @NotNull CompletableFuture<T> toFuture() {
if (completion.isSuccess()) {
return CompletableFuture.completedFuture(completion.result());
}
assert completion.exception() != null;
return CompletableFuture.failedFuture(completion.exception());
}
@Override
public @NotNull CompletionStage<T> toCompletionStage() {
return toFuture();
}
} }

View File

@@ -309,6 +309,116 @@ public interface Promise<T> {
*/ */
<V> @NotNull Promise<V> thenComposeAsync(@NotNull ExceptionalFunction<T, Promise<V>> task); <V> @NotNull Promise<V> thenComposeAsync(@NotNull ExceptionalFunction<T, Promise<V>> 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<Void> 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<Void> 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<Void> thenConsumeVirtual(@NotNull ExceptionalConsumer<T> 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<Void> thenConsumeDelayedVirtual(@NotNull ExceptionalConsumer<T> 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
*/
<V> @NotNull Promise<V> thenSupplyVirtual(@NotNull ExceptionalSupplier<V> 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
*/
<V> @NotNull Promise<V> thenSupplyDelayedVirtual(@NotNull ExceptionalSupplier<V> 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
*/
<V> @NotNull Promise<V> thenApplyVirtual(@NotNull ExceptionalFunction<T, V> 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
*/
<V> @NotNull Promise<V> thenApplyDelayedVirtual(@NotNull ExceptionalFunction<T, V> 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
*/
<V> @NotNull Promise<V> thenComposeVirtual(@NotNull ExceptionalFunction<T, Promise<V>> task);
/** /**
* Adds a listener to this promise that will populate the specified reference with the result of this * 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 * promise upon successful completion. The reference will not be populated if this promise completes
@@ -592,6 +702,18 @@ public interface Promise<T> {
*/ */
@Nullable PromiseCompletion<T> getCompletion(); @Nullable PromiseCompletion<T> 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. * Returns whether this promise has completed.
* *
@@ -601,10 +723,18 @@ public interface Promise<T> {
/** /**
* Converts this promise to a {@link CompletableFuture}. The returned future will complete with the * 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<T> toFuture(); @NotNull CompletableFuture<T> 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<T> toCompletionStage();
} }

View File

@@ -4,14 +4,13 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.util.concurrent.CancellationException; 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. * Represents the result of a {@link Promise}, containing either an optional result or an exception.
*/ */
public class PromiseCompletion<T> { public record PromiseCompletion<T>(@Nullable T result, @Nullable Throwable exception) {
private @Nullable T result;
private @Nullable Throwable exception;
/** /**
* Creates a new successful completion. * Creates a new successful completion.
@@ -19,7 +18,7 @@ public class PromiseCompletion<T> {
* @param result the result * @param result the result
*/ */
public PromiseCompletion(@Nullable T result) { public PromiseCompletion(@Nullable T result) {
this.result = result; this(result, null);
} }
/** /**
@@ -28,14 +27,14 @@ public class PromiseCompletion<T> {
* @param exception the exception * @param exception the exception
*/ */
public PromiseCompletion(@NotNull Throwable exception) { public PromiseCompletion(@NotNull Throwable exception) {
this.exception = exception; this(null, exception);
} }
/** /**
* Creates a new successful completion with a result of {@code null}. * Creates a new successful completion with a result of {@code null}.
*/ */
public PromiseCompletion() { public PromiseCompletion() {
this((T) null); this(null, null);
} }
/** /**
@@ -65,11 +64,6 @@ public class PromiseCompletion<T> {
return exception instanceof CancellationException; return exception instanceof CancellationException;
} }
@Deprecated
public boolean wasCanceled() {
return wasCancelled();
}
/** /**
* Gets the result of the completion. * Gets the result of the completion.
* *
@@ -88,4 +82,26 @@ public class PromiseCompletion<T> {
return exception; 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());
}
} }

View File

@@ -31,7 +31,7 @@ public interface PromiseFactory {
*/ */
static @NotNull PromiseFactory of(@NotNull Logger logger, @NotNull PromiseExecutor<?> syncExecutor, static @NotNull PromiseFactory of(@NotNull Logger logger, @NotNull PromiseExecutor<?> syncExecutor,
@NotNull PromiseExecutor<?> asyncExecutor) { @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 * @return the new promise factory
*/ */
static @NotNull PromiseFactory of(@NotNull Logger logger, @NotNull PromiseExecutor<?> executor) { static @NotNull PromiseFactory of(@NotNull Logger logger, @NotNull PromiseExecutor<?> executor) {
return new PromiseFactoryImpl<>(logger, executor, executor); return new PromiseFactoryImpl(logger, executor, executor);
} }
/** /**

View File

@@ -5,16 +5,16 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger; import org.slf4j.Logger;
public class PromiseFactoryImpl<FS, FA> extends AbstractPromiseFactory<FS, FA> { public class PromiseFactoryImpl extends AbstractPromiseFactory {
private final @NotNull Logger logger; private final @NotNull Logger logger;
private final @NotNull PromiseExecutor<FS> syncExecutor; private final @NotNull PromiseExecutor<?> syncExecutor;
private final @NotNull PromiseExecutor<FA> asyncExecutor; private final @NotNull PromiseExecutor<?> asyncExecutor;
public PromiseFactoryImpl( public PromiseFactoryImpl(
@NotNull Logger logger, @NotNull Logger logger,
@NotNull PromiseExecutor<FS> syncExecutor, @NotNull PromiseExecutor<?> syncExecutor,
@NotNull PromiseExecutor<FA> asyncExecutor @NotNull PromiseExecutor<?> asyncExecutor
) { ) {
this.logger = logger; this.logger = logger;
this.syncExecutor = syncExecutor; this.syncExecutor = syncExecutor;
@@ -47,25 +47,25 @@ public class PromiseFactoryImpl<FS, FA> extends AbstractPromiseFactory<FS, FA> {
} }
@Override @Override
public @NotNull PromiseExecutor<FS> getSyncExecutor() { public @NotNull PromiseExecutor<?> getSyncExecutor() {
return syncExecutor; return syncExecutor;
} }
@Override @Override
public @NotNull PromiseExecutor<FA> getAsyncExecutor() { public @NotNull PromiseExecutor<?> getAsyncExecutor() {
return asyncExecutor; return asyncExecutor;
} }
private class PromiseImpl<T> extends BasePromise<T, FS, FA> { private class PromiseImpl<T> extends BasePromise<T> {
@Override @Override
public @NotNull AbstractPromiseFactory<FS, FA> getFactory() { public @NotNull AbstractPromiseFactory getFactory() {
return PromiseFactoryImpl.this; return PromiseFactoryImpl.this;
} }
} }
private class CompletedPromiseImpl<T> extends CompletedPromise<T, FS, FA> { private class CompletedPromiseImpl<T> extends CompletedPromise<T> {
public CompletedPromiseImpl(@Nullable T result) { public CompletedPromiseImpl(@Nullable T result) {
super(new PromiseCompletion<>(result)); super(new PromiseCompletion<>(result));
@@ -80,7 +80,7 @@ public class PromiseFactoryImpl<FS, FA> extends AbstractPromiseFactory<FS, FA> {
} }
@Override @Override
public @NotNull AbstractPromiseFactory<FS, FA> getFactory() { public @NotNull AbstractPromiseFactory getFactory() {
return PromiseFactoryImpl.this; return PromiseFactoryImpl.this;
} }

View File

@@ -245,14 +245,14 @@ public final class PromiseTests {
@Test @Test
public void testImmediate1() { public void testImmediate1() {
var promise = promises.start().thenSupply(() -> 10); var promise = promises.start().thenSupply(() -> 10);
assert promise.isCompleted() && promise instanceof CompletedPromise<?,?,?>; assert promise.isCompleted() && promise instanceof CompletedPromise;
} }
@Test @Test
public void testImmediate2() { public void testImmediate2() {
var resolved = promises.resolve(10); var resolved = promises.resolve(10);
var promise = promises.start().thenCompose(_ -> resolved); var promise = promises.start().thenCompose(_ -> resolved);
assert promise.isCompleted() && promise instanceof CompletedPromise<?,?,?>; assert promise.isCompleted() && promise instanceof CompletedPromise;
} }
} }

View File

@@ -1,6 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists 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 networkTimeout=10000
validateDistributionUrl=true validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME