30e490f9565b5bc4e9e73a327a55fe9520361ffb
[org.ibex.util.git] / src / org / ibex / util / ThreadPool.java
1 // Copyright 2000-2005 the Contributors, as shown in the revision logs.
2 // Licensed under the Apache Public Source License 2.0 ("the License").
3 // You may not use this file except in compliance with the License.
4
5 package org.ibex.util;
6
7 import java.io.*;
8
9 /** A simple thread pool. */
10 public final class ThreadPool {
11
12     private final Queue tasks;
13     private final Queue idle;
14     private final int   minThreads;
15     private final int   maxThreads;
16     private       int   numThreads;
17
18     public ThreadPool(int min, int max) {
19         this.minThreads  = min;
20         this.maxThreads  = max;
21         this.idle    = new Queue(Math.min(min, 100));
22         this.tasks   = new Queue(Math.min(max, 100));
23     }
24
25     public synchronized void appendTask(Runnable r) {
26         if (idle.size() > 0)              ((PooledThread)idle.remove()).setTask(r);
27         else if (numThreads < maxThreads) new PooledThread(r);
28         else                              tasks.append(r);
29     }
30
31     public synchronized void prependTask(Runnable r) {
32         if (idle.size() > 0)              ((PooledThread)idle.remove()).setTask(r);
33         else if (numThreads < maxThreads) new PooledThread(r);
34         else                              tasks.prepend(r);
35     }
36
37     private class PooledThread extends Thread {
38         private Runnable task = null;
39         private boolean die = false;
40         public PooledThread(Runnable r) {
41             numThreads++;
42             if (r!=null) setTask(r);
43             start();
44         }
45         public synchronized boolean isRunning() { return task != null; }
46         public synchronized boolean setTask(Runnable r) {
47             if (task != null) throw new Error("setTask() on a thread that is alread busy!");
48             task = r;
49             notifyAll();
50             return true;
51         }
52         private synchronized void recycle() {
53             task = null;
54             // depends on the fact that our Queue class is synchronized
55             if (tasks.size() > 0)                       task = (Runnable)tasks.remove();
56             if (task==null && idle.size() < minThreads) idle.append(this);
57             else if (task==null)                        die = true;
58         }
59         public void run() {
60             try {
61                 while (!die) {
62                     try {
63                         synchronized(this) { while (task==null) wait(); }
64                         task.run();
65                     } catch (Exception e) { Log.error(this, e); }
66                     recycle();
67                 }
68             } finally {
69                 numThreads--;
70             }
71         }
72     }
73
74 }
75