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 }