Mercurial > hg > blitz_stable
comparison 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 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:3dc0c5604566 |
---|---|
1 package org.dancres.blitz.txnlock; | |
2 | |
3 import java.util.HashMap; | |
4 | |
5 import java.lang.ref.ReferenceQueue; | |
6 import java.lang.ref.WeakReference; | |
7 | |
8 import org.dancres.blitz.oid.OID; | |
9 | |
10 class LockCache { | |
11 private HashMap theLocks = new HashMap(); | |
12 | |
13 private ReferenceQueue theDeadLocks = new ReferenceQueue(); | |
14 | |
15 LockCache() { | |
16 } | |
17 | |
18 TxnLock getOrInsert(OID aOID) { | |
19 cleanQueue(); | |
20 | |
21 synchronized(this) { | |
22 TxnLock myLock = get(aOID); | |
23 | |
24 if (myLock == null) { | |
25 myLock = new TxnLock(); | |
26 put(aOID, myLock); | |
27 } | |
28 | |
29 return myLock; | |
30 } | |
31 } | |
32 | |
33 TxnLock get(OID aOID) { | |
34 cleanQueue(); | |
35 | |
36 synchronized(this) { | |
37 LockHolder myHolder = (LockHolder) theLocks.get(aOID); | |
38 | |
39 return (myHolder == null) ? null : (TxnLock) myHolder.get(); | |
40 } | |
41 } | |
42 | |
43 void put(OID aOID, TxnLock aLock) { | |
44 cleanQueue(); | |
45 | |
46 synchronized(this) { | |
47 LockHolder myHolder = new LockHolder(aOID, aLock, theDeadLocks); | |
48 | |
49 theLocks.put(aOID, myHolder); | |
50 } | |
51 } | |
52 | |
53 private void cleanQueue() { | |
54 LockHolder myRef; | |
55 | |
56 while ((myRef = (LockHolder) theDeadLocks.poll()) != null) { | |
57 synchronized(this) { | |
58 LockHolder myOther = (LockHolder) theLocks.remove(myRef.getOID()); | |
59 | |
60 /* | |
61 Check that the reference we're releasing is the same as the | |
62 one we currently have in the table. Otherwise: | |
63 | |
64 It could be that get(OID) was called above and the holder was | |
65 recovered but it's reference had been cleared resulting in | |
66 allocation of a new lock BEFORE we've processed the reference | |
67 from the queue. Thus we allocate the new lock, the old | |
68 reference (from get(OID)) is enqueued and we then delete the | |
69 new lock - oops! | |
70 */ | |
71 if ((myOther != null) &&(! myOther.equals(myRef))) { | |
72 theLocks.put(myOther.getOID(), myOther); | |
73 } | |
74 } | |
75 } | |
76 } | |
77 | |
78 private class LockHolder extends WeakReference { | |
79 private OID theOID; | |
80 | |
81 LockHolder(OID aOID, TxnLock aLock, ReferenceQueue aQueue) { | |
82 super(aLock, aQueue); | |
83 theOID = aOID; | |
84 } | |
85 | |
86 OID getOID() { | |
87 return theOID; | |
88 } | |
89 } | |
90 } |