All Downloads are FREE. Search and download functionalities are using the official Maven repository.

javaslang.concurrent.Promise Maven / Gradle / Ivy

Go to download

A Java implementation of a KillBill Payment Plugin that uses Authorize.Net as a payment gateway

There is a newer version: 2.8.196
Show newest version
/*     / \____  _    _  ____   ______  / \ ____  __    _______
 *    /  /    \/ \  / \/    \ /  /\__\/  //    \/  \  //  /\__\   JΛVΛSLΛNG
 *  _/  /  /\  \  \/  /  /\  \\__\\  \  //  /\  \ /\\/ \ /__\ \   Copyright 2014-2016 Javaslang, http://javaslang.io
 * /___/\_/  \_/\____/\_/  \_/\__\/__/\__\_/  \_//  \__/\_____/   Licensed under the Apache License, Version 2.0
 */
package javaslang.concurrent;

import javaslang.control.Try;

import java.util.Objects;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ForkJoinPool;

import static javaslang.concurrent.Future.DEFAULT_EXECUTOR_SERVICE;

/**
 * A Promise is a write-once wrapper around a read-only Future which can complete the underlying Future with a value
 * or an exception.
 * 

* The underlying {@code ExecutorService} is used to execute asynchronous handlers, e.g. via * {@code promise.future().onComplete(...)}. * *

Creation

*

* Promise offers static factory methods to create new promises which hasn't been fulfilled yet: *

    *
  • create new promises: {@link Promise#make()}
  • *
* And we may create new promises that are already finished: *
    *
  • {@link #failed(Throwable)}
  • *
  • {@link #fromTry(Try)}
  • *
  • {@link #successful(Object)}
  • *
* All the static factory methods mentioned above have additional versions which take an {@link ExecutorService} as * argument. This gives us more control over thread creation and thread pool sizes. * *

One-shot API

*

* The main purpose of a {@code Promise} is to complete its underlying {@code Future}. When only a single {@code Thread} * will eventually complete the {@code Promise}, we use one of these methods. Calls will throw if the {@code Promise} is already * completed. *

    *
  • {@link #complete(Try)}
  • *
  • {@link #completeWith(Future)}
  • *
  • {@link #failure(Throwable)}
  • *
  • {@link #success(Object)}
  • *
* *

API for competing threads

*

* When multiple {@code Thread}s may complete our {@code Promise}, we typically use one of these methods. Calls will * gracefully return {@code false} if the {@code Promise} is already completed. *

    *
  • {@link #tryComplete(Try)}
  • *
  • {@link #tryCompleteWith(Future)}
  • *
  • {@link #tryFailure(Throwable)}
  • *
  • {@link #trySuccess(Object)}
  • *
* * @param The result type of the underlying {@code Future}. * @author Daniel Dietrich * @since 2.0.0 */ public interface Promise { /** * Creates a failed {@code Promise}, backed by the {@link Future#DEFAULT_EXECUTOR_SERVICE}. * * @param exception The reason why it failed. * @param The value type of a successful result. * @return A failed {@code Promise}. * @throws NullPointerException if exception is null */ static Promise failed(Throwable exception) { Objects.requireNonNull(exception, "exception is null"); return failed(DEFAULT_EXECUTOR_SERVICE, exception); } /** * Creates a failed {@code Promise}, backed by the given {@link ExecutorService}. * * @param executorService An {@code ExecutorService} passed to the underlying {@link Future}. * @param exception The reason why it failed. * @param The value type of a successful result. * @return A failed {@code Promise}. * @throws NullPointerException if executorService or exception is null */ static Promise failed(ExecutorService executorService, Throwable exception) { Objects.requireNonNull(executorService, "executorService is null"); Objects.requireNonNull(exception, "exception is null"); return Promise. make(executorService).failure(exception); } /** * Creates a {@code Promise} from a {@link Try}, backed by the {@link Future#DEFAULT_EXECUTOR_SERVICE}. * * @param result The result. * @param The value type of a successful result. * @return A completed {@code Promise} which contains either a {@code Success} or a {@code Failure}. * @throws NullPointerException if result is null */ static Promise fromTry(Try result) { return fromTry(DEFAULT_EXECUTOR_SERVICE, result); } /** * Creates a {@code Promise} from a {@link Try}, backed by the given {@link ExecutorService}. * * @param executorService An {@code ExecutorService} passed to the underlying {@link Future}. * @param result The result. * @param The value type of a successful result. * @return A completed {@code Promise} which contains either a {@code Success} or a {@code Failure}. * @throws NullPointerException if executorService or result is null */ static Promise fromTry(ExecutorService executorService, Try result) { Objects.requireNonNull(executorService, "executorService is null"); Objects.requireNonNull(result, "result is null"); return Promise. make(executorService).complete(result); } /** * Makes a {@code Promise} that isn't fulfilled yet, backed by the {@link Future#DEFAULT_EXECUTOR_SERVICE}. * {@link ForkJoinPool#commonPool()}. * * @param Result type of the {@code Promise}. * @return A new {@code Promise}. */ static Promise make() { return make(DEFAULT_EXECUTOR_SERVICE); } /** * Makes a {@code Promise} that isn't fulfilled yet, backed by the given {@link ExecutorService}. * * @param executorService An {@code ExecutorService} passed to the underlying {@link Future}. * @param Result type of the {@code Promise}. * @return A new {@code Promise}. * @throws NullPointerException if executorService is null */ static Promise make(ExecutorService executorService) { Objects.requireNonNull(executorService, "executorService is null"); return new PromiseImpl<>(new FutureImpl<>(executorService)); } /** * Narrows a widened {@code Promise} to {@code Promise} * by performing a type safe-cast. This is eligible because immutable/read-only * collections are covariant. * * @param promise A {@code Promise}. * @param Component type of the {@code Promise}. * @return the given {@code promise} instance as narrowed type {@code Promise}. */ @SuppressWarnings("unchecked") static Promise narrow(Promise promise) { return (Promise) promise; } /** * Creates a succeeded {@code Promise}, backed by the {@link Future#DEFAULT_EXECUTOR_SERVICE}. * * @param result The result. * @param The value type of a successful result. * @return A succeeded {@code Promise}. */ static Promise successful(T result) { return successful(DEFAULT_EXECUTOR_SERVICE, result); } /** * Creates a succeeded {@code Promise}, backed by the given {@link ExecutorService}. * * @param executorService An {@code ExecutorService} passed to the underlying {@link Future}. * @param result The result. * @param The value type of a successful result. * @return A succeeded {@code Promise}. * @throws NullPointerException if executorService is null */ static Promise successful(ExecutorService executorService, T result) { Objects.requireNonNull(executorService, "executorService is null"); return Promise. make(executorService).success(result); } /** * Returns the {@link ExecutorService} used by this {@code Future}. * * @return The underlying {@code ExecutorService}. */ ExecutorService executorService(); /** * Returns the underlying {@link Future} of this {@code Promise}. * * @return The {@code Future}. */ Future future(); /** * Checks if this {@code Promise} is completed, i.e. has a value. * * @return true, if the computation successfully finished or failed, false otherwise. */ default boolean isCompleted() { return future().isCompleted(); } /** * Completes this {@code Promise} with the given {@code value}. * * @param value Either a {@link Try.Success} containing the result or a {@link Try.Failure} containing an exception. * @return This {@code Promise}. * @throws IllegalStateException if this {@code Promise} has already been completed. */ default Promise complete(Try value) { if (tryComplete(value)) { return this; } else { throw new IllegalStateException("Promise already completed."); } } /** * Attempts to completes this {@code Promise} with the given {@code value}. * * @param value Either a {@link Try.Success} containing the result or a {@link Try.Failure} containing an exception. * @return {@code false} if this {@code Promise} has already been completed, {@code true} otherwise. * @throws IllegalStateException if this {@code Promise} has already been completed. */ boolean tryComplete(Try value); /** * Completes this {@code Promise} with the given {@code Future}, once that {@code Future} is completed. * * @param other Another {@code Future} to react on. * @return This {@code Promise}. */ default Promise completeWith(Future other) { return tryCompleteWith(other); } /** * Attempts to complete this {@code Promise} with the specified {@code Future}, once that {@code Future} is completed. * * @param other Another {@code Future} to react on. * @return This {@code Promise}. */ default Promise tryCompleteWith(Future other) { other.onComplete(this::tryComplete); return this; } /** * Completes this {@code Promise} with the given {@code value}. * * @param value A value. * @return This {@code Promise}. * @throws IllegalStateException if this {@code Promise} has already been completed. */ default Promise success(T value) { return complete(Try.success(value)); } /** * Completes this {@code Promise} with the given {@code value}. * * @param value A value. * @return {@code false} if this {@code Promise} has already been completed, {@code true} otherwise. */ default boolean trySuccess(T value) { return tryComplete(Try.success(value)); } /** * Completes this {@code Promise} with the given {@code exception}. * * @param exception An exception. * @return This {@code Promise}. * @throws IllegalStateException if this {@code Promise} has already been completed. */ default Promise failure(Throwable exception) { return complete(Try.failure(exception)); } /** * Completes this {@code Promise} with the given {@code exception}. * * @param exception An exception. * @return {@code false} if this {@code Promise} has already been completed, {@code true} otherwise. */ default boolean tryFailure(Throwable exception) { return tryComplete(Try.failure(exception)); } } /** * Internal {@code Promise} implementation. * * @param result type * @author Daniel Dietrich * @since 2.0.0 */ final class PromiseImpl implements Promise { final FutureImpl future; PromiseImpl(FutureImpl future) { this.future = future; } @Override public ExecutorService executorService() { return future.executorService(); } @Override public Future future() { return future; } @Override public boolean tryComplete(Try value) { return future.tryComplete(value); } // The underlying FutureImpl is MUTABLE and therefore we CANNOT CHANGE DEFAULT equals() and hashCode() behavior. // See http://stackoverflow.com/questions/4718009/mutable-objects-and-hashcode @Override public String toString() { return "Promise(" + future.getValue().map(String::valueOf).getOrElse("?") + ")"; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy