001: /*
002: * <copyright>
003: *
004: * Copyright 1997-2004 BBNT Solutions, LLC
005: * under sponsorship of the Defense Advanced Research Projects
006: * Agency (DARPA).
007: *
008: * You can redistribute this software and/or modify it under the
009: * terms of the Cougaar Open Source License as published on the
010: * Cougaar Open Source Website (www.cougaar.org).
011: *
012: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
013: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
014: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
015: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
016: * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
017: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
018: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
019: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
020: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
021: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
022: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
023: *
024: * </copyright>
025: */
026:
027: package org.cougaar.util;
028:
029: /**
030: * A Thread class which can be restarted to rerun it's (settable)
031: * runnable object.
032: **/
033:
034: public class ReusableThread extends Thread {
035: /** reference to our thread pool so we can return when we die **/
036: private ReusableThreadPool pool;
037:
038: /** our runnable object, or null if we haven't been assigned one **/
039: private Runnable runnable = null;
040:
041: /** Has this thread already be actually started yet?
042: * access needs to be guarded by runLock.
043: **/
044: private boolean isStarted = false;
045:
046: /** are we actively running the runnable? **/
047: private boolean isRunning = false;
048:
049: /** guards isRunning, synced while actually executing and waits when
050: * suspended.
051: **/
052: private Object runLock = new Object();
053:
054: public void setRunnable(Runnable r) {
055: runnable = r;
056: }
057:
058: protected Runnable getRunnable() {
059: return runnable;
060: }
061:
062: /** The only constructor. **/
063: public ReusableThread(ReusableThreadPool p) {
064: super (p.getThreadGroup(), null, "ReusableThread");
065: setDaemon(true);
066: pool = p;
067: }
068:
069: // Hook for subclasses
070: protected void claim() {
071: }
072:
073: public final void run() {
074: while (true) {
075: synchronized (runLock) {
076: claim();
077: Runnable r = getRunnable();
078: if (r != null)
079: r.run();
080: isRunning = false;
081:
082: reclaim();
083:
084: try {
085: runLock.wait(); // suspend
086: } catch (InterruptedException ie) {
087: }
088: }
089: }
090: }
091:
092: public void start() throws IllegalThreadStateException {
093: synchronized (runLock) {
094: if (isRunning)
095: throw new IllegalThreadStateException(
096: "ReusableThread already started: " + this );
097: isRunning = true;
098:
099: if (!isStarted) {
100: isStarted = true;
101: super .start();
102: } else {
103: runLock.notify(); // resume
104: }
105: }
106: }
107:
108: protected synchronized void reclaim() {
109: pool.reclaimReusableThread(this);
110: notifyAll();
111: }
112: }
|