Source for org.jfree.report.util.WorkerPool

   1: /**
   2:  * ========================================
   3:  * JFreeReport : a free Java report library
   4:  * ========================================
   5:  *
   6:  * Project Info:  http://reporting.pentaho.org/
   7:  *
   8:  * (C) Copyright 2000-2007, by Object Refinery Limited, Pentaho Corporation and Contributors.
   9:  *
  10:  * This library is free software; you can redistribute it and/or modify it under the terms
  11:  * of the GNU Lesser General Public License as published by the Free Software Foundation;
  12:  * either version 2.1 of the License, or (at your option) any later version.
  13:  *
  14:  * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
  15:  * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  16:  * See the GNU Lesser General Public License for more details.
  17:  *
  18:  * You should have received a copy of the GNU Lesser General Public License along with this
  19:  * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  20:  * Boston, MA 02111-1307, USA.
  21:  *
  22:  * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
  23:  * in the United States and other countries.]
  24:  *
  25:  * ------------
  26:  * $Id: WorkerPool.java 3525 2007-10-16 11:43:48Z tmorgner $
  27:  * ------------
  28:  * (C) Copyright 2000-2005, by Object Refinery Limited.
  29:  * (C) Copyright 2005-2007, by Pentaho Corporation.
  30:  */
  31: 
  32: package org.jfree.report.util;
  33: 
  34: /**
  35:  * A simple static workpool. Worker threads are created when necessary.
  36:  *
  37:  * @author Thomas Morgner
  38:  */
  39: public class WorkerPool
  40: {
  41:   /**
  42:    * The worker array.
  43:    */
  44:   private Worker[] workers;
  45:   /**
  46:    * A flag indicating whether idle workers are available.
  47:    */
  48:   private boolean workersAvailable;
  49:   /**
  50:    * the name prefix for all workers of this pool.
  51:    */
  52:   private String namePrefix;
  53: 
  54:   /**
  55:    * Creates a new worker pool with the default size of 10 workers and the default name.
  56:    */
  57:   public WorkerPool ()
  58:   {
  59:     this(10);
  60:   }
  61: 
  62:   /**
  63:    * Creates a new workerpool with the given number of workers and the default name.
  64:    *
  65:    * @param size the maximum number of workers available.
  66:    */
  67:   public WorkerPool (final int size)
  68:   {
  69:     this(size, "WorkerPool-worker");
  70:   }
  71: 
  72:   /**
  73:    * Creates a new worker pool for the given number of workers and with the given name
  74:    * prefix.
  75:    *
  76:    * @param size       the size of the worker pool.
  77:    * @param namePrefix the name prefix for all created workers.
  78:    */
  79:   public WorkerPool (final int size, final String namePrefix)
  80:   {
  81:     if (size <= 0)
  82:     {
  83:       throw new IllegalArgumentException("Size must be > 0");
  84:     }
  85:     workers = new Worker[size];
  86:     workersAvailable = true;
  87:     this.namePrefix = namePrefix;
  88:   }
  89: 
  90:   /**
  91:    * Checks, whether workers are available.
  92:    *
  93:    * @return true, if at least one worker is idle, false otherwise.
  94:    */
  95:   public synchronized boolean isWorkerAvailable ()
  96:   {
  97:     return workersAvailable;
  98:   }
  99: 
 100:   /**
 101:    * Updates the workersAvailable flag after a worker was assigned.
 102:    */
 103:   private void updateWorkersAvailable ()
 104:   {
 105:     for (int i = 0; i < workers.length; i++)
 106:     {
 107:       if (workers[i] == null)
 108:       {
 109:         workersAvailable = true;
 110:         return;
 111:       }
 112:       if (workers[i].isAvailable() == true)
 113:       {
 114:         workersAvailable = true;
 115:         return;
 116:       }
 117:     }
 118:     workersAvailable = false;
 119:   }
 120: 
 121:   /**
 122:    * Waits until a worker will be available.
 123:    */
 124:   private synchronized void waitForWorkerAvailable ()
 125:   {
 126:     while (isWorkerAvailable() == false)
 127:     {
 128:       try
 129:       {
 130:         // remove lock
 131:         this.wait(5000);
 132:       }
 133:       catch (InterruptedException ie)
 134:       {
 135:         // ignored
 136:       }
 137:     }
 138:   }
 139: 
 140:   /**
 141:    * Returns a workerhandle for the given workload. This method will wait until an idle
 142:    * worker is found.
 143:    *
 144:    * @param r the workload for the worker
 145:    * @return a handle to the worker.
 146:    */
 147:   public synchronized WorkerHandle getWorkerForWorkload (final Runnable r)
 148:   {
 149:     waitForWorkerAvailable();
 150: 
 151:     int emptySlot = -1;
 152:     for (int i = 0; i < workers.length; i++)
 153:     {
 154:       if (workers[i] == null)
 155:       {
 156:         // in the first run, try to avoid to create new threads...
 157:         // reuse the already available threads
 158:         if (emptySlot == -1)
 159:         {
 160:           emptySlot = i;
 161:         }
 162:         continue;
 163:       }
 164:       if (workers[i].isAvailable() == true)
 165:       {
 166:         workers[i].setWorkload(r);
 167:         updateWorkersAvailable();
 168:         return new WorkerHandle(workers[i]);
 169:       }
 170:     }
 171:     if (emptySlot != -1)
 172:     {
 173:       workers[emptySlot] = new Worker();
 174:       workers[emptySlot].setName(namePrefix + "-" + emptySlot);
 175:       workers[emptySlot].setWorkerPool(this);
 176:       workers[emptySlot].setWorkload(r);
 177:       updateWorkersAvailable();
 178:       return new WorkerHandle(workers[emptySlot]);
 179:     }
 180:     throw new IllegalStateException
 181:             ("At this point, a worker should already have been assigned.");
 182:   }
 183: 
 184:   /**
 185:    * Marks the given worker as finished. The worker will be removed from the list of the
 186:    * available workers.
 187:    *
 188:    * @param worker the worker which was finished.
 189:    */
 190:   public void workerFinished (final Worker worker)
 191:   {
 192:     if (worker.isFinish() == false)
 193:     {
 194:       throw new IllegalArgumentException("This worker is not in the finish state.");
 195:     }
 196:     for (int i = 0; i < workers.length; i++)
 197:     {
 198:       if (workers[i] == worker)
 199:       {
 200:         synchronized (this)
 201:         {
 202:           workers[i] = null;
 203:           workersAvailable = true;
 204:           this.notifyAll();
 205:         }
 206:         return;
 207:       }
 208:     }
 209:   }
 210: 
 211:   /**
 212:    * Marks the given worker as available.
 213:    *
 214:    * @param worker the worker which was available.
 215:    */
 216:   public synchronized void workerAvailable (final Worker worker)
 217:   {
 218:     for (int i = 0; i < workers.length; i++)
 219:     {
 220:       if (workers[i] == worker)
 221:       {
 222:         synchronized (this)
 223:         {
 224:           workersAvailable = true;
 225:           this.notifyAll();
 226:         }
 227:         return;
 228:       }
 229:     }
 230:   }
 231: 
 232:   /**
 233:    * Finishes all worker of this pool.
 234:    */
 235:   public void finishAll ()
 236:   {
 237:     for (int i = 0; i < workers.length; i++)
 238:     {
 239:       if (workers[i] != null)
 240:       {
 241:         workers[i].finish();
 242:       }
 243:     }
 244:   }
 245: }