Mercurial > hg > blitz_condensed
diff src/org/dancres/blitz/txnlock/LockCache.java @ 0:3dc0c5604566
Initial checkin of blitz 2.0 fcs - no installer yet.
author | Dan Creswell <dan.creswell@gmail.com> |
---|---|
date | Sat, 21 Mar 2009 11:00:06 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/org/dancres/blitz/txnlock/LockCache.java Sat Mar 21 11:00:06 2009 +0000 @@ -0,0 +1,90 @@ +package org.dancres.blitz.txnlock; + +import java.util.HashMap; + +import java.lang.ref.ReferenceQueue; +import java.lang.ref.WeakReference; + +import org.dancres.blitz.oid.OID; + +class LockCache { + private HashMap theLocks = new HashMap(); + + private ReferenceQueue theDeadLocks = new ReferenceQueue(); + + LockCache() { + } + + TxnLock getOrInsert(OID aOID) { + cleanQueue(); + + synchronized(this) { + TxnLock myLock = get(aOID); + + if (myLock == null) { + myLock = new TxnLock(); + put(aOID, myLock); + } + + return myLock; + } + } + + TxnLock get(OID aOID) { + cleanQueue(); + + synchronized(this) { + LockHolder myHolder = (LockHolder) theLocks.get(aOID); + + return (myHolder == null) ? null : (TxnLock) myHolder.get(); + } + } + + void put(OID aOID, TxnLock aLock) { + cleanQueue(); + + synchronized(this) { + LockHolder myHolder = new LockHolder(aOID, aLock, theDeadLocks); + + theLocks.put(aOID, myHolder); + } + } + + private void cleanQueue() { + LockHolder myRef; + + while ((myRef = (LockHolder) theDeadLocks.poll()) != null) { + synchronized(this) { + LockHolder myOther = (LockHolder) theLocks.remove(myRef.getOID()); + + /* + Check that the reference we're releasing is the same as the + one we currently have in the table. Otherwise: + + It could be that get(OID) was called above and the holder was + recovered but it's reference had been cleared resulting in + allocation of a new lock BEFORE we've processed the reference + from the queue. Thus we allocate the new lock, the old + reference (from get(OID)) is enqueued and we then delete the + new lock - oops! + */ + if ((myOther != null) &&(! myOther.equals(myRef))) { + theLocks.put(myOther.getOID(), myOther); + } + } + } + } + + private class LockHolder extends WeakReference { + private OID theOID; + + LockHolder(OID aOID, TxnLock aLock, ReferenceQueue aQueue) { + super(aLock, aQueue); + theOID = aOID; + } + + OID getOID() { + return theOID; + } + } +}