001 /**
002 * ========================================
003 * JFreeReport : a free Java report library
004 * ========================================
005 *
006 * Project Info: http://reporting.pentaho.org/
007 *
008 * (C) Copyright 2000-2007, by Object Refinery Limited, Pentaho Corporation and Contributors.
009 *
010 * This library is free software; you can redistribute it and/or modify it under the terms
011 * of the GNU Lesser General Public License as published by the Free Software Foundation;
012 * either version 2.1 of the License, or (at your option) any later version.
013 *
014 * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
015 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
016 * See the GNU Lesser General Public License for more details.
017 *
018 * You should have received a copy of the GNU Lesser General Public License along with this
019 * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
020 * Boston, MA 02111-1307, USA.
021 *
022 * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
023 * in the United States and other countries.]
024 *
025 * ------------
026 * $Id: Worker.java,v 1.24 2007/04/01 18:49:34 taqua Exp $
027 * ------------
028 * (C) Copyright 2000-2005, by Object Refinery Limited.
029 * (C) Copyright 2005-2007, by Pentaho Corporation.
030 */
031
032 package org.jfree.report.util;
033
034 /**
035 * A simple worker implementation. The worker executes a assigned workload and then sleeps
036 * until another workload is set or the worker is killed.
037 *
038 * @author Thomas Morgner
039 */
040 public final class Worker extends Thread
041 {
042 /**
043 * the worker's task.
044 */
045 private Runnable workload;
046
047 /**
048 * a flag whether the worker should exit after the processing.
049 */
050 private volatile boolean finish;
051
052 /**
053 * The worker pool, to which this worker is assigned. May be null.
054 */
055 private WorkerPool workerPool;
056
057 /**
058 * Creates a new worker.
059 *
060 * @param sleeptime the time this worker sleeps until he checks for new work.
061 */
062 public Worker ()
063 {
064 this.setDaemon(true);
065 start();
066 }
067
068 /**
069 * Set the next workload for this worker.
070 *
071 * @param r the next workload for the worker.
072 * @throws IllegalStateException if the worker is not idle.
073 */
074 public void setWorkload (final Runnable r)
075 {
076 if (workload != null)
077 {
078 throw new IllegalStateException("This worker is not idle.");
079 }
080 //Log.debug("Workload set...");
081 synchronized (this)
082 {
083 workload = r;
084 //Log.debug("Workload assigned: Notified " + getName());
085 this.notifyAll();
086 }
087 }
088
089 /**
090 * Returns the workload object.
091 *
092 * @return the runnable executed by this worker thread.
093 */
094 public synchronized Runnable getWorkload()
095 {
096 return workload;
097 }
098
099 /**
100 * Kills the worker after he completed his work. Awakens the worker if he's sleeping, so
101 * that the worker dies without delay.
102 */
103 public void finish ()
104 {
105 finish = true;
106 // we are evil ..
107 try
108 {
109 this.interrupt();
110 this.notifyAll();
111 }
112 catch (SecurityException se)
113 {
114 // ignored
115 }
116 if (workerPool != null)
117 {
118 workerPool.workerFinished(this);
119 }
120 }
121
122 /**
123 * Checks, whether this worker has some work to do.
124 *
125 * @return true, if this worker has no more work and is currently sleeping.
126 */
127 public boolean isAvailable ()
128 {
129 return (workload == null);
130 }
131
132 /**
133 * If a workload is set, process it. After the workload is processed, this worker starts
134 * to sleep until a new workload is set for the worker or the worker got the finish()
135 * request.
136 */
137 public synchronized void run ()
138 {
139 while (!finish)
140 {
141 if (workload != null)
142 {
143 try
144 {
145 workload.run();
146 }
147 catch (Exception e)
148 {
149 org.jfree.util.Log.error("Worker caught exception on run: ", e);
150 }
151 workload = null;
152 if (workerPool != null)
153 {
154 workerPool.workerAvailable(this);
155 }
156 }
157
158 synchronized (this)
159 {
160 try
161 {
162 this.wait();
163 }
164 catch (InterruptedException ie)
165 {
166 // ignored
167 }
168 }
169 }
170 }
171
172 /**
173 * Checks whether this worker has received the signal to finish and die.
174 *
175 * @return true, if the worker should finish the work and end the thread.
176 */
177 public boolean isFinish ()
178 {
179 return finish;
180 }
181
182 /**
183 * Returns the worker's assigned pool.
184 *
185 * @return the worker pool (or null, if the worker is not assigned to a pool).
186 */
187 public WorkerPool getWorkerPool ()
188 {
189 return workerPool;
190 }
191
192 /**
193 * Defines the worker's assigned pool.
194 *
195 * @param workerPool the worker pool (or null, if the worker is not assigned to a
196 * pool).
197 */
198 public void setWorkerPool (final WorkerPool workerPool)
199 {
200 this.workerPool = workerPool;
201 }
202 }