76 */ |
76 */ |
77 protected Runnable runnable; |
77 protected Runnable runnable; |
78 |
78 |
79 /** |
79 /** |
80 * The (potentially null) Object whose notifyAll() method will be called |
80 * The (potentially null) Object whose notifyAll() method will be called |
81 * immediately after the Runnable.run() method returns. |
81 * immediately after the Runnable.run() method has returned or thrown an exception. |
|
82 * |
|
83 * @see #isDispatched |
82 */ |
84 */ |
83 protected Object notifier; |
85 protected Object notifier; |
|
86 |
|
87 /** |
|
88 * Indicates whether the <code>run()</code> method of the <code>runnable</code> |
|
89 * was executed or not. |
|
90 * |
|
91 * @see #isDispatched |
|
92 * @since 1.7 |
|
93 */ |
|
94 private volatile boolean dispatched = false; |
84 |
95 |
85 /** |
96 /** |
86 * Set to true if dispatch() catches Throwable and stores it in the |
97 * Set to true if dispatch() catches Throwable and stores it in the |
87 * exception instance variable. If false, Throwables are propagated up |
98 * exception instance variable. If false, Throwables are propagated up |
88 * to the EventDispatchThread's dispatch loop. |
99 * to the EventDispatchThread's dispatch loop. |
142 /** |
153 /** |
143 * Constructs an <code>InvocationEvent</code> with the specified |
154 * Constructs an <code>InvocationEvent</code> with the specified |
144 * source which will execute the runnable's <code>run</code> |
155 * source which will execute the runnable's <code>run</code> |
145 * method when dispatched. If notifier is non-<code>null</code>, |
156 * method when dispatched. If notifier is non-<code>null</code>, |
146 * <code>notifyAll()</code> will be called on it |
157 * <code>notifyAll()</code> will be called on it |
147 * immediately after <code>run</code> returns. |
158 * immediately after <code>run</code> has returned or thrown an exception. |
148 * <p>An invocation of the form <tt>InvocationEvent(source, |
159 * <p>An invocation of the form <tt>InvocationEvent(source, |
149 * runnable, notifier, catchThrowables)</tt> |
160 * runnable, notifier, catchThrowables)</tt> |
150 * behaves in exactly the same way as the invocation of |
161 * behaves in exactly the same way as the invocation of |
151 * <tt>{@link #InvocationEvent(Object, int, Runnable, Object, boolean) InvocationEvent}(source, InvocationEvent.INVOCATION_DEFAULT, runnable, notifier, catchThrowables)</tt>. |
162 * <tt>{@link #InvocationEvent(Object, int, Runnable, Object, boolean) InvocationEvent}(source, InvocationEvent.INVOCATION_DEFAULT, runnable, notifier, catchThrowables)</tt>. |
152 * <p>This method throws an <code>IllegalArgumentException</code> |
163 * <p>This method throws an <code>IllegalArgumentException</code> |
157 * @param runnable The <code>Runnable</code> whose |
168 * @param runnable The <code>Runnable</code> whose |
158 * <code>run</code> method will be |
169 * <code>run</code> method will be |
159 * executed |
170 * executed |
160 * @param notifier The {@code Object} whose <code>notifyAll</code> |
171 * @param notifier The {@code Object} whose <code>notifyAll</code> |
161 * method will be called after |
172 * method will be called after |
162 * <code>Runnable.run</code> has returned |
173 * <code>Runnable.run</code> has returned or |
|
174 * thrown an exception |
163 * @param catchThrowables Specifies whether <code>dispatch</code> |
175 * @param catchThrowables Specifies whether <code>dispatch</code> |
164 * should catch Throwable when executing |
176 * should catch Throwable when executing |
165 * the <code>Runnable</code>'s <code>run</code> |
177 * the <code>Runnable</code>'s <code>run</code> |
166 * method, or should instead propagate those |
178 * method, or should instead propagate those |
167 * Throwables to the EventDispatchThread's |
179 * Throwables to the EventDispatchThread's |
178 |
190 |
179 /** |
191 /** |
180 * Constructs an <code>InvocationEvent</code> with the specified |
192 * Constructs an <code>InvocationEvent</code> with the specified |
181 * source and ID which will execute the runnable's <code>run</code> |
193 * source and ID which will execute the runnable's <code>run</code> |
182 * method when dispatched. If notifier is non-<code>null</code>, |
194 * method when dispatched. If notifier is non-<code>null</code>, |
183 * <code>notifyAll</code> will be called on it |
195 * <code>notifyAll</code> will be called on it immediately after |
184 * immediately after <code>run</code> returns. |
196 * <code>run</code> has returned or thrown an exception. |
185 * <p>This method throws an |
197 * <p>This method throws an |
186 * <code>IllegalArgumentException</code> if <code>source</code> |
198 * <code>IllegalArgumentException</code> if <code>source</code> |
187 * is <code>null</code>. |
199 * is <code>null</code>. |
188 * |
200 * |
189 * @param source The <code>Object</code> that originated |
201 * @param source The <code>Object</code> that originated |
193 * the class description for {@link InvocationEvent} |
205 * the class description for {@link InvocationEvent} |
194 * @param runnable The <code>Runnable</code> whose |
206 * @param runnable The <code>Runnable</code> whose |
195 * <code>run</code> method will be executed |
207 * <code>run</code> method will be executed |
196 * @param notifier The <code>Object</code> whose <code>notifyAll</code> |
208 * @param notifier The <code>Object</code> whose <code>notifyAll</code> |
197 * method will be called after |
209 * method will be called after |
198 * <code>Runnable.run</code> has returned |
210 * <code>Runnable.run</code> has returned or |
|
211 * thrown an exception |
199 * @param catchThrowables Specifies whether <code>dispatch</code> |
212 * @param catchThrowables Specifies whether <code>dispatch</code> |
200 * should catch Throwable when executing the |
213 * should catch Throwable when executing the |
201 * <code>Runnable</code>'s <code>run</code> |
214 * <code>Runnable</code>'s <code>run</code> |
202 * method, or should instead propagate those |
215 * method, or should instead propagate those |
203 * Throwables to the EventDispatchThread's |
216 * Throwables to the EventDispatchThread's |
215 this.when = System.currentTimeMillis(); |
228 this.when = System.currentTimeMillis(); |
216 } |
229 } |
217 |
230 |
218 /** |
231 /** |
219 * Executes the Runnable's <code>run()</code> method and notifies the |
232 * Executes the Runnable's <code>run()</code> method and notifies the |
220 * notifier (if any) when <code>run()</code> returns. |
233 * notifier (if any) when <code>run()</code> has returned or thrown an exception. |
|
234 * |
|
235 * @see #isDispatched |
221 */ |
236 */ |
222 public void dispatch() { |
237 public void dispatch() { |
223 if (catchExceptions) { |
238 try { |
224 try { |
239 if (catchExceptions) { |
|
240 try { |
|
241 runnable.run(); |
|
242 } |
|
243 catch (Throwable t) { |
|
244 if (t instanceof Exception) { |
|
245 exception = (Exception) t; |
|
246 } |
|
247 throwable = t; |
|
248 } |
|
249 } |
|
250 else { |
225 runnable.run(); |
251 runnable.run(); |
226 } |
252 } |
227 catch (Throwable t) { |
253 } finally { |
228 if (t instanceof Exception) { |
254 dispatched = true; |
229 exception = (Exception) t; |
255 |
|
256 if (notifier != null) { |
|
257 synchronized (notifier) { |
|
258 notifier.notifyAll(); |
230 } |
259 } |
231 throwable = t; |
|
232 } |
|
233 } |
|
234 else { |
|
235 runnable.run(); |
|
236 } |
|
237 |
|
238 if (notifier != null) { |
|
239 synchronized (notifier) { |
|
240 notifier.notifyAll(); |
|
241 } |
260 } |
242 } |
261 } |
243 } |
262 } |
244 |
263 |
245 /** |
264 /** |
273 * @return this event's timestamp |
292 * @return this event's timestamp |
274 * @since 1.4 |
293 * @since 1.4 |
275 */ |
294 */ |
276 public long getWhen() { |
295 public long getWhen() { |
277 return when; |
296 return when; |
|
297 } |
|
298 |
|
299 /** |
|
300 * Returns {@code true} if the event is dispatched or any exception is |
|
301 * thrown while dispatching, {@code false} otherwise. The method should |
|
302 * be called by a waiting thread that calls the {@code notifier.wait()} method. |
|
303 * Since spurious wakeups are possible (as explained in {@link Object#wait()}), |
|
304 * this method should be used in a waiting loop to ensure that the event |
|
305 * got dispatched: |
|
306 * <pre> |
|
307 * while (!event.isDispatched()) { |
|
308 * notifier.wait(); |
|
309 * } |
|
310 * </pre> |
|
311 * If the waiting thread wakes up without dispatching the event, |
|
312 * the {@code isDispatched()} method returns {@code false}, and |
|
313 * the {@code while} loop executes once more, thus, causing |
|
314 * the awakened thread to revert to the waiting mode. |
|
315 * <p> |
|
316 * If the {@code notifier.notifyAll()} happens before the waiting thread |
|
317 * enters the {@code notifier.wait()} method, the {@code while} loop ensures |
|
318 * that the waiting thread will not enter the {@code notifier.wait()} method. |
|
319 * Otherwise, there is no guarantee that the waiting thread will ever be woken |
|
320 * from the wait. |
|
321 * |
|
322 * @return {@code true} if the event has been dispatched, or any exception |
|
323 * has been thrown while dispatching, {@code false} otherwise |
|
324 * @see #dispatch |
|
325 * @see #notifier |
|
326 * @see #catchExceptions |
|
327 * @since 1.7 |
|
328 */ |
|
329 public boolean isDispatched() { |
|
330 return dispatched; |
278 } |
331 } |
279 |
332 |
280 /** |
333 /** |
281 * Returns a parameter string identifying this event. |
334 * Returns a parameter string identifying this event. |
282 * This method is useful for event-logging and for debugging. |
335 * This method is useful for event-logging and for debugging. |