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: WorkerPool.java 3525 2007-10-16 11:43:48Z tmorgner $
027: * ------------
028: * (C) Copyright 2000-2005, by Object Refinery Limited.
029: * (C) Copyright 2005-2007, by Pentaho Corporation.
030: */package org.jfree.report.util;
031:
032: /**
033: * A simple static workpool. Worker threads are created when necessary.
034: *
035: * @author Thomas Morgner
036: */
037: public class WorkerPool {
038: /**
039: * The worker array.
040: */
041: private Worker[] workers;
042: /**
043: * A flag indicating whether idle workers are available.
044: */
045: private boolean workersAvailable;
046: /**
047: * the name prefix for all workers of this pool.
048: */
049: private String namePrefix;
050:
051: /**
052: * Creates a new worker pool with the default size of 10 workers and the default name.
053: */
054: public WorkerPool() {
055: this (10);
056: }
057:
058: /**
059: * Creates a new workerpool with the given number of workers and the default name.
060: *
061: * @param size the maximum number of workers available.
062: */
063: public WorkerPool(final int size) {
064: this (size, "WorkerPool-worker");
065: }
066:
067: /**
068: * Creates a new worker pool for the given number of workers and with the given name
069: * prefix.
070: *
071: * @param size the size of the worker pool.
072: * @param namePrefix the name prefix for all created workers.
073: */
074: public WorkerPool(final int size, final String namePrefix) {
075: if (size <= 0) {
076: throw new IllegalArgumentException("Size must be > 0");
077: }
078: workers = new Worker[size];
079: workersAvailable = true;
080: this .namePrefix = namePrefix;
081: }
082:
083: /**
084: * Checks, whether workers are available.
085: *
086: * @return true, if at least one worker is idle, false otherwise.
087: */
088: public synchronized boolean isWorkerAvailable() {
089: return workersAvailable;
090: }
091:
092: /**
093: * Updates the workersAvailable flag after a worker was assigned.
094: */
095: private void updateWorkersAvailable() {
096: for (int i = 0; i < workers.length; i++) {
097: if (workers[i] == null) {
098: workersAvailable = true;
099: return;
100: }
101: if (workers[i].isAvailable() == true) {
102: workersAvailable = true;
103: return;
104: }
105: }
106: workersAvailable = false;
107: }
108:
109: /**
110: * Waits until a worker will be available.
111: */
112: private synchronized void waitForWorkerAvailable() {
113: while (isWorkerAvailable() == false) {
114: try {
115: // remove lock
116: this .wait(5000);
117: } catch (InterruptedException ie) {
118: // ignored
119: }
120: }
121: }
122:
123: /**
124: * Returns a workerhandle for the given workload. This method will wait until an idle
125: * worker is found.
126: *
127: * @param r the workload for the worker
128: * @return a handle to the worker.
129: */
130: public synchronized WorkerHandle getWorkerForWorkload(
131: final Runnable r) {
132: waitForWorkerAvailable();
133:
134: int emptySlot = -1;
135: for (int i = 0; i < workers.length; i++) {
136: if (workers[i] == null) {
137: // in the first run, try to avoid to create new threads...
138: // reuse the already available threads
139: if (emptySlot == -1) {
140: emptySlot = i;
141: }
142: continue;
143: }
144: if (workers[i].isAvailable() == true) {
145: workers[i].setWorkload(r);
146: updateWorkersAvailable();
147: return new WorkerHandle(workers[i]);
148: }
149: }
150: if (emptySlot != -1) {
151: workers[emptySlot] = new Worker();
152: workers[emptySlot].setName(namePrefix + "-" + emptySlot);
153: workers[emptySlot].setWorkerPool(this );
154: workers[emptySlot].setWorkload(r);
155: updateWorkersAvailable();
156: return new WorkerHandle(workers[emptySlot]);
157: }
158: throw new IllegalStateException(
159: "At this point, a worker should already have been assigned.");
160: }
161:
162: /**
163: * Marks the given worker as finished. The worker will be removed from the list of the
164: * available workers.
165: *
166: * @param worker the worker which was finished.
167: */
168: public void workerFinished(final Worker worker) {
169: if (worker.isFinish() == false) {
170: throw new IllegalArgumentException(
171: "This worker is not in the finish state.");
172: }
173: for (int i = 0; i < workers.length; i++) {
174: if (workers[i] == worker) {
175: synchronized (this ) {
176: workers[i] = null;
177: workersAvailable = true;
178: this .notifyAll();
179: }
180: return;
181: }
182: }
183: }
184:
185: /**
186: * Marks the given worker as available.
187: *
188: * @param worker the worker which was available.
189: */
190: public synchronized void workerAvailable(final Worker worker) {
191: for (int i = 0; i < workers.length; i++) {
192: if (workers[i] == worker) {
193: synchronized (this ) {
194: workersAvailable = true;
195: this .notifyAll();
196: }
197: return;
198: }
199: }
200: }
201:
202: /**
203: * Finishes all worker of this pool.
204: */
205: public void finishAll() {
206: for (int i = 0; i < workers.length; i++) {
207: if (workers[i] != null) {
208: workers[i].finish();
209: }
210: }
211: }
212: }
|