| 
001 /*002  * Copyright 2008-2015 the original author or authors.
 003  *
 004  * Licensed under the Apache License, Version 2.0 (the "License");
 005  * you may not use this file except in compliance with the License.
 006  * You may obtain a copy of the License at
 007  *
 008  *     http://www.apache.org/licenses/LICENSE-2.0
 009  *
 010  * Unless required by applicable law or agreed to in writing, software
 011  * distributed under the License is distributed on an "AS IS" BASIS,
 012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 013  * See the License for the specific language governing permissions and
 014  * limitations under the License.
 015  */
 016 package org.codehaus.griffon.runtime.core.threading;
 017
 018 import griffon.core.ExecutorServiceManager;
 019 import griffon.core.GriffonExceptionHandler;
 020 import griffon.core.threading.UIThreadManager;
 021 import griffon.exceptions.GriffonException;
 022
 023 import javax.annotation.Nonnull;
 024 import javax.annotation.Nullable;
 025 import javax.inject.Inject;
 026 import javax.inject.Named;
 027 import java.util.concurrent.Callable;
 028 import java.util.concurrent.ExecutionException;
 029 import java.util.concurrent.ExecutorService;
 030 import java.util.concurrent.Future;
 031 import java.util.concurrent.FutureTask;
 032
 033 import static java.util.Objects.requireNonNull;
 034
 035 /**
 036  * @author Andres Almiray
 037  * @since 2.0.0
 038  */
 039 public abstract class AbstractUIThreadManager implements UIThreadManager {
 040     protected static final String ERROR_RUNNABLE_NULL = "Argument 'runnable' must not be bull";
 041     protected static final String ERROR_CALLABLE_NULL = "Argument 'callable' must not be null";
 042     private static final Thread.UncaughtExceptionHandler UNCAUGHT_EXCEPTION_HANDLER = new GriffonExceptionHandler();
 043
 044     private ExecutorServiceManager executorServiceManager;
 045
 046     @Inject @Named("defaultExecutorService")
 047     private ExecutorService executorService;
 048
 049     @Inject
 050     public void setExecutorServiceManager(@Nonnull ExecutorServiceManager executorServiceManager) {
 051         requireNonNull(executorServiceManager, "Argument 'executorServiceManager' must not be bull");
 052         if (this.executorServiceManager != null) {
 053             this.executorServiceManager.remove(executorService);
 054         }
 055         this.executorServiceManager = executorServiceManager;
 056         this.executorServiceManager.add(executorService);
 057     }
 058
 059     /**
 060      * Executes a code block as a Future on an ExecutorService.
 061      *
 062      * @param callable a code block to be executed
 063      * @return a Future that contains the result of the execution
 064      */
 065     @Nonnull
 066     public <R> Future<R> runFuture(@Nonnull Callable<R> callable) {
 067         requireNonNull(callable, ERROR_CALLABLE_NULL);
 068         return runFuture(executorService, callable);
 069     }
 070
 071     /**
 072      * Executes a code block as a Future on an ExecutorService.
 073      *
 074      * @param executorService the ExecutorService to use. Will use the default ExecutorService if null.
 075      * @param callable        a code block to be executed
 076      * @return a Future that contains the result of the execution
 077      */
 078     @Nonnull
 079     public <R> Future<R> runFuture(@Nonnull ExecutorService executorService, @Nonnull Callable<R> callable) {
 080         requireNonNull(executorService, "Argument 'executorService' must not be null");
 081         requireNonNull(callable, ERROR_CALLABLE_NULL);
 082         return executorService.submit(callable);
 083     }
 084
 085     public void runOutsideUI(@Nonnull final Runnable runnable) {
 086         requireNonNull(runnable, ERROR_RUNNABLE_NULL);
 087         if (!isUIThread()) {
 088             runnable.run();
 089         } else {
 090             executorService.submit(new Runnable() {
 091                 public void run() {
 092                     try {
 093                         runnable.run();
 094                     } catch (Throwable throwable) {
 095                         UNCAUGHT_EXCEPTION_HANDLER.uncaughtException(Thread.currentThread(), throwable);
 096                     }
 097                 }
 098             });
 099         }
 100     }
 101
 102     @Nullable
 103     @Override
 104     public <R> R runInsideUISync(@Nonnull Callable<R> callable) {
 105         requireNonNull(callable, ERROR_CALLABLE_NULL);
 106         FutureTask<R> ft = new FutureTask<>(callable);
 107         runInsideUISync(ft);
 108         try {
 109             return ft.get();
 110         } catch (InterruptedException | ExecutionException e) {
 111             throw new GriffonException("An error occurred while executing a task inside the UI thread", e);
 112         }
 113     }
 114 }
 |