KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > tc > util > concurrent > TCFuture


1 /**
2  * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright notice. All rights reserved.
3  */

4 package com.tc.util.concurrent;
5
6 import com.tc.exception.TCInternalError;
7 import com.tc.logging.TCLogger;
8 import com.tc.logging.TCLogging;
9 import com.tc.util.TCTimeoutException;
10
11 /**
12  * Class to hold "future" results. This class inspired by <code>FutureResult</code> from util.concurrent, but without
13  * mandating the use of Runnable and/or Callable interfaces
14  *
15  * @author teck
16  */

17 public class TCFuture {
18   private static final TCLogger logger = TCLogging.getLogger(TCFuture.class);
19   private volatile boolean set;
20   private volatile boolean cancel;
21   private volatile boolean timedOut;
22   private volatile Throwable JavaDoc exception;
23   private volatile Object JavaDoc value;
24   private final Object JavaDoc lock;
25
26   public TCFuture() {
27     this(null);
28   }
29   
30   public TCFuture(Object JavaDoc lock) {
31     this.lock = lock == null ? this : lock;
32     cancel = false;
33     value = null;
34     exception = null;
35     set = false;
36   }
37
38   /**
39    * Get the value of this future result, potentially blocking indefinitely until it is avaiable
40    *
41    * @return the value set in this future (which may be null)
42    * @throws InterruptedException if the current thread is interrupted while waiting for the result to be set
43    */

44   public Object JavaDoc get() throws InterruptedException JavaDoc, TCExceptionResultException {
45     try {
46       return get(0);
47     } catch (TCTimeoutException e) {
48       throw new TCInternalError("Timeout not supposed to happen here");
49     }
50   }
51
52   /**
53    * Get the value of this future result within the scope of the given timeout
54    *
55    * @param timeout time (in milliseconds) to wait before throwing a timeout exception. A value of zero will cause this
56    * method to wait indefinitely and a timeout exception will never be thrown
57    * @return the value set in this future (which may be null)
58    * @throws InterruptedException if the current thread is interrupted while waiting for the result to be set
59    * @throws TCTimeoutException if timeout period expires
60    * @throws TCExceptionResultExecption if another thread sets the future result to an exception.
61    * @see setException(Throwable t)
62    */

63   public Object JavaDoc get(long timeout) throws InterruptedException JavaDoc, TCTimeoutException, TCExceptionResultException {
64     return get(timeout, true);
65   }
66
67   /**
68    * Get the value of this future result within the scope of the given timeout
69    *
70    * @param timeout time (in milliseconds) to wait before throwing a timeout exception. A value of zero will cause this
71    * method to wait indefinitely and a timeout exception will never be thrown
72    * @param flagIfTimedOut if set to true and a TCTimeoutException is thrown waiting for the result the timedOut()
73    * method will return true, otherwise it will continue to return false
74    * @return the value set in this future (which may be null)
75    * @throws InterruptedException if the current thread is interrupted while waiting for the result to be set
76    * @throws TCTimeoutException if timeout period expires
77    * @throws TCExceptionResultExecption if another thread sets the future result to an exception.
78    * @see setException(Throwable t)
79    */

80   public Object JavaDoc get(long timeout, boolean flagIfTimedOut) throws InterruptedException JavaDoc, TCTimeoutException,
81       TCExceptionResultException {
82     synchronized (this.lock) {
83       if (cancel) { throw new InterruptedException JavaDoc("Future already cancelled"); }
84
85       while (!set) {
86         if (timeout < 0) { throw new TCTimeoutException("Timeout of " + timeout + " milliseconds occurred"); }
87
88         lock.wait(timeout);
89
90         if (cancel) { throw new InterruptedException JavaDoc("Future was cancelled while waiting"); }
91
92         if ((!set) && (timeout != 0)) {
93           this.timedOut = flagIfTimedOut;
94           throw new TCTimeoutException("Timeout of " + timeout + " milliseconds occured");
95         }
96       }
97
98       if (exception == null) {
99         return value;
100       } else if (exception != null) {
101         // NOTE: this won't work with JDK1.3
102
throw new TCExceptionResultException(exception);
103       }
104
105       throw new TCInternalError("Neither exception nor value set");
106     }
107   }
108
109   /**
110    * Set the value of this future to an exception result. Thread(s) waiting for the result (in method <code>get()</code>)
111    * will be awoken. If this future has been <code>cancel()</code> 'ed, setting the value will have no effect
112    *
113    * @param ex the exception result for this future
114    * @throws IllegalStateException if a result has already been set in this future
115    */

116   public void setException(Throwable JavaDoc ex) {
117     if (ex == null) { throw new IllegalArgumentException JavaDoc("exception result cannot be null"); }
118
119     synchronized (this.lock) {
120       if (cancel) {
121         logger.warn("Exception result set in future after it was cancelled");
122         return;
123       }
124
125       if (set) { throw new IllegalStateException JavaDoc("Future result already set"); }
126
127       set = true;
128       this.exception = ex;
129       this.lock.notifyAll();
130     }
131   }
132
133   /**
134    * Set the value of this future. Thread(s) waiting for the result (in method <code>get()</code>) will be awoken. If
135    * this future has been <code>cancel()</code> 'ed, setting the value will have no effect
136    *
137    * @param value the value to set into this future
138    * @throws IllegalStateException if the value has already been set in this future
139    */

140   public void set(Object JavaDoc value) {
141     synchronized (this.lock) {
142
143       if (cancel) {
144         logger.warn("Value set in future after it was cancelled");
145         return;
146       }
147
148       if (set) { throw new IllegalStateException JavaDoc("Value already set"); }
149
150       set = true;
151       this.value = value;
152       this.lock.notifyAll();
153     }
154   }
155
156   /**
157    * Cancel this future instance. Cancelling a future will cause any threads waiting on this future to receive an
158    * interrupted exception instead of a result value. Calling <code>cancel()</code> after a value has been set does
159    * not "unset" the value
160    */

161   public void cancel() {
162     synchronized (this.lock) {
163       if (set) {
164         logger.warn("Attempt to cancel an already set future value");
165       }
166
167       cancel = true;
168       this.lock.notifyAll();
169     }
170   }
171
172   /**
173    * @return true if a call to get(long,boolean) specified true as an argument and the call timed out, false otherwise.
174    */

175   public boolean timedOut() {
176     return this.timedOut;
177   }
178
179 }
Popular Tags