ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/CancellableTask.java
Revision: 1.2
Committed: Fri Jun 6 16:53:04 2003 UTC (21 years ago) by dl
Branch: MAIN
CVS Tags: JSR166_PRELIMINARY_TEST_RELEASE_1
Changes since 1.1: +1 -1 lines
Log Message:
Minor doc updates; FairReentrantLock serialize now

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