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 }