1 22 package org.jboss.util; 23 24 import java.util.Iterator ; 25 import java.util.Map ; 26 import java.util.HashMap ; 27 import java.util.LinkedList ; 28 import java.io.StringWriter ; 29 import java.io.PrintWriter ; 30 31 39 public class Semaphore 40 implements Sync 41 { 42 private static final long DEADLOCK_TIMEOUT = 5*60*1000; 44 45 private final static boolean m_debug = false; 47 private int m_users; 48 private int m_allowed; 49 private Map m_logMap; 50 51 53 public Semaphore(int allowed) 55 { 56 if (allowed < 1) throw new IllegalArgumentException (); 57 58 m_users = 0; 59 m_allowed = allowed; 60 m_logMap = new HashMap (); 61 } 62 63 public int getUsers() 65 { 66 synchronized (this) 67 { 68 return m_users; 69 } 70 } 71 72 public void acquire() throws InterruptedException 74 { 75 synchronized (this) 76 { 77 logAcquire(); 78 79 ++m_users; 81 boolean waitSuccessful = false; 82 while (m_allowed <= 0) 83 { 84 waitSuccessful = waitImpl(this); 85 if (!waitSuccessful) 86 { 87 --m_users; 90 ++m_allowed; 91 } 92 } 93 --m_allowed; 94 } 95 } 96 97 public void release() 98 { 99 synchronized (this) 100 { 101 logRelease(); 102 103 --m_users; 104 ++m_allowed; 105 notify(); 106 } 107 } 108 109 public String toString() 111 { 112 return super.toString() + " - " + m_users; 113 } 114 115 117 protected boolean waitImpl(Object lock) throws InterruptedException 119 { 120 long start = System.currentTimeMillis(); 123 lock.wait(DEADLOCK_TIMEOUT); 124 long end = System.currentTimeMillis(); 125 126 if ((end - start) > (DEADLOCK_TIMEOUT - 1000)) 127 { 128 logDeadlock(); 129 return false; 130 } 131 return true; 132 } 133 134 protected void logAcquire() 135 { 136 if (m_debug) 137 { 138 Thread thread = Thread.currentThread(); 140 141 StringWriter sw = new StringWriter (); 143 new Exception ().printStackTrace(new PrintWriter (sw)); 144 String trace = sw.toString(); 145 146 LinkedList list = (LinkedList )m_logMap.get(thread); 147 if (list != null) 148 { 149 Info prevInfo = (Info)list.getLast(); 152 Info info = new Info(thread, m_users, trace); 153 list.add(info); 154 } 155 else 156 { 157 list = new LinkedList (); 159 Info info = new Info(thread, m_users, trace); 160 list.add(info); 161 m_logMap.put(thread, list); 163 } 164 } 165 } 166 protected void logDeadlock() 167 { 168 System.err.println(); 169 System.err.println("DEADLOCK ON SEMAPHORE " + this); 170 if (m_debug) 171 { 172 for (Iterator i = m_logMap.values().iterator(); i.hasNext();) 173 { 174 LinkedList list = (LinkedList )i.next(); 175 for (Iterator iter = list.iterator(); iter.hasNext();) 176 { 177 System.err.println(iter.next()); 178 } 179 } 180 } 181 System.err.println(); 182 } 183 protected void logRelease() 184 { 185 if (m_debug) 186 { 187 Thread thread = Thread.currentThread(); 189 190 LinkedList list = (LinkedList )m_logMap.get(thread); 191 if (list != null) 192 { 193 Info info = new Info(thread, 0, ""); 194 if (!list.remove(info)) 195 { 196 System.err.println("LOG INFO SIZE: " + list); 197 new IllegalStateException ("BUG: semaphore log list does not contain required info").printStackTrace(); 198 } 199 200 int size = list.size(); 202 if (size < 1) 203 { 204 m_logMap.remove(thread); 205 } 206 } 207 else 208 { 209 throw new IllegalStateException ("Semaphore log failed: release called without acquire"); 210 } 211 } 212 } 213 214 216 private class Info 218 { 219 private Info(Thread t, int i, String s) 220 { 221 m_thread = t; 222 m_counter = i; 223 m_trace = s; 224 } 225 private Thread m_thread; 226 private int m_counter; 227 private String m_trace; 228 public boolean equals(Object o) 229 { 230 Info other = (Info)o; 231 return m_thread == other.m_thread; 232 } 233 public String toString() 234 { 235 return m_thread + " - " + m_counter + "\n" + m_trace; 236 } 237 } 238 } 239 | Popular Tags |