io.activej.async.AsyncAccumulator Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of activej-promise Show documentation
Show all versions of activej-promise Show documentation
A convenient way to organize asynchronous code.
Promises are a faster and more efficient version of JavaScript's Promise and Java's CompletionStage's.
/*
* Copyright (C) 2020 ActiveJ LLC.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.activej.async;
import io.activej.async.process.AsyncCloseable;
import io.activej.common.Checks;
import io.activej.common.builder.AbstractBuilder;
import io.activej.common.function.BiConsumerEx;
import io.activej.common.recycle.Recyclers;
import io.activej.promise.Promise;
import io.activej.promise.SettablePromise;
import io.activej.reactor.ImplicitlyReactive;
import org.jetbrains.annotations.Nullable;
import static io.activej.common.Checks.checkState;
import static io.activej.common.exception.FatalErrorHandler.handleError;
import static io.activej.reactor.Reactive.checkInReactorThread;
@SuppressWarnings("UnusedReturnValue")
public final class AsyncAccumulator extends ImplicitlyReactive implements AsyncCloseable {
private static final boolean CHECKS = Checks.isEnabled(AsyncAccumulator.class);
private final SettablePromise resultPromise = new SettablePromise<>();
private boolean started;
private final A accumulator;
private int activePromises;
private AsyncAccumulator(@Nullable A accumulator) {
this.accumulator = accumulator;
}
public static AsyncAccumulator create(@Nullable A accumulator) {
return builder(accumulator).build();
}
public static AsyncAccumulator.Builder builder(@Nullable A accumulator) {
return new AsyncAccumulator<>(accumulator).new Builder();
}
public final class Builder extends AbstractBuilder> {
private Builder() {}
public Builder withPromise(Promise promise, BiConsumerEx accumulator) {
checkNotBuilt(this);
addPromise(promise, accumulator);
return this;
}
@Override
protected AsyncAccumulator doBuild() {
return AsyncAccumulator.this;
}
}
public Promise run() {
checkInReactorThread(this);
checkState(!started);
this.started = true;
if (resultPromise.isComplete()) return resultPromise;
if (activePromises == 0) {
resultPromise.set(accumulator);
}
return resultPromise;
}
public Promise run(Promise runtimePromise) {
checkInReactorThread(this);
addPromise(runtimePromise, (result, v) -> {});
return run();
}
public void addPromise(Promise promise, BiConsumerEx consumer) {
if (CHECKS) checkInReactorThread(this);
if (resultPromise.isComplete()) {
promise.whenResult(Recyclers::recycle);
return;
}
activePromises++;
promise.subscribe((v, e) -> {
activePromises--;
if (resultPromise.isComplete()) {
Recyclers.recycle(v);
return;
}
if (e == null) {
try {
consumer.accept(accumulator, v);
} catch (Exception ex) {
handleError(ex, this);
resultPromise.setException(ex);
Recyclers.recycle(accumulator);
return;
}
if (activePromises == 0 && started) {
resultPromise.set(accumulator);
}
} else {
resultPromise.setException(e);
Recyclers.recycle(accumulator);
}
});
}
public SettablePromise newPromise(BiConsumerEx consumer) {
if (CHECKS) checkInReactorThread(this);
SettablePromise resultPromise = new SettablePromise<>();
addPromise(resultPromise, consumer);
return resultPromise;
}
public Promise get() {
return resultPromise;
}
public A getAccumulator() {
return accumulator;
}
public int getActivePromises() {
return activePromises;
}
public void complete() {
checkInReactorThread(this);
resultPromise.trySet(accumulator);
}
public void complete(A result) {
checkInReactorThread(this);
if (resultPromise.trySet(result) && result != accumulator) {
Recyclers.recycle(accumulator);
}
}
@Override
public void closeEx(Exception e) {
checkInReactorThread(this);
if (resultPromise.trySetException(e)) {
Recyclers.recycle(accumulator);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy