001: /*
002: * WorkThread.java - Background thread that does stuff
003: * Copyright (C) 2000 Slava Pestov
004: *
005: * This program is free software; you can redistribute it and/or
006: * modify it under the terms of the GNU General Public License
007: * as published by the Free Software Foundation; either version 2
008: * of the License, or any later version.
009: *
010: * This program is distributed in the hope that it will be useful,
011: * but WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
013: * GNU General Public License for more details.
014: *
015: * You should have received a copy of the GNU General Public License
016: * along with this program; if not, write to the Free Software
017: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
018: */
019:
020: package org.gjt.sp.util;
021:
022: /**
023: * Services work requests in the background.
024: * @author Slava Pestov
025: * @version $Id: WorkThread.java 10796 2007-10-04 08:46:18Z kpouer $
026: */
027: public class WorkThread extends Thread implements ThreadAbortMonitor {
028: public WorkThread(WorkThreadPool pool, ThreadGroup group,
029: String name) {
030: super (group, name);
031: // so that jEdit doesn't exit with no views open automatically
032: //setDaemon(true);
033: setPriority(Thread.MIN_PRIORITY);
034:
035: this .pool = pool;
036: }
037:
038: /**
039: * Sets if the current request can be aborted.
040: * If set to true and already aborted, the thread will be stopped
041: *
042: * @param abortable true if the WorkThread is abortable
043: * @since jEdit 2.6pre1
044: */
045: public void setAbortable(boolean abortable) {
046: synchronized (abortLock) {
047: this .abortable = abortable;
048: if (aborted)
049: stop(new Abort());
050: }
051: }
052:
053: /**
054: * Returns if the work thread is currently running a request.
055: * @return true if a request is currently running
056: */
057: public boolean isRequestRunning() {
058: return requestRunning;
059: }
060:
061: public boolean isAborted() {
062: synchronized (abortLock) {
063: return aborted;
064: }
065: }
066:
067: /**
068: * Returns the status text.
069: * @return the status label
070: */
071: public String getStatus() {
072: return status;
073: }
074:
075: /**
076: * Sets the status text.
077: * @param status the new status of the thread
078: * @since jEdit 2.6pre1
079: */
080: public void setStatus(String status) {
081: this .status = status;
082: pool.fireProgressChanged(this );
083: }
084:
085: /**
086: * Returns the progress value.
087: * @return the progress value
088: */
089: public int getProgressValue() {
090: return progressValue;
091: }
092:
093: /**
094: * Sets the progress value.
095: * @param progressValue the new progress value
096: * @since jEdit 2.6pre1
097: */
098: public void setProgressValue(int progressValue) {
099: this .progressValue = progressValue;
100: pool.fireProgressChanged(this );
101: }
102:
103: /**
104: * Returns the progress maximum.
105: * @return the maximum value of the progression
106: */
107: public int getProgressMaximum() {
108: return progressMaximum;
109: }
110:
111: /**
112: * Sets the maximum progress value.
113: * @param progressMaximum the maximum value of the progression
114: * @since jEdit 2.6pre1
115: */
116: public void setProgressMaximum(int progressMaximum) {
117: this .progressMaximum = progressMaximum;
118: pool.fireProgressChanged(this );
119: }
120:
121: /**
122: * Aborts the currently running request, if allowed.
123: * @since jEdit 2.6pre1
124: */
125: public void abortCurrentRequest() {
126: synchronized (abortLock) {
127: if (abortable && !aborted)
128: stop(new Abort());
129: aborted = true;
130: }
131: }
132:
133: public void run() {
134: Log.log(Log.DEBUG, this , "Work request thread starting ["
135: + getName() + "]");
136:
137: for (;;) {
138: doRequests();
139: }
140: }
141:
142: // private members
143: private WorkThreadPool pool;
144: private final Object abortLock = new Object();
145: private boolean requestRunning;
146: private boolean abortable;
147: private boolean aborted;
148: private String status;
149: private int progressValue;
150: private int progressMaximum;
151:
152: private void doRequests() {
153: WorkThreadPool.Request request;
154: for (;;) {
155: request = pool.getNextRequest();
156: if (request == null)
157: break;
158: else {
159: requestRunning = true;
160: pool.fireStatusChanged(this );
161: doRequest(request);
162: requestRunning = false;
163: }
164: }
165:
166: pool.fireStatusChanged(this );
167:
168: synchronized (pool.waitForAllLock) {
169: // notify a running waitForRequests() method
170: pool.waitForAllLock.notifyAll();
171: }
172:
173: synchronized (pool.lock) {
174: // wait for more requests
175: try {
176: pool.lock.wait();
177: } catch (InterruptedException ie) {
178: Log.log(Log.ERROR, this , ie);
179: }
180: }
181: }
182:
183: private void doRequest(WorkThreadPool.Request request) {
184: Log.log(Log.DEBUG, WorkThread.class, "Running in work thread: "
185: + request);
186:
187: try {
188: request.run.run();
189: } catch (Abort a) {
190: Log.log(Log.ERROR, WorkThread.class, "Unhandled abort", a);
191: } catch (Throwable t) {
192: Log.log(Log.ERROR, WorkThread.class,
193: "Exception in work thread: ", t);
194: } finally {
195: synchronized (abortLock) {
196: aborted = abortable = false;
197: }
198: status = null;
199: progressValue = progressMaximum = 0;
200: pool.requestDone();
201: pool.fireStatusChanged(this );
202: }
203: }
204:
205: public static class Abort extends Error {
206: public Abort() {
207: super ("Work request aborted");
208: }
209: }
210: }
|