1 package locklib; 2 3 import ensure.Ensure; 4 5 /** 6 * <p>A lock grant represents the successful acquisition of a lock. Lock grants 7 * can be either <em>valid</em> or <em>invalid</em>. They are created 8 * valid but, once the lock is released, they become invalid (meaning the 9 * lock granted has been revoked).</p> 10 * 11 * <p>Lock grants are organized in chains: the previous lock in a chain is 12 * called the <em>predecessor</em> lock and the next lock in the chain is 13 * called the <em>successor</em> lock. The first lock in the chain has no 14 * predecessor and the last has no successor. Chains are built from the 15 * target hierarchy: beginning of the chain is the top element in the 16 * target hierarchy and the last element in the lock chain is placed in the 17 * bottom element locked in target hierarchy.</p> 18 * 19 * <p>When being acquired, predecessor locks must be acquired <em>before</em> 20 * and released <em>after</em>. This is handled transparently 21 * by <em>locklib</em>.</p> 22 * 23 * <p>Lock grants are acquired through {@link LockGrantFuture}.</p> 24 * 25 * <p>Synchronization locks on <code>LockGrant</code> should never be made 26 * outside <em>locklib</em></p>. 27 * @param <LockType> type of lock 28 */ 29 /* 30 * Implementation notes: 31 * 32 * LockGrants are self-contained from a synchronization perspective: they do 33 * not invoke any object of another class with a lock held. 34 * 35 * LockGrants may need to acquire several synchronization locks on lock grants. 36 * The rule is that successors have to be locked before predecessors. 37 * 38 * LockGrants must be acquired forward in the chain and released backwards. 39 * This means that LockGrants can only be acquired once the predecessor grant 40 * has been acquired and can only be released after their successor has been 41 * released. 42 * 43 * LockGrants do not change anything else other than their own state. They do 44 * interact with other grants in the chain to ensure consistency. 45 */ 46 public class LockGrant<LockType> { 47 /** 48 * The lock requested. 49 */ 50 private LockRequest<LockType> m_request; 51 52 /** 53 * The lock target. 54 */ 55 private Target<LockType> m_target; 56 57 /** 58 * The predecessor lock that must be released <em>after</em> this one. 59 */ 60 private LockGrant<LockType> m_predecessor; 61 62 /** 63 * The successor lock that must be released <em>before</em> this one. 64 */ 65 private LockGrant<LockType> m_successor; 66 67 /** 68 * Is this grant still valid? 69 */ 70 private boolean m_valid; 71 72 /** 73 * Creates a new grant. 74 * @param r the lock requested 75 * @param t the target where the lock has been granted 76 * @param predecessor an optional predecessor 77 */ 78 LockGrant(LockRequest<LockType> r, Target<LockType> t, 79 LockGrant<LockType> predecessor) { 80 Ensure.not_null(r, "r == null"); 81 Ensure.not_null(t, "t == null"); 82 83 m_request = r; 84 m_target = t; 85 m_predecessor = predecessor; 86 m_valid = true; 87 m_successor = null; 88 89 /* 90 * Set this lock as the successor of the predecessor lock if there is 91 * a predecessor lock. 92 */ 93 if (predecessor != null) { 94 synchronized (predecessor) { 95 Ensure.is_null(predecessor.m_successor, 96 "predecessor.m_successor != null"); 97 Ensure.is_true(predecessor.m_valid, "!predecessor.m_valid"); 98 predecessor.m_successor = this; 99 } 100 } 101 } 102 103 /** 104 * Checks whether this grant is still valid or not. 105 * @return is the grant still valid? 106 */ 107 public synchronized boolean valid() { 108 return m_valid; 109 } 110 111 /** 112 * Invalidates a valid lock grant making it invalid. 113 */ 114 void invalidate() { 115 LockGrant<LockType> suc; 116 117 /* 118 * This is tricky but successors need to be held before predecessors. 119 * So first we must figure out if we have a successor to lock and check 120 * its state *before* locking and checking ourselves. 121 */ 122 synchronized (this) { 123 suc = m_successor; 124 } 125 126 if (suc != null) { 127 synchronized (m_successor) { 128 Ensure.is_false(m_successor.m_valid, "m_successor.m_valid"); 129 synchronized (this) { 130 Ensure.is_true(m_valid, "!m_valid"); 131 m_valid = false; 132 } 133 } 134 } else { 135 synchronized (this) { 136 Ensure.is_true(m_valid, "!m_valid"); 137 m_valid = false; 138 } 139 } 140 } 141 142 /** 143 * Obtains the lock request that generated this grant. 144 * @return the request 145 */ 146 public synchronized LockRequest<LockType> request() { 147 return m_request; 148 } 149 150 /** 151 * Obtains the locked target. 152 * @return the target 153 */ 154 public synchronized Target<LockType> target() { 155 return m_target; 156 } 157 158 /** 159 * Obtains the predecessor grant, if any. 160 * @return the grant or <code>null</code> if there is none 161 */ 162 synchronized LockGrant<LockType> predecessor() { 163 return m_predecessor; 164 } 165 166 /** 167 * Obtains the successor grant, if any. 168 * @return the grant or <code>null</code> if there is none 169 */ 170 synchronized LockGrant<LockType> successor() { 171 return m_successor; 172 } 173 174 /** 175 * Releases the grant. This is equivalent to invoke the 176 * {@link Target#unlock(LockGrant)} method of this grant's target. 177 */ 178 public void release() { 179 target().unlock(this); 180 } 181 182 @Override 183 public String toString() { 184 return "LockGrant[request=" + m_request + ", target=" + m_target 185 + ", predecessor=" + m_predecessor + "]"; 186 } 187 }