1 17 18 package EDU.oswego.cs.dl.util.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() { return writerLock_; } 47 public Sync readLock() { return readerLock_; } 48 49 54 55 56 protected synchronized void cancelledWaitingReader() { --waitingReaders_; } 57 protected synchronized void cancelledWaitingWriter() { --waitingWriters_; } 58 59 60 61 protected boolean allowReader() { 62 return activeWriter_ == null && waitingWriters_ == 0; 63 } 64 65 66 protected synchronized boolean startRead() { 67 boolean allowRead = allowReader(); 68 if (allowRead) ++activeReaders_; 69 return allowRead; 70 } 71 72 protected synchronized boolean startWrite() { 73 74 77 boolean allowWrite = (activeWriter_ == null && activeReaders_ == 0); 78 if (allowWrite) activeWriter_ = Thread.currentThread(); 79 return allowWrite; 80 } 81 82 83 89 90 protected synchronized boolean startReadFromNewReader() { 91 boolean pass = startRead(); 92 if (!pass) ++waitingReaders_; 93 return pass; 94 } 95 96 protected synchronized boolean startWriteFromNewWriter() { 97 boolean pass = startWrite(); 98 if (!pass) ++waitingWriters_; 99 return pass; 100 } 101 102 protected synchronized boolean startReadFromWaitingReader() { 103 boolean pass = startRead(); 104 if (pass) --waitingReaders_; 105 return pass; 106 } 107 108 protected synchronized boolean startWriteFromWaitingWriter() { 109 boolean pass = startWrite(); 110 if (pass) --waitingWriters_; 111 return pass; 112 } 113 114 118 protected synchronized Signaller endRead() { 119 if (--activeReaders_ == 0 && waitingWriters_ > 0) 120 return writerLock_; 121 else 122 return null; 123 } 124 125 126 130 protected synchronized Signaller endWrite() { 131 activeWriter_ = null; 132 if (waitingReaders_ > 0 && allowReader()) 133 return readerLock_; 134 else if (waitingWriters_ > 0) 135 return writerLock_; 136 else 137 return null; 138 } 139 140 141 149 150 protected abstract class Signaller { abstract void signalWaiters(); 152 } 153 154 protected class ReaderLock extends Signaller implements Sync { 155 156 public void acquire() throws InterruptedException { 157 if (Thread.interrupted()) throw new InterruptedException (); 158 InterruptedException ie = null; 159 synchronized(this) { 160 if (!startReadFromNewReader()) { 161 for (;;) { 162 try { 163 ReaderLock.this.wait(); 164 if (startReadFromWaitingReader()) 165 return; 166 } 167 catch(InterruptedException ex){ 168 cancelledWaitingReader(); 169 ie = ex; 170 break; 171 } 172 } 173 } 174 } 175 if (ie != null) { 176 writerLock_.signalWaiters(); 180 throw ie; 181 } 182 } 183 184 185 public void release() { 186 Signaller s = endRead(); 187 if (s != null) s.signalWaiters(); 188 } 189 190 191 synchronized void signalWaiters() { ReaderLock.this.notifyAll(); } 192 193 public boolean attempt(long msecs) throws InterruptedException { 194 if (Thread.interrupted()) throw new InterruptedException (); 195 InterruptedException ie = null; 196 synchronized(this) { 197 if (msecs <= 0) 198 return startRead(); 199 else if (startReadFromNewReader()) 200 return true; 201 else { 202 long waitTime = msecs; 203 long start = System.currentTimeMillis(); 204 for (;;) { 205 try { ReaderLock.this.wait(waitTime); } 206 catch(InterruptedException ex){ 207 cancelledWaitingReader(); 208 ie = ex; 209 break; 210 } 211 if (startReadFromWaitingReader()) 212 return true; 213 else { 214 waitTime = msecs - (System.currentTimeMillis() - start); 215 if (waitTime <= 0) { 216 cancelledWaitingReader(); 217 break; 218 } 219 } 220 } 221 } 222 } 223 writerLock_.signalWaiters(); 225 if (ie != null) throw ie; 226 else return false; } 228 229 } 230 231 protected class WriterLock extends Signaller implements Sync { 232 233 public void acquire() throws InterruptedException { 234 if (Thread.interrupted()) throw new InterruptedException (); 235 InterruptedException ie = null; 236 synchronized(this) { 237 if (!startWriteFromNewWriter()) { 238 for (;;) { 239 try { 240 WriterLock.this.wait(); 241 if (startWriteFromWaitingWriter()) 242 return; 243 } 244 catch(InterruptedException ex){ 245 cancelledWaitingWriter(); 246 WriterLock.this.notify(); 247 ie = ex; 248 break; 249 } 250 } 251 } 252 } 253 if (ie != null) { 254 readerLock_.signalWaiters(); 258 throw ie; 259 } 260 } 261 262 public void release(){ 263 Signaller s = endWrite(); 264 if (s != null) s.signalWaiters(); 265 } 266 267 synchronized void signalWaiters() { WriterLock.this.notify(); } 268 269 public boolean attempt(long msecs) throws InterruptedException { 270 if (Thread.interrupted()) throw new InterruptedException (); 271 InterruptedException ie = null; 272 synchronized(this) { 273 if (msecs <= 0) 274 return startWrite(); 275 else if (startWriteFromNewWriter()) 276 return true; 277 else { 278 long waitTime = msecs; 279 long start = System.currentTimeMillis(); 280 for (;;) { 281 try { WriterLock.this.wait(waitTime); } 282 catch(InterruptedException ex){ 283 cancelledWaitingWriter(); 284 WriterLock.this.notify(); 285 ie = ex; 286 break; 287 } 288 if (startWriteFromWaitingWriter()) 289 return true; 290 else { 291 waitTime = msecs - (System.currentTimeMillis() - start); 292 if (waitTime <= 0) { 293 cancelledWaitingWriter(); 294 WriterLock.this.notify(); 295 break; 296 } 297 } 298 } 299 } 300 } 301 302 readerLock_.signalWaiters(); 303 if (ie != null) throw ie; 304 else return false; } 306 307 } 308 309 310 311 } 312 313 | Popular Tags |