mirror of
https://github.com/HMCL-dev/HMCL.git
synced 2025-04-12 18:30:26 +08:00
Rename then-series functions
This commit is contained in:
parent
34890f21b3
commit
ed66b016db
@ -141,7 +141,7 @@ public final class LauncherHelper {
|
||||
}
|
||||
})
|
||||
.then(Task.of(Schedulers.javafx(), () -> emitStatus(LoadingState.LOGGING_IN)))
|
||||
.thenTaskResult(() -> Task.ofResult(i18n("account.methods"), () -> {
|
||||
.thenCompose(() -> Task.ofResult(i18n("account.methods"), () -> {
|
||||
try {
|
||||
return account.logIn();
|
||||
} catch (CredentialExpiredException e) {
|
||||
@ -152,11 +152,11 @@ public final class LauncherHelper {
|
||||
return account.playOffline().orElseThrow(() -> e);
|
||||
}
|
||||
}))
|
||||
.thenResult(Schedulers.javafx(), authInfo -> {
|
||||
.thenApply(Schedulers.javafx(), authInfo -> {
|
||||
emitStatus(LoadingState.LAUNCHING);
|
||||
return authInfo;
|
||||
})
|
||||
.thenResult(authInfo -> new HMCLGameLauncher(
|
||||
.thenApply(authInfo -> new HMCLGameLauncher(
|
||||
repository,
|
||||
selectedVersion,
|
||||
authInfo,
|
||||
@ -165,7 +165,7 @@ public final class LauncherHelper {
|
||||
? null // Unnecessary to start listening to game process output when close launcher immediately after game launched.
|
||||
: new HMCLProcessListener(authInfo, setting, gameVersion.isPresent())
|
||||
))
|
||||
.thenTaskResult(launcher -> { // launcher is prev task's result
|
||||
.thenCompose(launcher -> { // launcher is prev task's result
|
||||
if (scriptFile == null) {
|
||||
return new LaunchTask<>(launcher::launch).setName(i18n("version.launch"));
|
||||
} else {
|
||||
@ -175,7 +175,7 @@ public final class LauncherHelper {
|
||||
}).setName(i18n("version.launch_script"));
|
||||
}
|
||||
})
|
||||
.thenVoid(process -> { // process is LaunchTask's result
|
||||
.thenAccept(process -> { // process is LaunchTask's result
|
||||
if (scriptFile == null) {
|
||||
PROCESSES.add(process);
|
||||
if (launcherVisibility == LauncherVisibility.CLOSE)
|
||||
|
@ -110,13 +110,13 @@ public final class ModpackHelper {
|
||||
|
||||
if (modpack.getManifest() instanceof CurseManifest)
|
||||
return new CurseInstallTask(profile.getDependency(), zipFile, modpack, ((CurseManifest) modpack.getManifest()), name)
|
||||
.finalized(Schedulers.defaultScheduler(), success, failure);
|
||||
.whenComplete(Schedulers.defaultScheduler(), success, failure);
|
||||
else if (modpack.getManifest() instanceof HMCLModpackManifest)
|
||||
return new HMCLModpackInstallTask(profile, zipFile, modpack, name)
|
||||
.finalized(Schedulers.defaultScheduler(), success, failure);
|
||||
.whenComplete(Schedulers.defaultScheduler(), success, failure);
|
||||
else if (modpack.getManifest() instanceof MultiMCInstanceConfiguration)
|
||||
return new MultiMCModpackInstallTask(profile.getDependency(), zipFile, modpack, ((MultiMCInstanceConfiguration) modpack.getManifest()), name)
|
||||
.finalized(Schedulers.defaultScheduler(), success, failure)
|
||||
.whenComplete(Schedulers.defaultScheduler(), success, failure)
|
||||
.then(new MultiMCInstallVersionSettingTask(profile, ((MultiMCInstanceConfiguration) modpack.getManifest()), name));
|
||||
else throw new IllegalStateException("Unrecognized modpack: " + modpack);
|
||||
}
|
||||
|
@ -25,7 +25,6 @@ import org.jackhuang.hmcl.event.EventBus;
|
||||
import org.jackhuang.hmcl.event.RefreshedVersionsEvent;
|
||||
import org.jackhuang.hmcl.game.HMCLGameRepository;
|
||||
import org.jackhuang.hmcl.game.ModpackHelper;
|
||||
import org.jackhuang.hmcl.mod.Modpack;
|
||||
import org.jackhuang.hmcl.setting.Accounts;
|
||||
import org.jackhuang.hmcl.setting.Profile;
|
||||
import org.jackhuang.hmcl.setting.Profiles;
|
||||
@ -120,8 +119,8 @@ public final class LeftPaneController extends AdvancedListBox {
|
||||
File modpackFile = new File("modpack.zip").getAbsoluteFile();
|
||||
if (modpackFile.exists()) {
|
||||
Task.ofResult(() -> CompressingUtils.findSuitableEncoding(modpackFile.toPath()))
|
||||
.thenResult(encoding -> ModpackHelper.readModpackManifest(modpackFile.toPath(), encoding))
|
||||
.thenVoid(modpack -> {
|
||||
.thenApply(encoding -> ModpackHelper.readModpackManifest(modpackFile.toPath(), encoding))
|
||||
.thenAccept(modpack -> {
|
||||
AtomicReference<Region> region = new AtomicReference<>();
|
||||
TaskExecutor executor = ModpackHelper.getInstallTask(repository.getProfile(), modpackFile, modpack.getName(), modpack)
|
||||
.with(Task.of(Schedulers.javafx(), this::checkAccount)).executor();
|
||||
|
@ -62,7 +62,7 @@ public class AccountLoginPane extends StackPane {
|
||||
progressBar.setVisible(true);
|
||||
lblCreationWarning.setText("");
|
||||
Task.ofResult(() -> oldAccount.logInWithPassword(password))
|
||||
.finalized(Schedulers.javafx(), authInfo -> {
|
||||
.whenComplete(Schedulers.javafx(), authInfo -> {
|
||||
success.accept(authInfo);
|
||||
fireEvent(new DialogCloseEvent());
|
||||
progressBar.setVisible(false);
|
||||
|
@ -196,7 +196,7 @@ public class AddAccountPane extends StackPane {
|
||||
Object additionalData = getAuthAdditionalData();
|
||||
|
||||
Task.ofResult(() -> factory.create(new Selector(), username, password, additionalData))
|
||||
.finalized(Schedulers.javafx(), account -> {
|
||||
.whenComplete(Schedulers.javafx(), account -> {
|
||||
int oldIndex = Accounts.getAccounts().indexOf(account);
|
||||
if (oldIndex == -1) {
|
||||
Accounts.getAccounts().add(account);
|
||||
|
@ -106,7 +106,7 @@ public class AddAuthlibInjectorServerPane extends StackPane implements DialogAwa
|
||||
|
||||
Task.of(() -> {
|
||||
serverBeingAdded = AuthlibInjectorServer.locateServer(url);
|
||||
}).finalized(Schedulers.javafx(), (isDependentsSucceeded, exception) -> {
|
||||
}).whenComplete(Schedulers.javafx(), (isDependentsSucceeded, exception) -> {
|
||||
addServerPane.setDisable(false);
|
||||
nextPane.hideSpinner();
|
||||
|
||||
|
@ -93,13 +93,13 @@ public final class InstallerWizardProvider implements WizardProvider {
|
||||
TaskResult<Version> ret = Task.ofResult(() -> version);
|
||||
|
||||
if (settings.containsKey("forge"))
|
||||
ret = ret.thenTaskResult(profile.getDependency().installLibraryAsync((RemoteVersion) settings.get("forge")));
|
||||
ret = ret.thenCompose(profile.getDependency().installLibraryAsync((RemoteVersion) settings.get("forge")));
|
||||
|
||||
if (settings.containsKey("liteloader"))
|
||||
ret = ret.thenTaskResult(profile.getDependency().installLibraryAsync((RemoteVersion) settings.get("liteloader")));
|
||||
ret = ret.thenCompose(profile.getDependency().installLibraryAsync((RemoteVersion) settings.get("liteloader")));
|
||||
|
||||
if (settings.containsKey("optifine"))
|
||||
ret = ret.thenTaskResult(profile.getDependency().installLibraryAsync((RemoteVersion) settings.get("optifine")));
|
||||
ret = ret.thenCompose(profile.getDependency().installLibraryAsync((RemoteVersion) settings.get("optifine")));
|
||||
|
||||
return ret.then(profile.getRepository().refreshVersionsAsync());
|
||||
}
|
||||
|
@ -110,8 +110,8 @@ public final class ModpackPage extends StackPane implements WizardPage {
|
||||
|
||||
spinnerPane.showSpinner();
|
||||
Task.ofResult(() -> CompressingUtils.findSuitableEncoding(selectedFile.toPath()))
|
||||
.thenResult(encoding -> manifest = ModpackHelper.readModpackManifest(selectedFile.toPath(), encoding))
|
||||
.finalized(Schedulers.javafx(), manifest -> {
|
||||
.thenApply(encoding -> manifest = ModpackHelper.readModpackManifest(selectedFile.toPath(), encoding))
|
||||
.whenComplete(Schedulers.javafx(), manifest -> {
|
||||
spinnerPane.hideSpinner();
|
||||
controller.getSettings().put(MODPACK_MANIFEST, manifest);
|
||||
lblName.setText(manifest.getName());
|
||||
|
@ -59,7 +59,7 @@ public final class VanillaInstallWizardProvider implements WizardProvider {
|
||||
if (settings.containsKey("optifine"))
|
||||
builder.version((RemoteVersion) settings.get("optifine"));
|
||||
|
||||
return builder.buildAsync().finalized((a, b) -> profile.getRepository().refreshVersions())
|
||||
return builder.buildAsync().whenComplete((a, b) -> profile.getRepository().refreshVersions())
|
||||
.then(Task.of(Schedulers.javafx(), () -> profile.setSelectedVersion(name)));
|
||||
}
|
||||
|
||||
|
@ -128,7 +128,7 @@ public final class VersionsPage extends BorderPane implements WizardPage, Refres
|
||||
@Override
|
||||
public void refresh() {
|
||||
transitionHandler.setContent(spinner, ContainerAnimations.FADE.getAnimationProducer());
|
||||
executor = versionList.refreshAsync(gameVersion, downloadProvider).finalized((isDependentsSucceeded, exception) -> {
|
||||
executor = versionList.refreshAsync(gameVersion, downloadProvider).whenComplete((isDependentsSucceeded, exception) -> {
|
||||
if (isDependentsSucceeded) {
|
||||
List<VersionsPageItem> items = loadVersions();
|
||||
|
||||
|
@ -91,7 +91,7 @@ public final class ModListPage extends Control {
|
||||
modManager.refreshMods();
|
||||
return new LinkedList<>(modManager.getMods());
|
||||
}
|
||||
}).finalized(Schedulers.javafx(), (list, isDependentsSucceeded, exception) -> {
|
||||
}).whenComplete(Schedulers.javafx(), (list, isDependentsSucceeded, exception) -> {
|
||||
loadingProperty().set(false);
|
||||
if (isDependentsSucceeded)
|
||||
FXUtils.onWeakChangeAndOperate(parentTab.getSelectionModel().selectedItemProperty(), newValue -> {
|
||||
|
@ -118,7 +118,7 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag
|
||||
|
||||
FXUtils.smoothScrolling(scroll);
|
||||
|
||||
Task.ofResult(JavaVersion::getJavas).thenVoid(Schedulers.javafx(), list -> {
|
||||
Task.ofResult(JavaVersion::getJavas).thenAccept(Schedulers.javafx(), list -> {
|
||||
javaItem.loadChildren(list.stream()
|
||||
.map(javaVersion -> javaItem.createChildren(javaVersion.getVersion() + i18n("settings.game.java_directory.bit",
|
||||
javaVersion.getPlatform().getBit()), javaVersion.getBinary().toString(), javaVersion))
|
||||
@ -274,7 +274,7 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag
|
||||
if (versionSetting == null)
|
||||
return;
|
||||
Task.ofResult(versionSetting::getJavaVersion)
|
||||
.thenVoid(Schedulers.javafx(), javaVersion -> javaItem.setSubtitle(Optional.ofNullable(javaVersion)
|
||||
.thenAccept(Schedulers.javafx(), javaVersion -> javaItem.setSubtitle(Optional.ofNullable(javaVersion)
|
||||
.map(JavaVersion::getBinary).map(Path::toString).orElse("Invalid Java Path")))
|
||||
.start();
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ public class WorldListPage extends ListPage<WorldListItem> {
|
||||
|
||||
setLoading(true);
|
||||
Task.ofResult(() -> World.getWorlds(savesDir).parallel().collect(Collectors.toList()))
|
||||
.finalized(Schedulers.javafx(), (result, isDependentsSucceeded, exception) -> {
|
||||
.whenComplete(Schedulers.javafx(), (result, isDependentsSucceeded, exception) -> {
|
||||
setLoading(false);
|
||||
if (isDependentsSucceeded)
|
||||
itemsProperty().setAll(result.stream().map(WorldListItem::new).collect(Collectors.toList()));
|
||||
@ -73,10 +73,10 @@ public class WorldListPage extends ListPage<WorldListItem> {
|
||||
// Only accept one world file because user is required to confirm the new world name
|
||||
// Or too many input dialogs are popped.
|
||||
Task.ofResult(() -> new World(zipFile.toPath()))
|
||||
.finalized(Schedulers.javafx(), world -> {
|
||||
.whenComplete(Schedulers.javafx(), world -> {
|
||||
Controllers.inputDialog(i18n("world.name.enter"), (name, resolve, reject) -> {
|
||||
Task.of(() -> world.install(savesDir, name))
|
||||
.finalized(Schedulers.javafx(), () -> {
|
||||
.whenComplete(Schedulers.javafx(), () -> {
|
||||
itemsProperty().add(new WorldListItem(new World(savesDir.resolve(name))));
|
||||
resolve.run();
|
||||
}, e -> {
|
||||
|
@ -91,7 +91,7 @@ public class DefaultDependencyManager extends AbstractDependencyManager {
|
||||
public TaskResult<Version> installLibraryAsync(String gameVersion, Version version, String libraryId, String libraryVersion) {
|
||||
VersionList<?> versionList = getVersionList(libraryId);
|
||||
return versionList.loadAsync(gameVersion, getDownloadProvider())
|
||||
.thenTaskResult(() -> installLibraryAsync(version, versionList.getVersion(gameVersion, libraryVersion)
|
||||
.thenCompose(() -> installLibraryAsync(version, versionList.getVersion(gameVersion, libraryVersion)
|
||||
.orElseThrow(() -> new IllegalStateException("Remote library " + libraryId + " has no version " + libraryVersion))));
|
||||
}
|
||||
|
||||
@ -107,9 +107,9 @@ public class DefaultDependencyManager extends AbstractDependencyManager {
|
||||
else
|
||||
throw new IllegalArgumentException("Remote library " + libraryVersion + " is unrecognized.");
|
||||
return task
|
||||
.thenTaskResult(LibrariesUniqueTask::new)
|
||||
.thenTaskResult(MaintainTask::new)
|
||||
.thenTaskResult(newVersion -> new VersionJsonSaveTask(repository, newVersion));
|
||||
.thenCompose(LibrariesUniqueTask::new)
|
||||
.thenCompose(MaintainTask::new)
|
||||
.thenCompose(newVersion -> new VersionJsonSaveTask(repository, newVersion));
|
||||
}
|
||||
|
||||
|
||||
|
@ -22,7 +22,6 @@ import org.jackhuang.hmcl.game.Version;
|
||||
import org.jackhuang.hmcl.task.ParallelTask;
|
||||
import org.jackhuang.hmcl.task.Task;
|
||||
import org.jackhuang.hmcl.task.TaskResult;
|
||||
import org.jackhuang.hmcl.util.AutoTypingMap;
|
||||
import org.jackhuang.hmcl.util.function.ExceptionalFunction;
|
||||
import org.jackhuang.hmcl.util.gson.JsonUtils;
|
||||
|
||||
@ -50,7 +49,7 @@ public class DefaultGameBuilder extends GameBuilder {
|
||||
|
||||
@Override
|
||||
public Task buildAsync() {
|
||||
return new VersionJsonDownloadTask(gameVersion, dependencyManager).thenTaskResult(rawJson -> {
|
||||
return new VersionJsonDownloadTask(gameVersion, dependencyManager).thenCompose(rawJson -> {
|
||||
Version original = JsonUtils.GSON.fromJson(rawJson, Version.class);
|
||||
Version version = original.setId(name).setJar(null);
|
||||
Task vanillaTask = downloadGameAsync(gameVersion, version).then(new ParallelTask(
|
||||
@ -58,20 +57,20 @@ public class DefaultGameBuilder extends GameBuilder {
|
||||
new GameLibrariesTask(dependencyManager, version) // Game libraries will be downloaded for multiple times partly, this time is for vanilla libraries.
|
||||
).with(new VersionJsonSaveTask(dependencyManager.getGameRepository(), version))); // using [with] because download failure here are tolerant.
|
||||
|
||||
TaskResult<Version> libraryTask = vanillaTask.thenResult(() -> version);
|
||||
TaskResult<Version> libraryTask = vanillaTask.thenSupply(() -> version);
|
||||
|
||||
if (toolVersions.containsKey("forge"))
|
||||
libraryTask = libraryTask.thenTaskResult(libraryTaskHelper(gameVersion, "forge"));
|
||||
libraryTask = libraryTask.thenCompose(libraryTaskHelper(gameVersion, "forge"));
|
||||
if (toolVersions.containsKey("liteloader"))
|
||||
libraryTask = libraryTask.thenTaskResult(libraryTaskHelper(gameVersion, "liteloader"));
|
||||
libraryTask = libraryTask.thenCompose(libraryTaskHelper(gameVersion, "liteloader"));
|
||||
if (toolVersions.containsKey("optifine"))
|
||||
libraryTask = libraryTask.thenTaskResult(libraryTaskHelper(gameVersion, "optifine"));
|
||||
libraryTask = libraryTask.thenCompose(libraryTaskHelper(gameVersion, "optifine"));
|
||||
|
||||
for (RemoteVersion remoteVersion : remoteVersions)
|
||||
libraryTask = libraryTask.thenTaskResult(dependencyManager.installLibraryAsync(remoteVersion));
|
||||
libraryTask = libraryTask.thenCompose(dependencyManager.installLibraryAsync(remoteVersion));
|
||||
|
||||
return libraryTask;
|
||||
}).finalized((isDependentsSucceeded, exception) -> {
|
||||
}).whenComplete((isDependentsSucceeded, exception) -> {
|
||||
if (!isDependentsSucceeded)
|
||||
dependencyManager.getGameRepository().getVersionRoot(name).delete();
|
||||
});
|
||||
|
@ -156,7 +156,7 @@ public final class MultiMCModpackInstallTask extends Task {
|
||||
}
|
||||
}
|
||||
|
||||
dependencies.add(new MaintainTask(version).thenTaskResult(maintainedVersion -> new VersionJsonSaveTask(repository, maintainedVersion)));
|
||||
dependencies.add(new MaintainTask(version).thenCompose(maintainedVersion -> new VersionJsonSaveTask(repository, maintainedVersion)));
|
||||
dependencies.add(new MinecraftInstanceTask<>(zipFile, modpack.getEncoding(), "/" + manifest.getName() + "/minecraft", manifest, MODPACK_TYPE, repository.getModpackConfiguration(name)));
|
||||
}
|
||||
|
||||
|
@ -1,71 +0,0 @@
|
||||
/*
|
||||
* Hello Minecraft! Launcher
|
||||
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.jackhuang.hmcl.task;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
/**
|
||||
* A task that combines two tasks and make sure [pred] runs before succ.
|
||||
*
|
||||
* @author huangyuhui
|
||||
*/
|
||||
final class FinalizedTask extends Task {
|
||||
|
||||
private final Task pred;
|
||||
private final FinalizedCallback callback;
|
||||
private final Scheduler scheduler;
|
||||
|
||||
/**
|
||||
* A task that combines two tasks and make sure pred runs before succ.
|
||||
*
|
||||
* @param pred the task that runs before succ.
|
||||
* @param callback a callback that returns the task runs after pred, succ will be executed asynchronously. You can do something that relies on the result of pred.
|
||||
*/
|
||||
public FinalizedTask(Task pred, Scheduler scheduler, FinalizedCallback callback) {
|
||||
this.pred = pred;
|
||||
this.scheduler = scheduler;
|
||||
this.callback = callback;
|
||||
|
||||
setSignificance(TaskSignificance.MODERATE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Scheduler getScheduler() {
|
||||
return scheduler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() throws Exception {
|
||||
callback.execute(isDependentsSucceeded(), pred.getLastException());
|
||||
|
||||
if (!isDependentsSucceeded())
|
||||
throw new SilentException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Task> getDependents() {
|
||||
return Collections.singleton(pred);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRelyingOnDependents() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -265,18 +265,6 @@ public abstract class Task {
|
||||
return executor().test();
|
||||
}
|
||||
|
||||
public final void subscribe(Task subscriber) {
|
||||
new TaskExecutor(then(subscriber)).start();
|
||||
}
|
||||
|
||||
public final void subscribe(Scheduler scheduler, ExceptionalRunnable<?> closure) {
|
||||
subscribe(of(scheduler, closure));
|
||||
}
|
||||
|
||||
public final void subscribe(ExceptionalRunnable<?> closure) {
|
||||
subscribe(of(closure));
|
||||
}
|
||||
|
||||
public final Task then(Task b) {
|
||||
return then(convert(b));
|
||||
}
|
||||
@ -285,13 +273,29 @@ public abstract class Task {
|
||||
return new CoupleTask(this, b, true);
|
||||
}
|
||||
|
||||
public final <R> TaskResult<R> thenResult(Callable<R> supplier) {
|
||||
return thenTaskResult(() -> Task.ofResult(supplier));
|
||||
/**
|
||||
* Returns a new TaskResult that, when this task completes
|
||||
* normally, is executed using the default Scheduler.
|
||||
*
|
||||
* @param fn the function to use to compute the value of the returned TaskResult
|
||||
* @param <U> the function's return type
|
||||
* @return the new TaskResult
|
||||
*/
|
||||
public final <U> TaskResult<U> thenSupply(Callable<U> fn) {
|
||||
return thenCompose(() -> Task.ofResult(fn));
|
||||
}
|
||||
|
||||
public final <R> TaskResult<R> thenTaskResult(ExceptionalSupplier<TaskResult<R>, ?> taskSupplier) {
|
||||
return new TaskResult<R>() {
|
||||
TaskResult<R> then;
|
||||
/**
|
||||
* Returns a new TaskResult that, when this task completes
|
||||
* normally, is executed.
|
||||
*
|
||||
* @param fn the function returning a new TaskResult
|
||||
* @param <U> the type of the returned TaskResult's result
|
||||
* @return the TaskResult
|
||||
*/
|
||||
public final <U> TaskResult<U> thenCompose(ExceptionalSupplier<TaskResult<U>, ?> fn) {
|
||||
return new TaskResult<U>() {
|
||||
TaskResult<U> then;
|
||||
|
||||
@Override
|
||||
public Collection<? extends Task> getDependents() {
|
||||
@ -300,7 +304,7 @@ public abstract class Task {
|
||||
|
||||
@Override
|
||||
public void execute() throws Exception {
|
||||
then = taskSupplier.get().storeTo(this::setResult);
|
||||
then = fn.get().storeTo(this::setResult);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -318,17 +322,87 @@ public abstract class Task {
|
||||
return new CoupleTask(this, b, false);
|
||||
}
|
||||
|
||||
public final Task finalized(FinalizedCallback b) {
|
||||
return finalized(Schedulers.defaultScheduler(), b);
|
||||
/**
|
||||
* Returns a new Task with the same exception as this task, that executes
|
||||
* the given action when this task completes.
|
||||
*
|
||||
* <p>When this task is complete, the given action is invoked, a boolean
|
||||
* value represents the execution status of this task, and the exception
|
||||
* (or {@code null} if none) of this task as arguments. The returned task
|
||||
* is completed when the action returns. If the supplied action itself
|
||||
* encounters an exception, then the returned task exceptionally completes
|
||||
* with this exception unless this task also completed exceptionally.
|
||||
*
|
||||
* @param action the action to perform
|
||||
* @return the new Task
|
||||
*/
|
||||
public final Task whenComplete(FinalizedCallback action) {
|
||||
return whenComplete(Schedulers.defaultScheduler(), action);
|
||||
}
|
||||
|
||||
public final Task finalized(Scheduler scheduler, FinalizedCallback b) {
|
||||
return new FinalizedTask(this, scheduler, b).setName(getCaller());
|
||||
/**
|
||||
* Returns a new Task with the same exception as this task, that executes
|
||||
* the given action when this task completes.
|
||||
*
|
||||
* <p>When this task is complete, the given action is invoked, a boolean
|
||||
* value represents the execution status of this task, and the exception
|
||||
* (or {@code null} if none) of this task as arguments. The returned task
|
||||
* is completed when the action returns. If the supplied action itself
|
||||
* encounters an exception, then the returned task exceptionally completes
|
||||
* with this exception unless this task also completed exceptionally.
|
||||
*
|
||||
* @param action the action to perform
|
||||
* @param scheduler the executor to use for asynchronous execution
|
||||
* @return the new Task
|
||||
*/
|
||||
public final Task whenComplete(Scheduler scheduler, FinalizedCallback action) {
|
||||
return new Task() {
|
||||
{
|
||||
setSignificance(TaskSignificance.MODERATE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Scheduler getScheduler() {
|
||||
return scheduler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() throws Exception {
|
||||
action.execute(isDependentsSucceeded(), Task.this.getLastException());
|
||||
|
||||
if (!isDependentsSucceeded())
|
||||
throw new SilentException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Task> getDependents() {
|
||||
return Collections.singleton(Task.this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRelyingOnDependents() {
|
||||
return false;
|
||||
}
|
||||
}.setName(getCaller());
|
||||
}
|
||||
|
||||
// T, K here is necessary, or javac cannot infer type of failure
|
||||
public final <T extends Exception, K extends Exception> Task finalized(Scheduler scheduler, ExceptionalRunnable<T> success, ExceptionalConsumer<Exception, K> failure) {
|
||||
return finalized(scheduler, (isDependentsSucceeded, exception) -> {
|
||||
/**
|
||||
* Returns a new Task with the same exception as this task, that executes
|
||||
* the given actions when this task completes.
|
||||
*
|
||||
* <p>When this task is complete, the given success action is invoked, the
|
||||
* given failure action is invoked with the exception of this task. The
|
||||
* returned task is completed when the action returns. If the supplied
|
||||
* action itself encounters an exception, then the returned task exceptionally
|
||||
* completes with this exception unless this task also
|
||||
* completed exceptionally.
|
||||
*
|
||||
* @param success the action to perform when this task successfully completed
|
||||
* @param failure the action to perform when this task exceptionally returned
|
||||
* @return the new Task
|
||||
*/
|
||||
public final <E1 extends Exception, E2 extends Exception> Task whenComplete(Scheduler scheduler, ExceptionalRunnable<E1> success, ExceptionalConsumer<Exception, E2> failure) {
|
||||
return whenComplete(scheduler, (isDependentsSucceeded, exception) -> {
|
||||
if (isDependentsSucceeded) {
|
||||
if (success != null)
|
||||
try {
|
||||
|
@ -133,6 +133,7 @@ public final class TaskExecutor {
|
||||
private boolean executeTask(Task task) {
|
||||
if (canceled) {
|
||||
task.setState(Task.TaskState.FAILED);
|
||||
task.setLastException(new CancellationException());
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -221,7 +222,7 @@ public final class TaskExecutor {
|
||||
task.onDone().fireEvent(new TaskEvent(this, task, true));
|
||||
taskListeners.forEach(it -> it.onFailed(task, e));
|
||||
} catch (SilentException | RejectedExecutionException e) {
|
||||
// do nothing
|
||||
task.setLastException(e);
|
||||
} catch (Exception e) {
|
||||
task.setLastException(e);
|
||||
lastException = e;
|
||||
|
@ -29,35 +29,55 @@ import java.util.function.Consumer;
|
||||
*
|
||||
* @author huangyuhui
|
||||
*/
|
||||
public abstract class TaskResult<V> extends Task {
|
||||
public abstract class TaskResult<T> extends Task {
|
||||
|
||||
private V result;
|
||||
private Consumer<V> resultConsumer;
|
||||
private T result;
|
||||
private Consumer<T> resultConsumer;
|
||||
|
||||
@Override
|
||||
public TaskResult<V> setName(String name) {
|
||||
public TaskResult<T> setName(String name) {
|
||||
super.setName(name);
|
||||
return this;
|
||||
}
|
||||
|
||||
public V getResult() {
|
||||
/**
|
||||
* Returns the result of this task.
|
||||
*
|
||||
* The result will be generated only if the execution is completed.
|
||||
*/
|
||||
public T getResult() {
|
||||
return result;
|
||||
}
|
||||
|
||||
public void setResult(V result) {
|
||||
protected void setResult(T result) {
|
||||
this.result = result;
|
||||
if (resultConsumer != null)
|
||||
resultConsumer.accept(result);
|
||||
}
|
||||
|
||||
public TaskResult<V> storeTo(Consumer<V> resultConsumer) {
|
||||
this.resultConsumer = resultConsumer;
|
||||
/**
|
||||
* Sync the result of this task by given action.
|
||||
*
|
||||
* @param action the action to perform when result of this task changed
|
||||
* @return this TaskResult
|
||||
*/
|
||||
public TaskResult<T> storeTo(Consumer<T> action) {
|
||||
this.resultConsumer = action;
|
||||
return this;
|
||||
}
|
||||
|
||||
public <R, E extends Exception> TaskResult<R> thenTaskResult(ExceptionalFunction<V, TaskResult<R>, E> taskSupplier) {
|
||||
return new TaskResult<R>() {
|
||||
TaskResult<R> then;
|
||||
/**
|
||||
* Returns a new TaskResult that, when this task completes
|
||||
* normally, is executed with result of this task as the argument
|
||||
* to the supplied function.
|
||||
*
|
||||
* @param fn the function returning a new TaskResult
|
||||
* @param <U> the type of the returned TaskResult's result
|
||||
* @return the TaskResult
|
||||
*/
|
||||
public <U, E extends Exception> TaskResult<U> thenCompose(ExceptionalFunction<T, TaskResult<U>, E> fn) {
|
||||
return new TaskResult<U>() {
|
||||
TaskResult<U> then;
|
||||
|
||||
@Override
|
||||
public Collection<? extends Task> getDependents() {
|
||||
@ -66,7 +86,7 @@ public abstract class TaskResult<V> extends Task {
|
||||
|
||||
@Override
|
||||
public void execute() throws Exception {
|
||||
then = taskSupplier.apply(TaskResult.this.getResult()).storeTo(this::setResult);
|
||||
then = fn.apply(TaskResult.this.getResult()).storeTo(this::setResult);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -76,44 +96,129 @@ public abstract class TaskResult<V> extends Task {
|
||||
};
|
||||
}
|
||||
|
||||
public <R, E extends Exception> Task then(ExceptionalFunction<V, Task, E> taskSupplier) {
|
||||
return new CoupleTask(this, () -> taskSupplier.apply(getResult()), true);
|
||||
/**
|
||||
* Returns a new Task that, when this task completes
|
||||
* normally, is executed with this task as the argument
|
||||
* to the supplied function.
|
||||
*
|
||||
* @param fn the function returning a new Task
|
||||
* @return the Task
|
||||
*/
|
||||
public <E extends Exception> Task then(ExceptionalFunction<T, Task, E> fn) {
|
||||
return new CoupleTask(this, () -> fn.apply(getResult()), true);
|
||||
}
|
||||
|
||||
public <R, E extends Exception> TaskResult<R> thenResult(ExceptionalFunction<V, R, E> task) {
|
||||
return thenResult(Schedulers.defaultScheduler(), task);
|
||||
/**
|
||||
* Returns a new TaskResult that, when this task completes
|
||||
* normally, is executed using the default Scheduler, with this
|
||||
* task's result as the argument to the supplied function.
|
||||
*
|
||||
* @param fn the function to use to compute the value of the returned TaskResult
|
||||
* @param <U> the function's return type
|
||||
* @return the new TaskResult
|
||||
*/
|
||||
public <U, E extends Exception> TaskResult<U> thenApply(ExceptionalFunction<T, U, E> fn) {
|
||||
return thenApply(Schedulers.defaultScheduler(), fn);
|
||||
}
|
||||
|
||||
public <R, E extends Exception> TaskResult<R> thenResult(Scheduler scheduler, ExceptionalFunction<V, R, E> task) {
|
||||
return thenResult(getCaller(), scheduler, task);
|
||||
/**
|
||||
* Returns a new TaskResult that, when this task completes
|
||||
* normally, is executed using the supplied Scheduler, with this
|
||||
* task's result as the argument to the supplied function.
|
||||
*
|
||||
* @param scheduler the executor to use for asynchronous execution
|
||||
* @param fn the function to use to compute the value of the returned TaskResult
|
||||
* @param <U> the function's return type
|
||||
* @return the new TaskResult
|
||||
*/
|
||||
public <U, E extends Exception> TaskResult<U> thenApply(Scheduler scheduler, ExceptionalFunction<T, U, E> fn) {
|
||||
return thenApply(getCaller(), scheduler, fn);
|
||||
}
|
||||
|
||||
public <R, E extends Exception> TaskResult<R> thenResult(String name, Scheduler scheduler, ExceptionalFunction<V, R, E> task) {
|
||||
return new Subtask<>(name, scheduler, task);
|
||||
/**
|
||||
* Returns a new TaskResult that, when this task completes
|
||||
* normally, is executed using the supplied Scheduler, with this
|
||||
* task's result as the argument to the supplied function.
|
||||
*
|
||||
* @param name the name of this new TaskResult for displaying
|
||||
* @param scheduler the executor to use for asynchronous execution
|
||||
* @param fn the function to use to compute the value of the returned TaskResult
|
||||
* @param <U> the function's return type
|
||||
* @return the new TaskResult
|
||||
*/
|
||||
public <U, E extends Exception> TaskResult<U> thenApply(String name, Scheduler scheduler, ExceptionalFunction<T, U, E> fn) {
|
||||
return new Subtask<>(name, scheduler, fn);
|
||||
}
|
||||
|
||||
// stupid javac stop us from renaming thenVoid to thenResult
|
||||
public <E extends Exception> Task thenVoid(ExceptionalConsumer<V, E> task) {
|
||||
return thenVoid(Schedulers.defaultScheduler(), task);
|
||||
/**
|
||||
* Returns a new Task that, when this task completes
|
||||
* normally, is executed using the default Scheduler, with this
|
||||
* task's result as the argument to the supplied action.
|
||||
*
|
||||
* @param action the action to perform before completing the
|
||||
* returned Task
|
||||
* @return the new Task
|
||||
*/
|
||||
public <E extends Exception> Task thenAccept(ExceptionalConsumer<T, E> action) {
|
||||
return thenAccept(Schedulers.defaultScheduler(), action);
|
||||
}
|
||||
|
||||
public <E extends Exception> Task thenVoid(Scheduler scheduler, ExceptionalConsumer<V, E> task) {
|
||||
return new CoupleTask(this, () -> Task.of(scheduler, () -> task.accept(getResult())), true);
|
||||
/**
|
||||
* Returns a new Task that, when this task completes
|
||||
* normally, is executed using the supplied Scheduler, with this
|
||||
* task's result as the argument to the supplied action.
|
||||
*
|
||||
* @param action the action to perform before completing the returned Task
|
||||
* @param scheduler the executor to use for asynchronous execution
|
||||
* @return the new Task
|
||||
*/
|
||||
public <E extends Exception> Task thenAccept(Scheduler scheduler, ExceptionalConsumer<T, E> action) {
|
||||
return new CoupleTask(this, () -> Task.of(scheduler, () -> action.accept(getResult())), true);
|
||||
}
|
||||
|
||||
public <T extends Exception, K extends Exception> Task finalized(Scheduler scheduler, ExceptionalConsumer<V, T> success, ExceptionalConsumer<Exception, K> failure) {
|
||||
return finalized(scheduler, () -> success.accept(getResult()), failure);
|
||||
/**
|
||||
* Returns a new Task with the same exception as this task, that executes
|
||||
* the given actions when this task completes.
|
||||
*
|
||||
* <p>When this task is complete, the given success action is invoked with
|
||||
* the result, the given failure action is invoked with the exception of
|
||||
* this task. The returned task is completed when the action returns. If
|
||||
* the supplied action itself encounters an exception, then the returned
|
||||
* task exceptionally completes with this exception unless this task also
|
||||
* completed exceptionally.
|
||||
*
|
||||
* @param success the action to perform when this task successfully completed
|
||||
* @param failure the action to perform when this task exceptionally returned
|
||||
* @return the new Task
|
||||
*/
|
||||
public <E1 extends Exception, E2 extends Exception> Task whenComplete(Scheduler scheduler, ExceptionalConsumer<T, E1> success, ExceptionalConsumer<Exception, E2> failure) {
|
||||
return whenComplete(scheduler, () -> success.accept(getResult()), failure);
|
||||
}
|
||||
|
||||
public Task finalized(Scheduler scheduler, FinalizedCallback<V> callback) {
|
||||
return finalized(scheduler, ((isDependentsSucceeded, exception) -> callback.execute(getResult(), isDependentsSucceeded, exception)));
|
||||
/**
|
||||
* Returns a new Task with the same exception as this task, that executes
|
||||
* the given action when this task completes.
|
||||
*
|
||||
* <p>When this task is complete, the given action is invoked with the
|
||||
* result (or {@code null} if none), a boolean value represents the
|
||||
* execution status of this task, and the exception (or {@code null}
|
||||
* if none) of this task as arguments. The returned task is completed
|
||||
* when the action returns. If the supplied action itself encounters an
|
||||
* exception, then the returned task exceptionally completes with this
|
||||
* exception unless this task also completed exceptionally.
|
||||
*
|
||||
* @param action the action to perform
|
||||
* @return the new Task
|
||||
*/
|
||||
public Task whenComplete(Scheduler scheduler, FinalizedCallback<T> action) {
|
||||
return whenComplete(scheduler, ((isDependentsSucceeded, exception) -> action.execute(getResult(), isDependentsSucceeded, exception)));
|
||||
}
|
||||
|
||||
private class Subtask<R> extends TaskResult<R> {
|
||||
private final Scheduler scheduler;
|
||||
private final ExceptionalFunction<V, R, ?> callable;
|
||||
private final ExceptionalFunction<T, R, ?> callable;
|
||||
|
||||
public Subtask(String name, Scheduler scheduler, ExceptionalFunction<V, R, ?> callable) {
|
||||
public Subtask(String name, Scheduler scheduler, ExceptionalFunction<T, R, ?> callable) {
|
||||
this.scheduler = scheduler;
|
||||
this.callable = callable;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user