1 17 18 package org.logicalcobwebs.concurrent; 19 20 34 35 public class WriterPreferenceReadWriteLock implements ReadWriteLock { 36 37 protected long activeReaders_ = 0; 38 protected Thread activeWriter_ = null; 39 protected long waitingReaders_ = 0; 40 protected long waitingWriters_ = 0; 41 42 43 protected final ReaderLock readerLock_ = new ReaderLock(); 44 protected final WriterLock writerLock_ = new WriterLock(); 45 46 public Sync writeLock() { 47 return writerLock_; 48 } 49 50 public Sync readLock() { 51 return readerLock_; 52 } 53 54 59 60 61 protected synchronized void cancelledWaitingReader() { 62 --waitingReaders_; 63 } 64 65 protected synchronized void cancelledWaitingWriter() { 66 --waitingWriters_; 67 } 68 69 70 71 protected boolean allowReader() { 72 return activeWriter_ == null && waitingWriters_ == 0; 73 } 74 75 76 protected synchronized boolean startRead() { 77 boolean allowRead = allowReader(); 78 if (allowRead) ++activeReaders_; 79 return allowRead; 80 } 81 82 protected synchronized boolean startWrite() { 83 84 87 boolean allowWrite = (activeWriter_ == null && activeReaders_ == 0); 88 if (allowWrite) activeWriter_ = Thread.currentThread(); 89 return allowWrite; 90 } 91 92 93 99 100 protected synchronized boolean startReadFromNewReader() { 101 boolean pass = startRead(); 102 if (!pass) ++waitingReaders_; 103 return pass; 104 } 105 106 protected synchronized boolean startWriteFromNewWriter() { 107 boolean pass = startWrite(); 108 if (!pass) ++waitingWriters_; 109 return pass; 110 } 111 112 protected synchronized boolean startReadFromWaitingReader() { 113 boolean pass = startRead(); 114 if (pass) --waitingReaders_; 115 return pass; 116 } 117 118 protected synchronized boolean startWriteFromWaitingWriter() { 119 boolean pass = startWrite(); 120 if (pass) --waitingWriters_; 121 return pass; 122 } 123 124 128 protected synchronized Signaller endRead() { 129 if (--activeReaders_ == 0 && waitingWriters_ > 0) 130 return writerLock_; 131 else 132 return null; 133 } 134 135 136 140 protected synchronized Signaller endWrite() { 141 activeWriter_ = null; 142 if (waitingReaders_ > 0 && allowReader()) 143 return readerLock_; 144 else if (waitingWriters_ > 0) 145 return writerLock_; 146 else 147 return null; 148 } 149 150 151 159 160 protected abstract class Signaller { abstract void signalWaiters(); 162 } 163 164 protected class ReaderLock extends Signaller implements Sync { 165 166 public void acquire() throws InterruptedException { 167 if (Thread.interrupted()) throw new InterruptedException (); 168 InterruptedException ie = null; 169 synchronized (this) { 170 if (!startReadFromNewReader()) { 171 for (; ;) { 172 try { 173 ReaderLock.this.wait(); 174 if (startReadFromWaitingReader()) 175 return; 176 } catch (InterruptedException ex) { 177 cancelledWaitingReader(); 178 ie = ex; 179 break; 180 } 181 } 182 } 183 } 184 if (ie != null) { 185 writerLock_.signalWaiters(); 189 throw ie; 190 } 191 } 192 193 194 public void release() { 195 Signaller s = endRead(); 196 if (s != null) s.signalWaiters(); 197 } 198 199 200 synchronized void signalWaiters() { 201 ReaderLock.this.notifyAll(); 202 } 203 204 public boolean attempt(long msecs) throws InterruptedException { 205 if (Thread.interrupted()) throw new InterruptedException (); 206 InterruptedException ie = null; 207 synchronized (this) { 208 if (msecs <= 0) 209 return startRead(); 210 else if (startReadFromNewReader()) 211 return true; 212 else { 213 long waitTime = msecs; 214 long start = System.currentTimeMillis(); 215 for (; ;) { 216 try { 217 ReaderLock.this.wait(waitTime); 218 } catch (InterruptedException ex) { 219 cancelledWaitingReader(); 220 ie = ex; 221 break; 222 } 223 if (startReadFromWaitingReader()) 224 return true; 225 else { 226 waitTime = msecs - (System.currentTimeMillis() - start); 227 if (waitTime <= 0) { 228 cancelledWaitingReader(); 229 break; 230 } 231 } 232 } 233 } 234 } 235 writerLock_.signalWaiters(); 237 if (ie != null) 238 throw ie; 239 else 240 return false; } 242 243 } 244 245 protected class WriterLock extends Signaller implements Sync { 246 247 public void acquire() throws InterruptedException { 248 if (Thread.interrupted()) throw new InterruptedException (); 249 InterruptedException ie = null; 250 synchronized (this) { 251 if (!startWriteFromNewWriter()) { 252 for (; ;) { 253 try { 254 WriterLock.this.wait(); 255 if (startWriteFromWaitingWriter()) 256 return; 257 } catch (InterruptedException ex) { 258 cancelledWaitingWriter(); 259 WriterLock.this.notify(); 260 ie = ex; 261 break; 262 } 263 } 264 } 265 } 266 if (ie != null) { 267 readerLock_.signalWaiters(); 271 throw ie; 272 } 273 } 274 275 public void release() { 276 Signaller s = endWrite(); 277 if (s != null) s.signalWaiters(); 278 } 279 280 synchronized void signalWaiters() { 281 WriterLock.this.notify(); 282 } 283 284 public boolean attempt(long msecs) throws InterruptedException { 285 if (Thread.interrupted()) throw new InterruptedException (); 286 InterruptedException ie = null; 287 synchronized (this) { 288 if (msecs <= 0) 289 return startWrite(); 290 else if (startWriteFromNewWriter()) 291 return true; 292 else { 293 long waitTime = msecs; 294 long start = System.currentTimeMillis(); 295 for (; ;) { 296 try { 297 WriterLock.this.wait(waitTime); 298 } catch (InterruptedException ex) { 299 cancelledWaitingWriter(); 300 WriterLock.this.notify(); 301 ie = ex; 302 break; 303 } 304 if (startWriteFromWaitingWriter()) 305 return true; 306 else { 307 waitTime = msecs - (System.currentTimeMillis() - start); 308 if (waitTime <= 0) { 309 cancelledWaitingWriter(); 310 WriterLock.this.notify(); 311 break; 312 } 313 } 314 } 315 } 316 } 317 318 readerLock_.signalWaiters(); 319 if (ie != null) 320 throw ie; 321 else 322 return false; } 324 325 } 326 327 328 } 329 330 | Popular Tags |