1 8 9 package com.sleepycat.je.latch; 10 11 import java.util.ArrayList ; 12 import java.util.Iterator ; 13 import java.util.List ; 14 15 import com.sleepycat.je.DatabaseException; 16 import com.sleepycat.je.RunRecoveryException; 17 import com.sleepycat.je.dbi.EnvironmentImpl; 18 19 35 public class SharedLatchImpl implements SharedLatch { 36 37 private String name = null; 38 private List waiters = new ArrayList (); 39 private LatchStats stats = new LatchStats(); 40 41 private EnvironmentImpl env = null; 42 private boolean noteLatch; 43 private boolean exclusiveOnly; 44 45 48 public SharedLatchImpl(String name, EnvironmentImpl env) { 49 this.name = name; 50 this.env = env; 51 this.exclusiveOnly = false; 52 } 53 54 57 public void setExclusiveOnly(boolean exclusiveOnly) { 58 this.exclusiveOnly = exclusiveOnly; 59 } 60 61 65 synchronized public void setName(String name) { 66 this.name = name; 67 } 68 69 73 synchronized public boolean setNoteLatch(boolean noteLatch) { 74 this.noteLatch = noteLatch; 75 return true; 76 } 77 78 94 public synchronized void acquireExclusive() 95 throws DatabaseException { 96 97 try { 98 Thread thread = Thread.currentThread(); 99 int index = indexOf(thread); 100 Owner owner; 101 if (index < 0) { 102 owner = new Owner(thread, Owner.EXCLUSIVE); 103 waiters.add(owner); 104 } else { 105 throw new LatchException 106 (getNameString() + " reentrancy/upgrade not allowed"); 107 } 108 if (waiters.size() == 1) { 109 stats.nAcquiresNoWaiters++; 110 } else { 111 stats.nAcquiresWithContention++; 112 while (waiters.get(0) != owner) { 113 wait(); 114 } 115 } 116 owner.nAcquires += 1; 117 assert (noteLatch ? noteLatch() : true); } catch (InterruptedException e) { 119 throw new RunRecoveryException(env, e); 120 } finally { 121 assert EnvironmentImpl.maybeForceYield(); 122 } 123 } 124 125 public synchronized boolean acquireExclusiveNoWait() 126 throws DatabaseException { 127 128 try { 129 Thread thread = Thread.currentThread(); 130 int index = indexOf(thread); 131 if (index < 0) { 132 if (waiters.size() == 0) { 133 Owner owner = new Owner(thread, Owner.EXCLUSIVE); 134 waiters.add(owner); 135 owner.nAcquires += 1; 136 stats.nAcquiresNoWaiters++; 137 138 assert (noteLatch ? noteLatch() : true); 139 return true; 140 } else { 141 return false; 142 } 143 } else { 144 throw new LatchException 145 (getNameString() + " reentrancy/upgrade not allowed"); 146 } 147 } finally { 148 assert EnvironmentImpl.maybeForceYield(); 149 } 150 } 151 152 159 public synchronized void acquireShared() 160 throws DatabaseException { 161 162 if (exclusiveOnly) { 163 acquireExclusive(); 164 return; 165 } 166 167 try { 168 Thread thread = Thread.currentThread(); 169 int index = indexOf(thread); 170 Owner owner; 171 if (index < 0) { 172 owner = new Owner(thread, Owner.SHARED); 173 waiters.add(owner); 174 } else { 175 owner = (Owner) waiters.get(index); 176 } 177 while (indexOf(thread) > firstWriter()) { 178 wait(); 179 } 180 owner.nAcquires += 1; 181 stats.nAcquireSharedSuccessful++; 182 assert (noteLatch ? noteLatch() : true); } catch (InterruptedException e) { 184 throw new RunRecoveryException(env, e); 185 } finally { 186 assert EnvironmentImpl.maybeForceYield(); 187 } 188 } 189 190 public synchronized boolean isOwner() { 191 try { 192 Thread thread = Thread.currentThread(); 193 int index = indexOf(thread); 194 if (index < 0 || 195 index > firstWriter()) { 196 return false; 197 } 198 return true; 199 } finally { 200 assert EnvironmentImpl.maybeForceYield(); 201 } 202 } 203 204 208 public synchronized void release() 209 throws LatchNotHeldException { 210 211 try { 212 Thread thread = Thread.currentThread(); 213 int index = indexOf(thread); 214 if (index < 0 || index > firstWriter()) { 215 return; 216 } 217 Owner owner = (Owner) waiters.get(index); 218 owner.nAcquires -= 1; 219 if (owner.nAcquires == 0) { 220 waiters.remove(index); 221 222 assert (noteLatch ? unNoteLatch() : true); 223 notifyAll(); 224 } 225 stats.nReleases++; 226 } finally { 227 assert EnvironmentImpl.maybeForceYield(); 228 } 229 } 230 231 public void releaseIfOwner() 232 throws LatchNotHeldException { 233 234 release(); 235 } 236 237 241 private int indexOf(Thread thread) { 242 243 Iterator i = waiters.iterator(); 244 for (int index = 0; i.hasNext(); index += 1) { 245 Owner owner = (Owner) i.next(); 246 if (owner.thread == thread) { 247 return index; 248 } 249 } 250 return -1; 251 } 252 253 257 private int firstWriter() { 258 259 Iterator i = waiters.iterator(); 260 for (int index = 0; i.hasNext(); index += 1) { 261 Owner owner = (Owner) i.next(); 262 if (owner.type == Owner.EXCLUSIVE) { 263 return index; 264 } 265 } 266 return Integer.MAX_VALUE; 267 } 268 269 272 private static class Owner { 273 274 static final int SHARED = 0; 275 static final int EXCLUSIVE = 1; 276 277 Thread thread; 278 int type; 279 int nAcquires; 280 281 Owner(Thread thread, int type) { 282 this.thread = thread; 283 this.type = type; 284 } 285 } 286 287 290 private String getNameString() { 291 292 return LatchSupport.latchTable.getNameString(name); 293 } 294 295 298 private boolean noteLatch() 299 throws LatchException { 300 301 return LatchSupport.latchTable.noteLatch(this); 302 } 303 304 307 private boolean unNoteLatch() 308 throws LatchNotHeldException { 309 310 return LatchSupport.latchTable.unNoteLatch(this, name); 311 } 312 313 public synchronized boolean isWriteLockedByCurrentThread() { 314 if (waiters.size() > 0) { 315 Owner curOwner = (Owner) waiters.get(0); 316 return (curOwner.thread == Thread.currentThread() && 317 curOwner.type == Owner.EXCLUSIVE); 318 } else { 319 return false; 320 } 321 } 322 323 327 328 333 339 340 345 351 352 357 364 365 370 376 377 380 386 } 387 | Popular Tags |