blob: e2c26cb80aa4f31fa02fcbb6a2d68df681e16627 [file] [log] [blame]
/*
* Copyright (c) OSGi Alliance (2014, 2017). All Rights Reserved.
*
* 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 org.osgi.util.promise;
import static java.util.Objects.requireNonNull;
import org.osgi.annotation.versioning.ProviderType;
/**
* A Deferred Promise resolution.
*
* <p>
* Instances of this class can be used to create a {@link Promise} that can be
* resolved in the future. The {@link #getPromise() associated} Promise can be
* successfully resolved with {@link #resolve(Object)} or resolved with a
* failure with {@link #fail(Throwable)}. It can also be resolved with the
* resolution of another promise using {@link #resolveWith(Promise)}.
*
* <p>
* The associated Promise can be provided to any one, but the Deferred object
* should be made available only to the party that will responsible for
* resolving the Promise.
*
* @param <T> The value type associated with the created Promise.
*
* @Immutable
* @author $Id$
*/
@ProviderType
public class Deferred<T> {
/**
* The Promise associated with this Deferred.
*/
private final PromiseImpl<T> promise;
/**
* Create a new Deferred.
* <p>
* The {@link #getPromise() associated promise} will use the default
* callback executor and default scheduled executor.
*
* @see PromiseExecutors#deferred()
*/
public Deferred() {
this(PromiseExecutors.defaultExecutors);
}
/**
* Create a new Deferred with the specified callback and scheduled
* executors.
*
* @param executors The executors to use for callbacks and scheduled
* operations.
* @since 1.1
*/
Deferred(PromiseExecutors executors) {
promise = new PromiseImpl<>(executors);
}
/**
* Returns the Promise associated with this Deferred.
* <p>
* All Promise objects created by the associated Promise will use the
* executors of the associated Promise.
*
* @return The Promise associated with this Deferred.
*/
public Promise<T> getPromise() {
return promise;
}
/**
* Successfully resolve the Promise associated with this Deferred.
*
* <p>
* After the associated Promise is resolved with the specified value, all
* registered {@link Promise#onResolve(Runnable) callbacks} are called and
* any {@link Promise#then(Success, Failure) chained} Promises are resolved.
* This may occur asynchronously to this method.
* <p>
* Resolving the associated Promise <i>happens-before</i> any registered
* callback is called. That is, in a registered callback,
* {@link Promise#isDone()} must return {@code true} and
* {@link Promise#getValue()} and {@link Promise#getFailure()} must not
* block.
*
* @param value The value of the resolved Promise.
* @throws IllegalStateException If the associated Promise was already
* resolved.
*/
public void resolve(T value) {
promise.resolve(value, null);
}
/**
* Fail the Promise associated with this Deferred.
*
* <p>
* After the associated Promise is resolved with the specified failure, all
* registered {@link Promise#onResolve(Runnable) callbacks} are called and
* any {@link Promise#then(Success, Failure) chained} Promises are resolved.
* This may occur asynchronously to this method.
* <p>
* Resolving the associated Promise <i>happens-before</i> any registered
* callback is called. That is, in a registered callback,
* {@link Promise#isDone()} must return {@code true} and
* {@link Promise#getValue()} and {@link Promise#getFailure()} must not
* block.
*
* @param failure The failure of the resolved Promise. Must not be
* {@code null}.
* @throws IllegalStateException If the associated Promise was already
* resolved.
*/
public void fail(Throwable failure) {
promise.resolve(null, requireNonNull(failure));
}
/**
* Resolve the Promise associated with this Deferred with the specified
* Promise.
*
* <p>
* If the specified Promise is successfully resolved, the associated Promise
* is resolved with the value of the specified Promise. If the specified
* Promise is resolved with a failure, the associated Promise is resolved
* with the failure of the specified Promise.
*
* <p>
* After the associated Promise is resolved with the specified Promise, all
* registered {@link Promise#onResolve(Runnable) callbacks} are called and
* any {@link Promise#then(Success, Failure) chained} Promises are resolved.
* This may occur asynchronously to this method.
* <p>
* Resolving the associated Promise <i>happens-before</i> any registered
* callback is called. That is, in a registered callback,
* {@link Promise#isDone()} must return {@code true} and
* {@link Promise#getValue()} and {@link Promise#getFailure()} must not
* block.
*
* @param with A Promise whose value or failure must be used to resolve the
* associated Promise. Must not be {@code null}.
* @return A Promise that is resolved only when the associated Promise is
* resolved by the specified Promise. The returned Promise must be
* successfully resolved with the value {@code null}, if the
* associated Promise was resolved by the specified Promise. The
* returned Promise must be resolved with a failure of
* {@link IllegalStateException}, if the associated Promise was
* already resolved when the specified Promise was resolved.
*/
public Promise<Void> resolveWith(Promise<? extends T> with) {
return promise.resolveWith(with);
}
/**
* Returns a string representation of the associated Promise.
*
* @return A string representation of the associated Promise.
* @since 1.1
*/
@Override
public String toString() {
return promise.toString();
}
}