1 package locklib;
2
3 import java.util.HashMap;
4 import java.util.HashSet;
5 import java.util.LinkedList;
6 import java.util.List;
7 import java.util.Map;
8 import java.util.Set;
9
10 import ensure.Ensure;
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51 public class Target<LockType> {
52
53
54
55
56 private Map<Target<LockType>, Set<Target<LockType>>> m_children;
57
58
59
60
61 private Target<LockType> m_parent;
62
63
64
65
66 private LockManager<LockType> m_manager;
67
68
69
70
71 private Set<LockGrant<LockType>> m_locks;
72
73
74
75
76 private WaitQueue<LockType> m_queue;
77
78
79
80
81
82 public Target(LockManager<LockType> lm) {
83 Ensure.not_null(lm, "lm == null");
84 m_manager = lm;
85 m_parent = null;
86 m_children = new HashMap<>();
87 m_locks = new HashSet<>();
88 m_queue = null;
89 }
90
91
92
93
94
95 public Target(Target<LockType> parent) {
96 this(Ensure.not_null(parent, "parent == null").m_manager);
97 parent(parent);
98 }
99
100
101
102
103
104
105
106
107
108
109 public synchronized void parent(Target<LockType> p) {
110 if (p == m_parent) {
111 return;
112 }
113
114 if (p == this) {
115 throw new CyclicTargetHierarchyException("Cannot add a target as "
116 + "a parent of itself.");
117 }
118
119 if (p != null && p.m_manager != m_manager) {
120 throw new DifferentLockManagersException("Target {" + p + "} has "
121 + "lock manager {" + p.m_manager + "} and this {" + this
122 + "} has lock manager { " + m_manager + "}.");
123 }
124
125 if (m_locks.size() > 0) {
126 throw new HierarchyChangeBreaksChainException("Cannot set parent "
127 + "of target {" + this + "} to {" + p + "} because it "
128 + "would break existing lock chains.");
129 }
130
131 if (m_parent != null) {
132 m_parent.remove_child(this);
133 m_parent = null;
134 }
135
136 if (p != null) {
137
138
139
140 synchronized (p) {
141 if (m_children.containsKey(p)) {
142 throw new CyclicTargetHierarchyException("Cannot add {"
143 + p + "} as a parent of {" + this + "} because "
144 + "it is a child.");
145 }
146
147 for (Set<Target<LockType>> ch : m_children.values()) {
148 if (ch.contains(p)) {
149 throw new CyclicTargetHierarchyException("Cannot add {"
150 + p + "} as a parent of {" + this + "} "
151 + "because it is a (non-immediate) "
152 + "child.");
153 }
154 }
155
156 p.m_children.put(this, new HashSet<Target<LockType>>());
157 m_parent = p;
158 update_parent_children();
159 }
160 }
161 }
162
163
164
165
166
167
168 private synchronized void remove_child(Target<LockType> c) {
169 Ensure.not_null(c, "c == null");
170 Ensure.is_true(m_children.containsKey(c), "!m_children.containsKey(c)");
171 m_children.remove(c);
172
173 update_parent_children();
174 }
175
176
177
178
179
180 private void update_parent_children() {
181 if (m_parent != null) {
182 Set<Target<LockType>> ch = new HashSet<>(m_children.keySet());
183
184 for (Set<Target<LockType>> cch : m_children.values()) {
185 ch.addAll(cch);
186 }
187
188 m_parent.update_children(this, ch);
189 }
190 }
191
192
193
194
195
196
197
198 private synchronized void update_children(Target<LockType> c,
199 Set<Target<LockType>> cch) {
200 Ensure.not_null(c, "c == null");
201 Ensure.is_true(m_children.containsKey(c), "!m_children.containsKey(c)");
202 Ensure.not_null(cch, "cch == null");
203
204 m_children.put(c, cch);
205 update_parent_children();
206 }
207
208
209
210
211
212 public synchronized Target<LockType> parent() {
213 return m_parent;
214 }
215
216
217
218
219
220 public synchronized Set<Target<LockType>> children() {
221 return new HashSet<>(m_children.keySet());
222 }
223
224
225
226
227
228
229
230
231
232
233
234 public synchronized LockGrantFuture<LockType> lock(
235 LockRequest<LockType> request) {
236 Ensure.not_null(request, "request == null");
237
238 LockGrantFuture<LockType> future = null;
239
240
241
242
243
244 LockGrantFuture<LockType> plock = null;
245 if (m_parent != null) {
246 LockType plocktype = m_manager.policy().parent_lock(
247 request.type());
248 plock = m_parent.lock(new LockRequest<>(plocktype,
249 request.holder()));
250 }
251
252
253
254
255 future = new LockGrantFuture<>(request, this, plock);
256
257
258
259
260
261 TryLockResult<LockType> r = try_lock(future);
262 Ensure.is_null(r.successor(), "r.successor() != null");
263 if (!r.granted()) {
264 m_manager.pre_checker().pre_check_wait(future.request(), this);
265 if (m_queue == null) {
266 m_queue = m_manager.wait_queue_factory().make();
267 }
268
269 m_queue.enqueue(future);
270 }
271
272 return future;
273 }
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289 private synchronized TryLockResult<LockType> try_lock(
290 LockGrantFuture<LockType> future) {
291 Ensure.not_null(future, "future == null");
292 Ensure.same(this, future.target(), "future.target() != this");
293
294
295
296
297 LockGrantFuture<LockType> successor;
298 boolean succeeded;
299
300 synchronized (future) {
301 Ensure.is_false(future.isDone(), "future.isDone()");
302
303 successor = future.successor_future();
304
305
306
307
308
309 LockGrantFuture<LockType> pf = future.predecessor_future();
310 LockGrant<LockType> plg = null;
311 if (pf != null) {
312 synchronized (pf) {
313 if (!pf.isDone()) {
314 return new TryLockResult<>(false, null);
315 }
316
317 plg = pf.get_now();
318 }
319 }
320
321
322
323
324
325
326 if (pf != null) {
327 Ensure.is_false(pf.isCancelled(), "pf.isCancelled()");
328 }
329
330 if (can_grant(future.request())) {
331 LockGrant<LockType> lg;
332 lg = grant(future.request(), plg);
333 future.acquired(lg);
334 if (m_queue != null) {
335 m_queue.dequeue(future);
336 }
337
338 succeeded = true;
339 } else {
340 succeeded = false;
341 }
342 }
343
344 return new TryLockResult<>(succeeded, successor);
345 }
346
347
348
349
350
351
352
353
354 public void unlock(LockGrant<LockType> g) {
355 Ensure.not_null(g, "g == null");
356 Ensure.same(this, g.target(), "g.target() != this");
357 Ensure.is_null(g.successor(), "g.successor() != null");
358
359 List<Target<LockType>> unlocked_targets = new LinkedList<>();
360 unlock_chain(g, unlocked_targets);
361
362
363
364
365
366
367 for (Target<LockType> t : unlocked_targets) {
368 t.try_lock_any();
369 }
370 }
371
372
373
374
375
376 private void try_lock_any() {
377
378
379
380
381 LinkedList<LockGrantFuture<LockType>> next = new LinkedList<>();
382
383
384
385
386
387 synchronized (this) {
388 boolean done;
389 do {
390 done = false;
391 if (m_queue != null) {
392
393
394
395 for (LockGrantFuture<LockType> pending : m_queue) {
396 TryLockResult<LockType> r = try_lock(pending);
397 if (r.granted()) {
398 done = true;
399 if (r.successor() != null) {
400 next.add(r.successor());
401 }
402
403 break;
404 }
405 }
406 }
407 } while (done);
408 }
409
410
411
412
413
414 while (next.size() > 0) {
415 LockGrantFuture<LockType> f = next.removeFirst();
416 Target<LockType> t = f.target();
417 synchronized (t) {
418 synchronized (f) {
419 if (!f.isDone()) {
420 TryLockResult<LockType> r = t.try_lock(f);
421 if (r.successor() != null) {
422 next.add(r.successor());
423 }
424 }
425 }
426 }
427 }
428 }
429
430
431
432
433
434
435
436
437
438 private synchronized void unlock_chain(LockGrant<LockType> g,
439 List<Target<LockType>> unlocked) {
440 Ensure.not_null(g, "g == null");
441
442 LockGrant<LockType> pred = g.predecessor();
443 synchronized (g) {
444
445
446
447 if (!g.valid()) {
448 throw new NotLockedException("Lock grant is no longer "
449 + "valid. It has already been released.");
450 }
451
452
453
454
455
456
457 LockGrant<LockType> sl = g.successor();
458 if (sl != null) {
459 Ensure.is_false(sl.valid(), "sl.valid()");
460 }
461
462
463
464
465 Ensure.is_true(m_locks.contains(g), "!m_locks.contains(g)");
466 m_locks.remove(g);
467 m_manager.api().unlocked(g);
468 g.invalidate();
469 unlocked.add(this);
470 }
471
472
473
474
475
476
477
478 if (pred != null) {
479 Ensure.is_true(pred.valid(), "!pred.valid()");
480 pred.target().unlock_chain(pred, unlocked);
481 }
482 }
483
484
485
486
487
488
489
490 synchronized boolean can_grant(LockRequest<LockType> request) {
491
492
493
494
495 boolean is_promotion = false;
496
497 Ensure.not_null(request, "request == null");
498 for (LockGrant<LockType> l : m_locks) {
499 if (l.request().holder() == request.holder()) {
500 is_promotion = true;
501 } else if (!m_manager.policy().is_compatible(l.request().type(),
502 request.type())) {
503 return false;
504 }
505 }
506
507 if (!is_promotion && !m_manager.policy().starvation_allowed()) {
508
509
510
511
512
513 if (m_queue != null) {
514 for (LockGrantFuture<LockType> f : m_queue) {
515 if (f.request() == request) {
516
517
518
519
520 break;
521 }
522
523 if (f.predecessor_future() == null ||
524 f.predecessor_future().isDone()) {
525
526
527
528
529
530
531 return false;
532 }
533
534
535
536
537
538
539 }
540 }
541
542 }
543
544 return true;
545 }
546
547
548
549
550
551
552
553
554 private synchronized LockGrant<LockType> grant(
555 LockRequest<LockType> request, LockGrant<LockType> plock) {
556 Ensure.not_null(request, "request == null");
557 LockGrant<LockType> g = new LockGrant<>(request, this, plock);
558 m_locks.add(g);
559 m_manager.api().locked(g);
560 return g;
561 }
562
563
564
565
566
567
568
569
570
571
572 boolean cancel(LockGrantFuture<LockType> future) {
573 Ensure.not_null(future, "future == null");
574
575 LockGrant<LockType> to_release;
576 synchronized (this) {
577 synchronized (future) {
578 Ensure.is_null(future.successor_future(),
579 "future.successor_future() == null");
580
581 if (future.isDone()) {
582 return future.isCancelled();
583 }
584
585 to_release = cancel_chain(future);
586 }
587 }
588
589 if (to_release != null) {
590 unlock(to_release);
591 }
592
593 return true;
594 }
595
596
597
598
599
600
601
602
603
604 synchronized LockGrant<LockType> cancel_chain(
605 LockGrantFuture<LockType> future) {
606 Ensure.not_null(future, "future == null");
607
608 synchronized (future) {
609 Ensure.same(future.target(), this, "future.target() == this");
610 if (future.isDone()) {
611 LockGrant<LockType> grant = future.get_now();
612 Ensure.is_true(grant.valid(), "!grant.valid()");
613 return grant;
614 }
615
616 future.cancelled();
617
618
619
620
621 Ensure.not_null(m_queue, "m_queue == null");
622 m_queue.dequeue(future);
623
624 LockGrantFuture<LockType> p = future.predecessor_future();
625 if (p != null) {
626 return p.target().cancel_chain(p);
627 } else {
628 return null;
629 }
630 }
631 }
632
633
634
635
636
637 private static class TryLockResult<LockType> {
638
639
640
641 private boolean m_granted;
642
643
644
645
646
647
648 private LockGrantFuture<LockType> m_successor;
649
650
651
652
653
654
655 TryLockResult(boolean granted, LockGrantFuture<LockType> successor) {
656 m_granted = granted;
657 m_successor = successor;
658 }
659
660
661
662
663
664 boolean granted() {
665 return m_granted;
666 }
667
668
669
670
671
672 LockGrantFuture<LockType> successor() {
673 return m_successor;
674 }
675 }
676 }