|
|||||||||||||||||||
| Source file | Conditionals | Statements | Methods | TOTAL | |||||||||||||||
| SwingWorker.java | 0% | 0% | 0% | 0% |
|
||||||||||||||
| 1 | /*BEGIN_COPYRIGHT_BLOCK* | |
| 2 | ||
| 3 | PLT Utilities BSD License | |
| 4 | ||
| 5 | Copyright (c) 2007-2010 JavaPLT group at Rice University | |
| 6 | All rights reserved. | |
| 7 | ||
| 8 | Developed by: Java Programming Languages Team | |
| 9 | Rice University | |
| 10 | http://www.cs.rice.edu/~javaplt/ | |
| 11 | ||
| 12 | Redistribution and use in source and binary forms, with or without modification, are permitted | |
| 13 | provided that the following conditions are met: | |
| 14 | ||
| 15 | - Redistributions of source code must retain the above copyright notice, this list of conditions | |
| 16 | and the following disclaimer. | |
| 17 | - Redistributions in binary form must reproduce the above copyright notice, this list of | |
| 18 | conditions and the following disclaimer in the documentation and/or other materials provided | |
| 19 | with the distribution. | |
| 20 | - Neither the name of the JavaPLT group, Rice University, nor the names of the library's | |
| 21 | contributors may be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR | |
| 25 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND | |
| 26 | FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND | |
| 27 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
| 28 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
| 29 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER | |
| 30 | IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT | |
| 31 | OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| 32 | ||
| 33 | *END_COPYRIGHT_BLOCK*/ | |
| 34 | ||
| 35 | package edu.rice.cs.plt.swing; | |
| 36 | ||
| 37 | import java.util.LinkedList; | |
| 38 | import java.util.List; | |
| 39 | import java.util.concurrent.BlockingQueue; | |
| 40 | ||
| 41 | import javax.swing.SwingUtilities; | |
| 42 | ||
| 43 | import edu.rice.cs.plt.lambda.Runnable1; | |
| 44 | import edu.rice.cs.plt.lambda.WrappedException; | |
| 45 | import edu.rice.cs.plt.concurrent.CompletionMonitor; | |
| 46 | import edu.rice.cs.plt.concurrent.IncrementalTaskController; | |
| 47 | ||
| 48 | /** | |
| 49 | * <p>A utility class providing the core functionality of {@code javax.swing.SwingWorker} (first available | |
| 50 | * in Java 6), in addition to supporting the IncrementalTaskController interface. Allows a task to be | |
| 51 | * separated into two parts: a working portion that calculates a value (or sequence of intermediate values) | |
| 52 | * in the background, and a GUI portion that executes in the Swing event thread when the working portion is | |
| 53 | * complete. Implementations should define {@link #doInBackground} and, optionally, {@link #process} | |
| 54 | * and {@link #done}. The {@code doInBackground()} implementation may call {@link #publish} | |
| 55 | * and {@link #authorizeContinue}; other protected methods should generally be ignored as implementation | |
| 56 | * details.</p> | |
| 57 | * | |
| 58 | * <p>Implementations should be able to migrate seamlessly to the Java 6 API version by simply changing | |
| 59 | * the parent class, as long as they stick to methods that are defined in both classes. This version doesn't | |
| 60 | * support PropertyChangeListeners, a progress property, the Runnable interface, a {@code getState()} method | |
| 61 | * (although {@code status()} provides similar information), or an {@code isCancelled()} method that can be | |
| 62 | * polled by {@code doInBackground()} ({@code isCancelled()} is defined, but its result is never | |
| 63 | * {@code true} before {@code doInBackground()} returns; implementations should instead handle cancellation | |
| 64 | * by checking for an interrupt). There is also (currently) no thread pooling — | |
| 65 | * each worker runs in a new thread. This version <em>adds</em> the methods provided by | |
| 66 | * IncrementalTaskController, as well as {@link #authorizeContinue}, which supports the implementation | |
| 67 | * of {@link #pause}.</p> | |
| 68 | */ | |
| 69 | public abstract class SwingWorker<R, I> extends IncrementalTaskController<I, R> { | |
| 70 | ||
| 71 | private CompletionMonitor _continueMonitor; | |
| 72 | private Thread _workerThread; | |
| 73 | ||
| 74 | 0 | public SwingWorker() { |
| 75 | 0 | super(); |
| 76 | 0 | _continueMonitor = new CompletionMonitor(false); |
| 77 | 0 | _workerThread = new Thread("SwingWorker") { |
| 78 | 0 | public void run() { |
| 79 | 0 | started(); |
| 80 | 0 | try { finishedCleanly(doInBackground()); } |
| 81 | 0 | catch (InterruptedException e) { stopped(); } |
| 82 | 0 | catch (Exception e) { finishedWithTaskException(e); } |
| 83 | 0 | catch (Throwable t) { finishedWithImplementationException(new WrappedException(t)); } |
| 84 | } | |
| 85 | }; | |
| 86 | 0 | finishListeners().add(new Runnable() { |
| 87 | 0 | public void run() { |
| 88 | 0 | SwingUtilities.invokeLater(new Runnable() { |
| 89 | 0 | public void run() { done(); } |
| 90 | }); | |
| 91 | } | |
| 92 | }); | |
| 93 | // Defined as a stand-alone class in order to simplify self-references. | |
| 94 | class IntermediateListener implements Runnable1<I> { | |
| 95 | 0 | public void run(I val) { |
| 96 | 0 | intermediateListeners().remove(this); // don't respond again until the Swing task runs |
| 97 | 0 | SwingUtilities.invokeLater(new Runnable() { |
| 98 | 0 | public void run() { |
| 99 | 0 | List<I> vals = new LinkedList<I>(); |
| 100 | // add listener before drain to ensure a concurrent write isn't missed | |
| 101 | 0 | intermediateListeners().add(IntermediateListener.this); |
| 102 | 0 | intermediateQueue().drainTo(vals); |
| 103 | 0 | process(vals); |
| 104 | } | |
| 105 | }); | |
| 106 | } | |
| 107 | } | |
| 108 | 0 | @SuppressWarnings("unchecked") // javac 6 bug (Eclipse and javac 5 are fine) |
| 109 | Runnable1<I> listener = new IntermediateListener(); | |
| 110 | 0 | intermediateListeners().add(listener); |
| 111 | } | |
| 112 | ||
| 113 | ||
| 114 | /*=== Public SwingWorker interface. ===*/ | |
| 115 | ||
| 116 | 0 | public final void execute() { start(); } |
| 117 | ||
| 118 | ||
| 119 | /*=== Methods to be overridden by the subclass. ===*/ | |
| 120 | ||
| 121 | /** Work to be performed in a worker thread. */ | |
| 122 | protected abstract R doInBackground() throws Exception; | |
| 123 | ||
| 124 | /** Action to be performed in the event thread when intermediate results are available. */ | |
| 125 | 0 | protected void process(List<I> chunks) {} |
| 126 | ||
| 127 | /** Action to be performed in the event thread when work has completed. */ | |
| 128 | 0 | protected void done() {} |
| 129 | ||
| 130 | ||
| 131 | /*=== Methods that the subclass may call in doInBackground(). ===*/ | |
| 132 | ||
| 133 | /** Called by {@link #doInBackground} when intermediate results are available. */ | |
| 134 | 0 | protected final void publish(I... chunks) { |
| 135 | 0 | BlockingQueue<I> queue = intermediateQueue(); |
| 136 | 0 | try { |
| 137 | 0 | for (I val : chunks) { queue.put(val); } |
| 138 | } | |
| 139 | 0 | catch (InterruptedException e) { throw new WrappedException(e); } |
| 140 | } | |
| 141 | ||
| 142 | /** | |
| 143 | * <p>Called by {@link #doInBackground} to ensure that the task has not been paused or canceled. | |
| 144 | * If paused, this method blocks until the task is restarted. If canceled, throws an | |
| 145 | * InterruptedException.</p> | |
| 146 | * | |
| 147 | * <p>Tasks that wish to maintain migration compatibility with {@code javax.swing.SwingWorker} cannot | |
| 148 | * call this method or support pausing. Instead, they should simply respond to an interrupt when canceled | |
| 149 | * (checking, for example, via {@link Thread#interrupted}).</p> | |
| 150 | */ | |
| 151 | 0 | protected void authorizeContinue() throws InterruptedException { |
| 152 | 0 | if (Thread.interrupted()) { throw new InterruptedException(); } |
| 153 | 0 | if (!_continueMonitor.isSignaled()) { |
| 154 | 0 | paused(); |
| 155 | 0 | _continueMonitor.ensureSignaled(); |
| 156 | 0 | started(); |
| 157 | } | |
| 158 | } | |
| 159 | ||
| 160 | ||
| 161 | /*=== Implementation of IncrementalTaskController. ===*/ | |
| 162 | ||
| 163 | ||
| 164 | 0 | protected final void doStart() { |
| 165 | 0 | _continueMonitor.signal(); |
| 166 | 0 | _workerThread.start(); |
| 167 | } | |
| 168 | 0 | protected final void doPause() { _continueMonitor.reset(); } |
| 169 | 0 | protected final void doResume() { _continueMonitor.signal(); } |
| 170 | 0 | protected final void doStop() { _workerThread.interrupt(); } |
| 171 | ||
| 172 | } |
|
||||||||||