1 30 31 package com.nightlabs.util; 32 33 import java.util.HashMap ; 34 import java.util.Iterator ; 35 36 import org.apache.log4j.Level; 37 import org.apache.log4j.Logger; 38 39 50 51 public class RWLockMan 52 { 53 public static Logger LOGGER = Logger.getLogger(RWLockMan.class.getName()); 54 55 private static RWLockMan rwLockMan; 56 public static synchronized RWLockMan getRWLockMan() 57 { 58 if (rwLockMan == null) 59 rwLockMan = new RWLockMan(); 60 return rwLockMan; 61 } 62 63 protected RWLockMan() 64 { 65 } 66 67 private Object mutex = new Object (); 68 69 private static class ThreadCounter 70 { 71 private Thread thread; 72 public Thread getThread() { return thread; } 73 74 public int threadCount = 0; 75 76 public ThreadCounter(Thread _thread) 77 { 78 this.thread = _thread; 79 } 80 } 81 82 private static class RWLockCounter 83 { 84 private RWLock rwLock; 85 public RWLock getRWLock() { return rwLock; } 86 87 public int rwLockCountRead = 0; 88 public int rwLockCountWrite = 0; 89 90 public RWLockCounter(RWLock _rwLock) 91 { 92 this.rwLock = _rwLock; 93 } 94 95 public String toString() 96 { 97 StringBuffer sb = new StringBuffer (); 98 sb.append("RWLockCounter{"); 99 sb.append(rwLock.toString()); 100 sb.append(",reads="); 101 sb.append(rwLockCountRead); 102 sb.append(",writes="); 103 sb.append(rwLockCountWrite); 104 sb.append('}'); 105 return sb.toString(); 106 } 107 108 118 } 119 120 124 private HashMap heldLocksToThreadsMap = new HashMap (); 125 126 127 131 private HashMap threadsToHeldLocksMap = new HashMap (); 132 133 134 138 private HashMap waitingThreadsToLocksMap = new HashMap (); 139 140 public static final byte MODE_READ = 120; 141 public static final byte MODE_WRITE = 121; 142 143 public static String modeToString(byte mode) 144 { 145 if (mode == MODE_READ) 146 return "MODE_READ"; 147 else if (mode == MODE_WRITE) 148 return "MODE_WRITE"; 149 else 150 throw new IllegalArgumentException ("unknown mode: "+mode); 151 } 152 153 154 public void beginWaitForLock(RWLock rwLock, byte mode) 155 throws DeadLockException 156 { 157 try { 158 if (mode != MODE_READ && mode != MODE_WRITE) 159 throw new IllegalArgumentException ("unknown mode!"); 160 161 Thread currentThread = Thread.currentThread(); 162 163 synchronized (mutex) { 164 165 167 HashMap ourHeldLocks = (HashMap )threadsToHeldLocksMap.get(currentThread); 169 170 HashMap threads = (HashMap )heldLocksToThreadsMap.get(rwLock); 173 if (threads != null) { 174 175 for (Iterator itThreads = threads.keySet().iterator(); itThreads.hasNext(); ) { 179 Thread thread = (Thread ) itThreads.next(); 180 181 if (thread != currentThread) { 182 183 HashMap waitingForRWLocks = (HashMap )waitingThreadsToLocksMap.get(thread); 185 if (waitingForRWLocks != null) { 186 187 if (ourHeldLocks != null) { 189 for (Iterator itLocks = waitingForRWLocks.values().iterator(); itLocks.hasNext(); ) { 191 RWLockCounter rwLockCounter = (RWLockCounter) itLocks.next(); 192 193 194 RWLockCounter ourHeldLockCounter = (RWLockCounter)ourHeldLocks.get(rwLockCounter.getRWLock()); 195 196 if (ourHeldLockCounter != null) { 197 201 if ( 204 ourHeldLockCounter.rwLockCountWrite > 0 || 205 rwLockCounter.rwLockCountWrite > 0 206 ) 207 throw new DeadLockException(currentThread+": We are about to wait for lock "+rwLock+"("+modeToString(mode)+") which is held by thread "+thread+". This thread is waiting for lock "+rwLockCounter+" which is held by us: "+ourHeldLockCounter); 208 209 } 211 212 } } 215 } 217 } 219 } } 222 224 225 227 HashMap waitingForRWLocks = (HashMap )waitingThreadsToLocksMap.get(currentThread); 228 if (waitingForRWLocks == null) { 229 waitingForRWLocks = new HashMap (); 230 waitingThreadsToLocksMap.put(currentThread, waitingForRWLocks); 231 } 232 233 RWLockCounter rwLockCounter = (RWLockCounter)waitingForRWLocks.get(rwLock); 234 if (rwLockCounter == null) { 235 rwLockCounter = new RWLockCounter(rwLock); 236 waitingForRWLocks.put(rwLock, rwLockCounter); 237 } 239 if (mode == MODE_READ) 240 rwLockCounter.rwLockCountRead++; 241 else 242 rwLockCounter.rwLockCountWrite++; 243 244 246 } 248 } catch (RuntimeException x) { 249 LOGGER.log(Level.FATAL, "Exception in thread "+Thread.currentThread(), x); 250 throw x; 251 } catch (Throwable t) { 252 LOGGER.log(Level.FATAL, "Exception in thread "+Thread.currentThread(), t); 253 throw new RuntimeException (t); 254 } 255 } 256 257 public void endWaitForLock(RWLock rwLock, byte mode) 258 { 259 try { 260 if (mode != MODE_READ && mode != MODE_WRITE) 261 throw new IllegalArgumentException ("unknown mode!"); 262 263 Thread currentThread = Thread.currentThread(); 264 265 synchronized (mutex) { 266 267 HashMap waitingForRWLocks = (HashMap )waitingThreadsToLocksMap.get(currentThread); 268 if (waitingForRWLocks == null) 269 throw new IllegalStateException (currentThread+": No waiting locks registered for this thread! Unable to end wait for lock: "+rwLock); 270 271 RWLockCounter rwLockCounter = (RWLockCounter)waitingForRWLocks.get(rwLock); 272 if (rwLockCounter == null) 273 throw new IllegalStateException (currentThread+": No waiting lockCounter registered for this thread! Unable to end wait for lock: "+rwLock); 274 275 276 if (mode == MODE_READ) 277 rwLockCounter.rwLockCountRead--; 278 else 279 rwLockCounter.rwLockCountWrite--; 280 281 282 if (rwLockCounter.rwLockCountRead == 0 && rwLockCounter.rwLockCountWrite == 0) { 283 286 waitingForRWLocks.remove(rwLock); 287 288 if (waitingForRWLocks.isEmpty()) 289 waitingThreadsToLocksMap.remove(currentThread); 290 291 } } 294 } catch (RuntimeException x) { 295 LOGGER.log(Level.FATAL, "Exception in thread "+Thread.currentThread(), x); 296 throw x; 297 } catch (Throwable t) { 298 LOGGER.log(Level.FATAL, "Exception in thread "+Thread.currentThread(), t); 299 throw new RuntimeException (t); 300 } 301 } 302 303 public void acquireLock(RWLock rwLock, byte mode, int count) 304 { 305 try { 306 if (mode != MODE_READ && mode != MODE_WRITE) 307 throw new IllegalArgumentException ("unknown mode!"); 308 309 Thread currentThread = Thread.currentThread(); 310 311 synchronized (mutex) { 312 HashMap threads = (HashMap )heldLocksToThreadsMap.get(rwLock); 313 if (threads == null) { 314 threads = new HashMap (); 315 heldLocksToThreadsMap.put(rwLock, threads); 316 } 317 318 ThreadCounter threadCounter = (ThreadCounter)threads.get(currentThread); 319 if (threadCounter == null) { 320 threadCounter = new ThreadCounter(currentThread); 321 threads.put(currentThread, threadCounter); 322 } 324 threadCounter.threadCount += count; 325 326 327 328 HashMap heldLocks = (HashMap )threadsToHeldLocksMap.get(currentThread); 329 if (heldLocks == null) { 330 heldLocks = new HashMap (); 331 threadsToHeldLocksMap.put(currentThread, heldLocks); 332 } 333 334 RWLockCounter rwLockCounter = (RWLockCounter)heldLocks.get(rwLock); 335 if (rwLockCounter == null) { 336 rwLockCounter = new RWLockCounter(rwLock); 337 heldLocks.put(rwLock, rwLockCounter); 338 } 340 if (mode == MODE_READ) 341 rwLockCounter.rwLockCountRead += count; 342 else 343 rwLockCounter.rwLockCountWrite += count; 344 345 } 347 } catch (RuntimeException x) { 348 LOGGER.log(Level.FATAL, "Exception in thread "+Thread.currentThread(), x); 349 throw x; 350 } catch (Throwable t) { 351 LOGGER.log(Level.FATAL, "Exception in thread "+Thread.currentThread(), t); 352 throw new RuntimeException (t); 353 } 354 } 355 356 public void releaseLock(RWLock rwLock, byte mode, int count) 357 { 358 try { 359 if (mode != MODE_READ && mode != MODE_WRITE) 360 throw new IllegalArgumentException ("unknown mode!"); 361 362 Thread currentThread = Thread.currentThread(); 363 364 synchronized (mutex) { 365 366 HashMap threads = (HashMap )heldLocksToThreadsMap.get(rwLock); 367 if (threads == null) 368 throw new IllegalStateException (currentThread+": No possessing threads registered for this lock! Unable to release lock: "+rwLock); 369 370 ThreadCounter threadCounter = (ThreadCounter)threads.get(currentThread); 371 if (threadCounter == null) 372 throw new IllegalStateException (currentThread+": No thread counter registered for this lock & current thread! Unable to release lock: "+rwLock); 373 374 375 376 377 HashMap heldLocks = (HashMap )threadsToHeldLocksMap.get(currentThread); 378 if (heldLocks == null) 379 throw new IllegalStateException (currentThread+": No held locks registered for this thread! Unable to release lock: "+rwLock); 380 381 RWLockCounter rwLockCounter = (RWLockCounter)heldLocks.get(rwLock); 382 if (rwLockCounter == null) 383 throw new IllegalStateException (currentThread+": No lock counter registered for this thread & lock! Unable to release lock: "+rwLock); 384 385 386 threadCounter.threadCount -= count; 387 388 if (mode == MODE_READ) 389 rwLockCounter.rwLockCountRead -= count; 390 else 391 rwLockCounter.rwLockCountWrite -= count; 392 393 395 if (threadCounter.threadCount == 0) { 396 397 threads.remove(currentThread); 398 399 if (threads.isEmpty()) 400 heldLocksToThreadsMap.get(rwLock); 401 402 } 404 if (rwLockCounter.rwLockCountRead == 0 && rwLockCounter.rwLockCountWrite == 0) { 405 406 heldLocks.remove(rwLock); 407 408 if (heldLocks.isEmpty()) 409 threadsToHeldLocksMap.remove(currentThread); 410 411 } 413 } 415 } catch (RuntimeException x) { 416 LOGGER.log(Level.FATAL, "Exception in thread "+Thread.currentThread(), x); 417 throw x; 418 } catch (Throwable t) { 419 LOGGER.log(Level.FATAL, "Exception in thread "+Thread.currentThread(), t); 420 throw new RuntimeException (t); 421 } 422 } 423 424 } | Popular Tags |