OSDN Git Service

ad7a5b7893e02711673d69065ff8f0f7a389922d
[mikumikustudio/MikuMikuStudio.git] / src / com / jme / util / GameTask.java
1 /*
2  * Copyright (c) 2003-2009 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.jme.util;
33
34 import java.util.concurrent.Callable;
35 import java.util.concurrent.ExecutionException;
36 import java.util.concurrent.Future;
37 import java.util.concurrent.TimeUnit;
38 import java.util.concurrent.TimeoutException;
39 import java.util.concurrent.locks.Condition;
40 import java.util.concurrent.locks.ReentrantLock;
41 import java.util.logging.Level;
42 import java.util.logging.Logger;
43
44 /**
45  * <code>GameTask</code> is used in <code>GameTaskQueue</code> to manage tasks that have
46  * yet to be accomplished.
47  * 
48  * @author Matthew D. Hicks, lazloh
49  */
50 public class GameTask<V> implements Future<V> {
51     private static final Logger logger = Logger.getLogger(GameTask.class
52             .getName());
53     
54     private final Callable<V> callable;
55     
56     private V result;
57     private ExecutionException exception;
58     private boolean cancelled, finished;
59     private final ReentrantLock stateLock = new ReentrantLock();
60     private final Condition finishedCondition = stateLock.newCondition();
61     
62     public GameTask(Callable<V> callable) {
63         this.callable = callable;
64     }
65     
66     public boolean cancel(boolean mayInterruptIfRunning) {
67         // TODO mayInterruptIfRunning was ignored in previous code, should this param be removed?
68         stateLock.lock();
69         try {
70                 if (result != null) {
71                         return false;
72                 }
73                 cancelled = true;
74                 
75                 finishedCondition.signalAll();
76                 
77                 return true;
78         } finally {
79                 stateLock.unlock();
80         }
81     }
82
83     public V get() throws InterruptedException, ExecutionException {
84         stateLock.lock();
85         try {
86                 while (!isDone()) {
87                         finishedCondition.await();
88                 }
89                 if (exception != null) {
90                         throw exception;
91                 }
92                 return result;
93         } finally {
94                 stateLock.unlock();
95         }
96     }
97
98     public V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
99         stateLock.lock();
100         try {
101                 if (!isDone()) {
102                         finishedCondition.await(timeout, unit);
103                 }
104                 if (exception != null) {
105                         throw exception;
106                 }
107                 if (result == null) {
108                         throw new TimeoutException("Object not returned in time allocated.");
109                 }
110                 return result;
111         } finally {
112                 stateLock.unlock();
113         }
114     }
115     
116     public boolean isCancelled() {
117         stateLock.lock();
118         try {
119                 return cancelled;
120         } finally {
121                 stateLock.unlock();
122         }
123     }
124
125     public boolean isDone() {
126         stateLock.lock();
127         try {
128                 return finished || cancelled || (exception != null);
129         } finally {
130                 stateLock.unlock();
131         }
132     }
133     
134     public Callable<V> getCallable() {
135         return callable;
136     }
137     
138     public void invoke() {
139         try {
140                 final V tmpResult = callable.call();
141                 
142                 stateLock.lock();
143                 try {
144                         result = tmpResult;
145                         finished = true;
146                         
147                         finishedCondition.signalAll();
148                 } finally {
149                         stateLock.unlock();
150                 }
151         } catch(Exception e) {
152                 logger.logp(Level.SEVERE, this.getClass().toString(), "invoke()", "Exception", e);
153                 
154                 stateLock.lock();
155                 try {
156                         exception = new ExecutionException(e);
157                         
158                         finishedCondition.signalAll();
159                 } finally {
160                         stateLock.unlock();
161                 }
162         }
163     }
164     
165 }