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 2725 2007-04-01 18:49:29Z taqua $
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    }