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

org.wisdom.executors.Task Maven / Gradle / Ivy

/*
 * #%L
 * Wisdom-Framework
 * %%
 * Copyright (C) 2013 - 2015 Wisdom Framework
 * %%
 * 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.
 * #L%
 */
package org.wisdom.executors;

import com.google.common.util.concurrent.*;
import org.wisdom.api.concurrent.ExecutionContext;
import org.wisdom.api.concurrent.ManagedFutureTask;

import java.util.concurrent.*;

/**
 * Implementation of {@link org.wisdom.api.concurrent.ManagedFutureTask} to be
 * used with {@link org.wisdom.executors.ManagedExecutorServiceImpl}.
 *
 * @param  the type of the result computed by the task. {@link Void} for task not computing a result.
 */
public class Task extends FutureTask implements ListenableFuture, ManagedFutureTask {

    private final ListeningExecutorService executor;
    private final ExecutionContext executionContext;
    protected final Callable callable;
    protected ListenableFuture future;
    private Throwable taskRunThrowable;
    private final AbstractManagedExecutorService parent;

    protected long submissionDate;
    private long startDate;
    private long completionDate;
    private long hungTime;

    protected Task(
            ListeningExecutorService executor,
            Runnable runnable,
            V result,
            ExecutionContext executionContext,
            long hungTime,
            AbstractManagedExecutorService parent) {
        super(runnable, result);
        this.callable = new EnhancedCallable(Executors.callable(runnable, result));
        this.executor = executor;
        this.executionContext = executionContext;
        this.hungTime = hungTime;
        this.parent = parent;
    }

    /**
     * Creates a task.
     *
     * @param executor         the executor service
     * @param callable         the callable object
     * @param executionContext the execution context used to execute the task
     * @param hungTime         the hung time for the executor service
     * @param parent           the {@link AbstractManagedExecutorService} having created this task
     */
    public Task(
            ListeningExecutorService executor,
            Callable callable,
            ExecutionContext executionContext,
            long hungTime,
            AbstractManagedExecutorService parent) {
        super(callable);
        this.callable = new EnhancedCallable(callable);
        this.executor = executor;
        this.executionContext = executionContext;
        this.hungTime = hungTime;
        this.parent = parent;
    }

    protected Task execute() {
        ListenableFuture future = executor.submit(callable);
        submitted(future);
        return this;
    }

    protected Task submitted(Future future) {
        this.submissionDate = System.currentTimeMillis();
        this.future = JdkFutureAdapters.listenInPoolThread(future);
        return this;
    }

    /**
     * Registers a listener on this task. The listener is invoked when the task is completed. The listener is executed
     * the same executor as the task.
     *
     * @param listener the listener.
     */
    public void addListener(Runnable listener) {
        addListener(listener, executor);
    }

    @Override
    public void addListener(Runnable listener, Executor exec) {
        this.future.addListener(listener, exec);
    }

    @Override
    public boolean cancel(boolean mayInterruptIfRunning) {
        return this.future != null && this.future.cancel(mayInterruptIfRunning);
    }

    @Override
    public V get() throws InterruptedException, ExecutionException {
        return this.future.get();
    }

    @Override
    public V get(long timeout, TimeUnit unit) throws InterruptedException, TimeoutException, ExecutionException {
        return this.future.get(timeout, unit);
    }

    @Override
    public boolean isCancelled() {
        return this.future.isCancelled();
    }

    @Override
    public boolean isDone() {
        return this.future.isDone();
    }

    /**
     * @return the {@link Throwable} object that could have been thrown while executing this task. {@code null} if
     * the task execution succeed.
     */
    public Throwable cause() {
        return taskRunThrowable;
    }

    @Override
    protected void setException(Throwable throwable) {
        taskRunThrowable = throwable;
    }

    @Override
    public Task onSuccess(final SuccessCallback callback, Executor executor) {
        Futures.addCallback(future, new FutureCallback() {
            @Override
            public void onSuccess(V v) {
                callback.onSuccess(Task.this, v);
            }

            @Override
            public void onFailure(Throwable throwable) {
                // Do nothing.
            }
        }, executor);
        return this;
    }

    @Override
    public Task onSuccess(final SuccessCallback callback) {
        return onSuccess(callback, executor);
    }

    @Override
    public Task onFailure(final FailureCallback callback, Executor executor) {
        Futures.addCallback(future, new FutureCallback() {
            @Override
            public void onSuccess(V v) {
                // Do nothing
            }

            @Override
            public void onFailure(Throwable throwable) {
                callback.onFailure(Task.this, throwable);
            }
        }, executor);
        return this;
    }

    @Override
    public Task onFailure(final FailureCallback callback) {
        return onFailure(callback, executor);
    }

    @Override
    public boolean isTaskHang() {
        // The task was completed.
        return completionDate == 0 && System.currentTimeMillis() - submissionDate >= hungTime;
    }

    @Override
    public boolean isShutdown() {
        return executor.isShutdown();
    }

    @Override
    public long getTaskStartTime() {
        return startDate;
    }

    @Override
    public long getTaskCompletionTime() {
        return completionDate;
    }

    @Override
    public long getTaskRunTime() {
        if (startDate == 0) {
            return 0;
        }
        if (completionDate == 0) {
            return System.currentTimeMillis() - startDate;
        }
        return completionDate - startDate;
    }


    @Override
    public long getHungTaskThreshold() {
        return hungTime;
    }

    @Override
    public ExecutionContext getExecutionContext() {
        return executionContext;
    }

    class EnhancedCallable implements Callable {

        private final Callable delegate;

        private EnhancedCallable(Callable delegate) {
            this.delegate = delegate;
        }

        @Override
        public V call() throws Exception {
            try {
                if (executionContext != null) {
                    executionContext.apply();
                }
                startDate = System.currentTimeMillis();
                return delegate.call();
            } catch (Throwable e) { //NOSONAR
                // We set the exception in the task.
                setException(e);
                throw e;
            } finally {
                completionDate = System.currentTimeMillis();
                if (executionContext != null) {
                    executionContext.unapply();
                }
                parent.addToStatistics(Task.this);
            }
        }
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy