• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2009-2010 jMonkeyEngine
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  * * Redistributions of source code must retain the above copyright
10  *   notice, this list of conditions and the following disclaimer.
11  *
12  * * Redistributions in binary form must reproduce the above copyright
13  *   notice, this list of conditions and the following disclaimer in the
14  *   documentation and/or other materials provided with the distribution.
15  *
16  * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
17  *   may be used to endorse or promote products derived from this software
18  *   without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 package com.jme3.app;
33 
34 import java.util.concurrent.*;
35 import java.util.concurrent.locks.Condition;
36 import java.util.concurrent.locks.ReentrantLock;
37 import java.util.logging.Level;
38 import java.util.logging.Logger;
39 
40 /**
41  * <code>AppTask</code> is used in <code>AppTaskQueue</code> to manage tasks that have
42  * yet to be accomplished. The AppTask system is used to execute tasks either
43  * in the OpenGL/Render thread, or outside of it.
44  *
45  * @author Matthew D. Hicks, lazloh
46  */
47 public class AppTask<V> implements Future<V> {
48     private static final Logger logger = Logger.getLogger(AppTask.class
49             .getName());
50 
51     private final Callable<V> callable;
52 
53     private V result;
54     private ExecutionException exception;
55     private boolean cancelled, finished;
56     private final ReentrantLock stateLock = new ReentrantLock();
57     private final Condition finishedCondition = stateLock.newCondition();
58 
59     /**
60      * Create an <code>AppTask</code> that will execute the given
61      * {@link Callable}.
62      *
63      * @param callable The callable to be executed
64      */
AppTask(Callable<V> callable)65     public AppTask(Callable<V> callable) {
66         this.callable = callable;
67     }
68 
cancel(boolean mayInterruptIfRunning)69     public boolean cancel(boolean mayInterruptIfRunning) {
70         stateLock.lock();
71         try {
72             if (result != null) {
73                 return false;
74             }
75             cancelled = true;
76 
77             finishedCondition.signalAll();
78 
79             return true;
80         } finally {
81             stateLock.unlock();
82         }
83     }
84 
get()85     public V get() throws InterruptedException, ExecutionException {
86         stateLock.lock();
87         try {
88             while (!isDone()) {
89                 finishedCondition.await();
90             }
91             if (exception != null) {
92                 throw exception;
93             }
94             return result;
95         } finally {
96             stateLock.unlock();
97         }
98     }
99 
get(long timeout, TimeUnit unit)100     public V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
101         stateLock.lock();
102         try {
103             if (!isDone()) {
104                 finishedCondition.await(timeout, unit);
105             }
106             if (exception != null) {
107                 throw exception;
108             }
109             if (result == null) {
110                 throw new TimeoutException("Object not returned in time allocated.");
111             }
112             return result;
113         } finally {
114             stateLock.unlock();
115         }
116     }
117 
isCancelled()118     public boolean isCancelled() {
119         stateLock.lock();
120         try {
121             return cancelled;
122         } finally {
123             stateLock.unlock();
124         }
125     }
126 
isDone()127     public boolean isDone() {
128         stateLock.lock();
129         try {
130             return finished || cancelled || (exception != null);
131         } finally {
132             stateLock.unlock();
133         }
134     }
135 
getCallable()136     public Callable<V> getCallable() {
137         return callable;
138     }
139 
invoke()140     public void invoke() {
141         try {
142             final V tmpResult = callable.call();
143 
144             stateLock.lock();
145             try {
146                 result = tmpResult;
147                 finished = true;
148 
149                 finishedCondition.signalAll();
150             } finally {
151                 stateLock.unlock();
152             }
153         } catch (Exception e) {
154             logger.logp(Level.SEVERE, this.getClass().toString(), "invoke()", "Exception", e);
155 
156             stateLock.lock();
157             try {
158                 exception = new ExecutionException(e);
159 
160                 finishedCondition.signalAll();
161             } finally {
162                 stateLock.unlock();
163             }
164         }
165     }
166 
167 }