ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/CancellableTask.java
Revision: 1.9
Committed: Tue Aug 5 00:37:41 2003 UTC (20 years, 10 months ago) by dl
Branch: MAIN
Changes since 1.8: +3 -1 lines
Log Message:
Kill old JSR166Support

File Contents

# User Rev Content
1 dl 1.1 /*
2     * Written by Doug Lea with assistance from members of JCP JSR-166
3     * Expert Group and released to the public domain. Use, modify, and
4     * redistribute this code in any way without acknowledgement.
5     */
6    
7     package java.util.concurrent;
8     import java.util.concurrent.atomic.*;
9 dl 1.6 import java.util.concurrent.locks.*;
10 dl 1.1
11     /**
12     * Base class for cancellable actions running in the Executor
13     * framework. In addition to serving as a standalone class, this
14     * provides <tt>protected</tt> functionality that may be useful when
15     * creating customized task classes.
16 dl 1.5 * @since 1.5
17     * @author Doug Lea
18 dl 1.1 */
19    
20     public class CancellableTask implements Cancellable, Runnable {
21     /**
22     * Holds the run-state, taking on values:
23     * null = not yet started,
24     * [some thread ref] = running,
25     * DONE = completed normally,
26     * CANCELLED = cancelled (may or may not have ever run).
27     * Transitions use atomic updates.
28     */
29     private volatile Object runner;
30    
31 dl 1.5 /**
32 dl 1.1 * Special value for "runner" indicating task is completed
33     */
34     private static final Object DONE = new Object();
35    
36 dl 1.5 /**
37 dl 1.1 * Special value for "runner" indicating task is cancelled
38     */
39     private static final Object CANCELLED = new Object();
40    
41     private static AtomicReferenceFieldUpdater<CancellableTask, Object>
42 dl 1.9 runnerUpdater =
43     AtomicReferenceFieldUpdater.newUpdater
44     (CancellableTask.class, Object.class, "runner");
45 dl 1.1
46     /**
47     * The runnable underlying this task
48     */
49     private volatile Runnable runnable;
50    
51     /**
52 brian 1.4 * Creates a new CancellableTask which invokes the given
53     * <tt>Runnable</tt> when executed.
54 dl 1.5 * @param r the runnable action
55 dl 1.1 */
56     public CancellableTask(Runnable r) {
57     this.runnable = r;
58     }
59    
60     /**
61     * Creates a new CancellableTask without a runnable action, which
62     * must be set using <tt>setRunnable</tt> before use. This is
63     * intended for use in subclasses that must complete superclass
64     * construction beofre establishing the runnable action.
65     */
66     protected CancellableTask() {
67     }
68    
69    
70     public boolean cancel(boolean mayInterruptIfRunning) {
71     Object r = runner;
72     if (r == DONE || r == CANCELLED)
73     return false;
74    
75     if (mayInterruptIfRunning &&
76     r != null &&
77     r instanceof Thread &&
78 dl 1.3 runnerUpdater.compareAndSet(this, r, CANCELLED))
79 dl 1.1
80     ((Thread)r).interrupt();
81 dl 1.3 else
82 dl 1.1 runnerUpdater.set(this, CANCELLED);
83     return true;
84     }
85    
86     public boolean isCancelled() {
87     return runner == CANCELLED;
88     }
89    
90     public boolean isDone() {
91     Object r = runner;
92     return r == DONE || r == CANCELLED;
93     }
94    
95     /**
96     * Return the Runnable forming the basis of this task.
97 dl 1.5 * @return the runnable action
98 dl 1.1 */
99     protected Runnable getRunnable() {
100     return runnable;
101     }
102    
103     /**
104     * Set the Runnable forming the basis of this task.
105 dl 1.5 * @param r the runnable action
106 dl 1.1 */
107     protected void setRunnable(Runnable r) {
108     runnable = r;
109     }
110    
111     /**
112     * Set the state of this task to Cancelled
113     */
114     protected void setCancelled() {
115     runnerUpdater.set(this, CANCELLED);
116     }
117    
118     /**
119     * Set the state of this task to Done, unless already
120     * in a Cancelled state, in which Cancelled status is preserved.
121     *
122     */
123     protected void setDone() {
124     for (;;) {
125     Object r = runner;
126     if (r == DONE || r == CANCELLED)
127     return;
128     if (runnerUpdater.compareAndSet(this, r, DONE))
129     return;
130     }
131     }
132    
133     /**
134     * Attempt to set the state of this task to Running, succeeding
135     * only if the state is currently NOT Done, Running, or Cancelled.
136 dl 1.2 * @return true if successful
137 dl 1.1 */
138     protected boolean setRunning() {
139     return runnerUpdater.compareAndSet(this, null, Thread.currentThread());
140     }
141    
142     public void run() {
143     if (setRunning()) {
144     try {
145     runnable.run();
146     }
147     finally {
148     setDone();
149     }
150     }
151     }
152    
153     /**
154     * Implementation of Future methods under the control of a current
155     * CancellableTask. This is split into an inner class to permit
156     * Future support to be mixed-in with other flavors of tasks.
157     */
158     protected class InnerCancellableFuture<V> implements Future<V>, Runnable {
159     private final Callable<V> callable;
160     private final ReentrantLock lock = new ReentrantLock();
161     private final Condition accessible = lock.newCondition();
162     private V result;
163     private Throwable exception;
164 dl 1.5
165     /**
166     * Create an InnerCancellableFuture that will execute the
167     * given callable.
168     * @param callable the function to execute
169     */
170 dl 1.1 protected InnerCancellableFuture(Callable<V> callable) {
171     this.callable = callable;
172     }
173    
174     public boolean isDone() {
175     return CancellableTask.this.isDone();
176     }
177    
178     public void run() {
179     try {
180     set(callable.call());
181     }
182     catch(Throwable ex) {
183     setException(ex);
184     }
185     }
186    
187     public V get() throws InterruptedException, ExecutionException {
188     lock.lock();
189     try {
190     while (!isDone())
191     accessible.await();
192     if (isCancelled())
193     throw new CancellationException();
194     else if (exception != null)
195     throw new ExecutionException(exception);
196     else
197     return result;
198     }
199     finally {
200     lock.unlock();
201     }
202     }
203    
204     public V get(long timeout, TimeUnit unit)
205     throws InterruptedException, ExecutionException, TimeoutException {
206     lock.lock();
207     try {
208     if (!isDone()) {
209     long nanos = unit.toNanos(timeout);
210     do {
211     if (nanos <= 0)
212     throw new TimeoutException();
213     nanos = accessible.awaitNanos(nanos);
214     } while (!isDone());
215     }
216     if (isCancelled())
217     throw new CancellationException();
218     else if (exception != null)
219     throw new ExecutionException(exception);
220     else
221     return result;
222     }
223     finally {
224     lock.unlock();
225     }
226     }
227    
228     protected void set(V v) {
229     lock.lock();
230     try {
231     result = v;
232     setDone();
233     accessible.signalAll();
234     }
235     finally {
236     lock.unlock();
237     }
238     }
239    
240     protected void setException(Throwable t) {
241     lock.lock();
242     try {
243     exception = t;
244     setDone();
245     accessible.signalAll();
246     }
247     finally {
248     lock.unlock();
249     }
250     }
251     }
252    
253     }