001 /*
002 * $Id: Terminator.java 3393 2010-12-09 21:46:03Z kredel $
003 */
004
005 package edu.jas.util;
006
007
008 import java.util.concurrent.Semaphore;
009
010 import org.apache.log4j.Logger;
011
012
013 //import edu.unima.ky.parallel.Semaphore;
014
015 /**
016 * Terminating helper class. Like a barrier, but with coming and going.
017 * @author Heinz Kredel
018 */
019
020 public class Terminator {
021
022
023 private static final Logger logger = Logger.getLogger(Terminator.class);
024
025
026 private final int workers;
027
028
029 private int idler = 0;
030
031
032 private final Semaphore fin;
033
034
035 private /*volatile*/ boolean done;
036
037
038 /**
039 * Terminator.
040 * @param workers number of expected threads.
041 */
042 public Terminator(int workers) {
043 this.workers = workers;
044 fin = new Semaphore(0);
045 done = false;
046 logger.info("constructor, workers = " + workers);
047 }
048
049
050 /**
051 * to string
052 */
053 @Override
054 public String toString() {
055 return "Terminator(" + done + ",workers=" + workers + ",idler=" + idler + ")";
056 }
057
058
059 /**
060 * beIdle.
061 * Checks for release().
062 */
063 public synchronized void beIdle() {
064 idler++;
065 logger.info("beIdle, idler = " + idler);
066 if (idler >= workers) {
067 done = true;
068 fin.release(); //fin.V();
069 }
070 }
071
072
073 /**
074 * initIdle.
075 * No check for release().
076 * @param i number of idle threads.
077 */
078 public synchronized void initIdle(int i) {
079 idler += i;
080 logger.info("initIdle, idler = " + idler);
081 if ( idler > workers ) {
082 if (done) {
083 idler = workers;
084 } else {
085 throw new RuntimeException("idler > workers");
086 }
087 }
088 }
089
090
091 /**
092 * beIdle.
093 * Checks for release().
094 * @param i number of idle threads.
095 */
096 public synchronized void beIdle(int i) {
097 idler += i;
098 logger.info("beIdle, idler = " + idler);
099 if (idler >= workers) {
100 done = true;
101 fin.release(); //fin.V();
102 }
103 }
104
105
106 /**
107 * allIdle.
108 * Checks for release().
109 */
110 public synchronized void allIdle() {
111 idler = workers;
112 logger.info("allIdle");
113 done = true;
114 fin.release(); //fin.V();
115 }
116
117
118 /**
119 * notIdle.
120 */
121 public synchronized void notIdle() {
122 idler--;
123 logger.info("notIdle, idler = " + idler);
124 if ( idler < 0 ) {
125 throw new RuntimeException("idler < 0");
126 }
127 }
128
129
130 /**
131 * getJobs.
132 * @return number of possible jobs.
133 */
134 public synchronized int getJobs() {
135 return (workers - idler);
136 }
137
138
139 /**
140 * hasJobs.
141 * @return true, if there are possibly jobs, else false.
142 */
143 public boolean hasJobs() {
144 return (idler < workers);
145 }
146
147
148 /**
149 * Release if possible.
150 */
151 public synchronized void release() {
152 logger.info("release = " + this);
153 if ( idler >= workers ) {
154 done = true;
155 fin.release();
156 }
157 //logger.info("release, idler = " + idler);
158 }
159
160
161 /**
162 * Wait until released.
163 */
164 public void waitDone() {
165 try {
166 fin.acquire();
167 } catch (InterruptedException e) {
168 Thread.currentThread().interrupt();
169 }
170 logger.info("waitDone " + this);
171 }
172
173 }