brooklyn.util.task.Tasks Maven / Gradle / Ivy
package brooklyn.util.task;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import brooklyn.management.ExecutionContext;
import brooklyn.management.Task;
import brooklyn.util.flags.TypeCoercions;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
public class Tasks {
private static final Logger log = LoggerFactory.getLogger(Tasks.class);
/** convenience for setting "blocking details" on any task where the current thread is running;
* typically invoked prior to a wait, for transparency to a user;
* then invoked with 'null' just after the wait */
public static void setBlockingDetails(String description) {
Task current = current();
if (current instanceof BasicTask)
((BasicTask)current).setBlockingDetails(description);
}
/** convenience for setting "blocking details" on any task where the current thread is running,
* while the passed code is executed; often used from groovy as
* {@code withBlockingDetails("sleeping 5s") { Thread.sleep(5000); } }
* If code block is null, the description is set until further notice (not cleareed). */
@SuppressWarnings("rawtypes")
public static T withBlockingDetails(String description, Callable code) throws Exception {
Task current = current();
if (code==null) {
log.warn("legacy invocation of withBlockingDetails with null code block, ignoring");
return null;
}
if (current instanceof BasicTask)
((BasicTask)current).setBlockingDetails(description);
try {
return code.call();
} finally {
if (current instanceof BasicTask)
((BasicTask)current).setBlockingDetails(null);
}
}
/** the {@link Task} where the current thread is executing, if executing in a Task, otherwise null */
@SuppressWarnings("rawtypes")
public static Task current() { return BasicExecutionManager.getPerThreadCurrentTask().get(); }
/** @see #resolveValue(Object, Class, ExecutionContext, String) */
public static T resolveValue(Object v, Class type, ExecutionContext exec) throws ExecutionException, InterruptedException {
return resolveValue(v, type, exec, null);
}
/** attempt to resolve the given value as the given type, waiting on futures, submitting if necessary,
* and coercing as allowed by TypeCoercions;
* contextMessage (optional) will be displayed in status reports while it waits (e.g. the name of the config key being looked up) */
@SuppressWarnings({ "unchecked", "rawtypes" })
public static T resolveValue(Object v, Class type, ExecutionContext exec, String contextMessage) throws ExecutionException, InterruptedException {
//if the expected type is a closure or map and that's what we have, we're done (or if it's null);
//but not allowed to return a future or DeferredSupplier as the resolved value
if (v==null || (type.isInstance(v) && !Future.class.isInstance(v) && !DeferredSupplier.class.isInstance(v)))
return (T) v;
try {
//if it's a task or a future, we wait for the task to complete
if (v instanceof Task) {
//if it's a task, we make sure it is submitted
//(perhaps could run it here? ... tbd)
if (!((Task) v).isSubmitted() ) {
exec.submit((Task) v);
}
}
if (v instanceof Future) {
final Future> vfuture = (Future>) v;
//including tasks, above
if (!vfuture.isDone()) {
final AtomicReference
© 2015 - 2025 Weber Informatics LLC | Privacy Policy