001/* 002 * $Id: Terminator.java 4543 2013-07-30 12:24:09Z kredel $ 003 */ 004 005package edu.jas.util; 006 007 008import java.util.concurrent.Semaphore; 009 010import 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 020public 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; 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 idler = 0; 047 logger.info("constructor, workers = " + workers); 048 } 049 050 051 /** 052 * to string 053 */ 054 @Override 055 public String toString() { 056 return "Terminator(" + done + ",workers=" + workers + ",idler=" + idler + ")"; 057 } 058 059 060 /** 061 * beIdle. 062 * Checks for release(). 063 */ 064 public synchronized void beIdle() { 065 idler++; 066 logger.info("beIdle, idler = " + idler); 067 if (idler >= workers) { 068 done = true; 069 fin.release(); //fin.V(); 070 } 071 } 072 073 074 /** 075 * initIdle. 076 * No check for release(). 077 * @param i number of idle threads. 078 */ 079 public synchronized void initIdle(int i) { 080 idler += i; 081 logger.info("initIdle, idler = " + idler); 082 if ( idler > workers ) { 083 if (done) { 084 idler = workers; 085 } else { 086 throw new RuntimeException("idler > workers"); 087 } 088 } 089 } 090 091 092 /** 093 * beIdle. 094 * Checks for release(). 095 * @param i number of idle threads. 096 */ 097 public synchronized void beIdle(int i) { 098 idler += i; 099 logger.info("beIdle, idler = " + idler); 100 if (idler >= workers) { 101 done = true; 102 fin.release(); //fin.V(); 103 } 104 } 105 106 107 /** 108 * allIdle. 109 * Checks for release(). 110 */ 111 public synchronized void allIdle() { 112 idler = workers; 113 logger.info("allIdle"); 114 done = true; 115 fin.release(); //fin.V(); 116 } 117 118 119 /** 120 * notIdle. 121 */ 122 public synchronized void notIdle() { 123 idler--; 124 logger.info("notIdle, idler = " + idler); 125 if ( idler < 0 ) { 126 throw new RuntimeException("idler < 0"); 127 } 128 } 129 130 131 /** 132 * getJobs. 133 * @return number of possible jobs. 134 */ 135 public synchronized int getJobs() { 136 return (workers - idler); 137 } 138 139 140 /** 141 * hasJobs. 142 * @return true, if there are possibly jobs, else false. 143 */ 144 public synchronized boolean hasJobs() { 145 return (idler < workers); 146 } 147 148 149 /** 150 * Release if possible. 151 */ 152 public synchronized void release() { 153 logger.info("release = " + this); 154 if ( idler >= workers ) { 155 done = true; 156 fin.release(); 157 } 158 //logger.info("release, idler = " + idler); 159 } 160 161 162 /** 163 * Wait until released. 164 */ 165 public void waitDone() { 166 try { 167 fin.acquire(); 168 } catch (InterruptedException e) { 169 Thread.currentThread().interrupt(); 170 } 171 logger.info("waitDone " + this); 172 } 173 174}