1 8 9 package com.sleepycat.je.latch; 10 11 import java.util.ArrayList ; 12 import java.util.List ; 13 14 import com.sleepycat.je.DatabaseException; 15 import com.sleepycat.je.RunRecoveryException; 16 import com.sleepycat.je.dbi.EnvironmentImpl; 17 18 34 public class LatchImpl implements Latch { 35 private static final String DEFAULT_LATCH_NAME = "LatchImpl"; 36 37 private String name = null; 38 private List waiters = null; 39 private LatchStats stats = new LatchStats(); 40 41 private EnvironmentImpl env = null; 42 private Thread owner = null; 43 44 47 public LatchImpl(String name, EnvironmentImpl env) { 48 this.name = name; 49 this.env = env; 50 } 51 52 55 public LatchImpl(EnvironmentImpl env) { 56 this.env = env; 57 this.name = DEFAULT_LATCH_NAME; 58 } 59 60 64 synchronized public void setName(String name) { 65 this.name = name; 66 } 67 68 82 public void acquire() 83 throws DatabaseException { 84 85 try { 86 Thread thread = Thread.currentThread(); 87 LatchWaiter waitTarget = null; 88 89 synchronized (this) { 90 if (thread == owner) { 91 stats.nAcquiresSelfOwned++; 92 throw new LatchException(getNameString() + 93 " already held"); 94 } 95 96 if (owner == null) { 97 stats.nAcquiresNoWaiters++; 98 owner = thread; 99 } else { 100 if (waiters == null) { 101 waiters = new ArrayList (); 102 } 103 waitTarget = new LatchWaiter(thread); 104 waiters.add(waitTarget); 105 stats.nAcquiresWithContention++; 106 } 107 } 108 109 if (waitTarget != null) { 110 synchronized (waitTarget) { 111 while (true) { 112 if (waitTarget.active) { 113 if (thread == owner) { 114 break; 115 } else { 116 throw new DatabaseException 117 ("waitTarget.active but not owner"); 118 } 119 } else { 120 waitTarget.wait(); 121 if (thread == owner) { 122 break; 123 } else { 124 continue; 125 } 126 } 127 } 128 } 129 } 130 131 assert noteLatch(); } catch (InterruptedException e) { 133 throw new RunRecoveryException(env, e); 134 } finally { 135 assert EnvironmentImpl.maybeForceYield(); 136 } 137 } 138 139 148 public synchronized boolean acquireNoWait() 149 throws LatchException { 150 151 try { 152 Thread thread = Thread.currentThread(); 153 if (thread == owner) { 154 stats.nAcquiresSelfOwned++; 155 throw new LatchException(getNameString() + 156 " already held"); 157 } 158 if (owner == null) { 159 owner = thread; 160 stats.nAcquireNoWaitSuccessful++; 161 assert noteLatch(); return true; 163 } else { 164 stats.nAcquireNoWaitUnsuccessful++; 165 return false; 166 } 167 } finally { 168 assert EnvironmentImpl.maybeForceYield(); 169 } 170 } 171 172 177 public void releaseIfOwner() { 178 doRelease(false); 179 } 180 181 187 public void release() 188 throws LatchNotHeldException { 189 190 if (doRelease(true)) { 191 throw new LatchNotHeldException 192 (getNameString() + " not held"); 193 } 194 } 195 196 201 private boolean doRelease(boolean checkHeld) { 202 203 LatchWaiter newOwner = null; 204 205 try { 206 synchronized (this) { 207 Thread thread = Thread.currentThread(); 208 if (thread != owner) { 209 return true; 210 } 211 212 if (waiters != null && waiters.size() > 0) { 213 newOwner = (LatchWaiter) waiters.remove(0); 214 owner = (Thread ) newOwner.thread; 215 216 } else { 217 owner = null; 218 } 219 stats.nReleases++; 220 assert unNoteLatch(checkHeld); } 222 } finally { 223 assert EnvironmentImpl.maybeForceYield(); 224 } 225 226 if (newOwner != null) { 227 synchronized (newOwner) { 228 newOwner.active = true; 229 newOwner.notifyAll(); 230 } 231 } 232 return false; 233 } 234 235 240 public boolean isOwner() { 241 242 return Thread.currentThread() == owner; 243 } 244 245 250 public Thread owner() { 251 252 return owner; 253 } 254 255 260 public synchronized int nWaiters() { 261 262 return (waiters != null) ? waiters.size() : 0; 263 } 264 265 268 public LatchStats getLatchStats() { 269 LatchStats s = null; 270 try { 271 s = (LatchStats) stats.clone(); 272 } catch (CloneNotSupportedException e) { 273 274 } 275 return s; 276 } 277 278 281 public synchronized String toString() { 282 283 return LatchSupport.latchTable.toString(name, owner, waiters, 0); 284 } 285 286 289 private String getNameString() { 290 291 return LatchSupport.latchTable.getNameString(name); 292 } 293 294 297 private boolean noteLatch() 298 throws LatchException { 299 300 return LatchSupport.latchTable.noteLatch(this); 301 } 302 303 306 private boolean unNoteLatch(boolean checkHeld) { 307 308 309 if (checkHeld) { 310 return LatchSupport.latchTable.unNoteLatch(this, name); 311 } else { 312 LatchSupport.latchTable.unNoteLatch(this, name); 313 return true; 314 } 315 } 316 317 320 static private class LatchWaiter { 321 boolean active; 322 Thread thread; 323 324 LatchWaiter(Thread thread) { 325 this.thread = thread; 326 active = false; 327 } 328 329 public String toString() { 330 return "<LatchWaiter: " + thread + ">"; 331 } 332 } 333 } 334 | Popular Tags |