1 package com.daffodilwoods.daffodildb.server.datasystem.utility; 2 3 import java.util.*; 4 5 public class FIFOReadWriteLocker implements ReadWriteLock{ 6 7 boolean tableLocked= false; 8 TableLock tableLock = new TableLock(); 9 Map map = Collections.synchronizedMap(new HashMap()); 10 Object monitor = new Object (); 11 12 Vector waiters = new Vector(10); 13 14 public FIFOReadWriteLocker() { 15 } 16 17 private static class TableLock{ 18 Object owner; 19 int waitingThreads=0; 20 21 synchronized void incrementWaiters(){ 22 ++waitingThreads; 23 } 24 25 synchronized void decrementWaitersToZero(){ 26 waitingThreads = 0; 27 } 28 29 synchronized int waitersCount(){ 30 return waitingThreads; 31 } 32 } 33 34 static private class RowLock{ 35 Object owner; int readersCount; 37 private int waitingThreads; 38 39 synchronized void increment(){ 40 ++readersCount; 41 } 42 43 synchronized void decrement(){ 44 --readersCount; 45 } 46 47 synchronized int readersCount(){ 48 return readersCount; 49 } 50 51 synchronized void incrementWaiters(){ 52 ++waitingThreads; 53 } 54 55 synchronized void decrementWaitersToZero(){ 56 waitingThreads = 0; 57 } 58 59 synchronized int waitingThreads(){ 60 return waitingThreads; 61 } 62 63 } 64 65 private static class Wait{ 66 RowLock rw; 67 boolean read; 68 private Object rowIdentity; 69 70 boolean rowLock; 71 72 public synchronized void doWait(){ 73 try { 74 wait(10); 75 }catch (InterruptedException ex) { 76 } 77 } 78 79 public synchronized void signal(){ 80 notify(); 81 } 82 } 83 84 private void waitOnTableLock(boolean rowLock){ 85 Wait tw = new Wait(); 86 tw.rowLock = rowLock; 87 waiters.add(tw); 88 do{ 89 tw.doWait(); 90 }while( (tableLocked || map.size() > 0) || (waiters.indexOf(tw) != 0) ); 91 waiters.remove(0); 92 } 93 94 ArrayList released = new ArrayList(10); 95 96 private void notifyOnTableLock(){ 97 released.clear(); 98 boolean flag = true; 99 try{ 100 for (int i = 0;flag && i < waiters.size(); i++) { 101 Wait w = (Wait)waiters.get(i); 102 if( w.rw == null && w.rowLock == false ){ 103 flag = false; if( released.size() == 0 ) 105 released.add(w); 106 } 107 else if( w.read == false ) 108 { 109 for (Iterator j = released.iterator();flag && j.hasNext(); ) { 110 Wait item = (Wait)j.next(); 111 if ( item.rowIdentity.equals(w.rowIdentity) ){ 112 flag = false; 113 } 114 } 115 } 116 else{ 117 released.add(w); 118 } 119 } 120 }catch(ArrayIndexOutOfBoundsException ae){ 121 } 122 123 for (int i = 0,length=released.size(); i < length; i++) { 124 Wait w = (Wait) released.get(i); 125 w.signal(); 126 } 127 released.clear(); 128 } 129 130 private void waitOnRowLock(RowLock rw, Object rowIdentity,boolean read){ 131 Wait w = new Wait(); 132 w.rw = rw; 133 w.read = read; 134 w.rowIdentity = rowIdentity; 135 waiters.add(w); 136 do{ 137 w.doWait(); 138 }while( tableLocked || (waiters.indexOf(w) != 0) ); 139 waiters.remove(0); 140 } 141 142 private void notifyOnRowLock(RowLock rw){ 143 notifyOnTableLock(); 144 } 145 146 public void lockTable() { 147 for(;;){ 148 if( tableLocked ){ 149 waitOnTableLock(false); 150 } 151 else if ( map.size() > 0 ) 152 { 153 tableLock.incrementWaiters(); 154 waitOnTableLock(false); 155 } 156 else{ 157 synchronized( monitor ){ 158 if( map.size() == 0 ){ 159 tableLocked = true; 160 tableLock.decrementWaitersToZero(); 161 tableLock.owner = Thread.currentThread(); 162 return; 163 } 164 } 165 } 166 } 167 } 168 169 public void releaseTable() { 170 synchronized( monitor ) { 171 tableLock.owner = null; 172 notifyOnTableLock(); 173 tableLocked = false; 174 } 175 } 176 177 public void lockRowForRead(Object rowIdentity) { 178 for(;;){ 179 RowLock rw = (RowLock)map.get(rowIdentity); 180 if( rw != null ){ 181 if( rw.owner == Thread.currentThread() ){ 182 synchronized( monitor ){ 183 rw.increment(); 184 map.put(rowIdentity,rw); 185 return; 186 } 187 } 188 else if ( tableLock.waitersCount() > 0 ){ 189 waitOnTableLock(true); 190 } 191 else if( rw.owner == null && rw.waitingThreads()==0){ 192 synchronized( monitor ){ 193 if( tableLocked == false ){ 194 rw = (RowLock)map.get(rowIdentity); 195 rw = rw == null ? new RowLock() : rw; if(rw !=null && rw.owner == null && rw.waitingThreads()==0 ){ 197 rw.increment(); 198 map.put(rowIdentity,rw); 199 return; 200 } 201 } 202 } 203 } 204 else{ 205 rw.incrementWaiters(); 206 waitOnRowLock(rw,rowIdentity,true); 207 } 208 } 209 else if ( tableLocked ){ 210 waitOnTableLock(true); 211 } 212 else if ( tableLock.waitersCount() > 0 ){ 213 waitOnTableLock(true); 214 } 215 else{ 216 synchronized( monitor ){ 217 if( tableLocked == false ){ 218 rw = (RowLock)map.get(rowIdentity); 219 rw = rw == null ? new RowLock() : rw; 220 if( rw.owner == null ){ 221 rw.increment(); 222 map.put(rowIdentity,rw); 223 return; 224 } 225 } 226 } 227 } 228 } 229 } 230 231 public void releaseRowForRead(Object rowIdentity) { 232 synchronized(monitor){ 233 RowLock rw = (RowLock) map.get(rowIdentity); 234 tableLocked=true; 235 rw.decrement(); 236 237 if( rw.readersCount() == 0 ){ 238 map.remove(rowIdentity); 239 240 if ( tableLock.waitersCount() > 0 ) 241 notifyOnTableLock(); 242 243 if( rw.waitingThreads() > 0 ) 244 notifyOnRowLock(rw); 245 } 246 tableLocked=false; 247 } 248 } 249 250 public void lockRowForWrite(Object rowIdentity) { 251 for(;;){ 252 RowLock rw = (RowLock) map.get(rowIdentity); 253 if( rw != null ){ 254 if( tableLock.waitersCount() > 0){ 255 waitOnTableLock(true); 256 } 257 else{ 258 rw.incrementWaiters(); 259 waitOnRowLock(rw,rowIdentity,false); 260 } 261 } 262 else if ( tableLocked ){ 263 waitOnTableLock(true); 264 } 265 else if ( tableLock.waitersCount() > 0 ){ 266 waitOnTableLock(true); 267 } 268 else{ 269 synchronized( monitor ){ 270 if( tableLocked == false ){ 271 rw = (RowLock) map.get(rowIdentity); 272 rw = rw == null ? new RowLock() : rw; 273 if( rw.readersCount() == 0 ){ 274 rw.increment(); 275 rw.owner = Thread.currentThread(); 276 map.put(rowIdentity,rw); 277 return; 278 } 279 } 280 } 281 } 282 } 283 } 284 285 public void releaseRowForWrite(Object rowIdentity) { 286 synchronized( monitor ){ 287 RowLock rw = (RowLock) map.get(rowIdentity); 288 tableLocked = true; 289 rw.decrement(); 290 291 map.remove(rowIdentity); 292 293 if( tableLock.waitersCount() > 0 ){ 294 notifyOnTableLock(); 295 } 296 297 if ( rw.waitingThreads() > 0 ) 298 notifyOnRowLock(rw); 299 300 tableLocked = false; 301 } 302 } 303 } 304 | Popular Tags |