1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.aether.named.support;
20
21 import java.util.ArrayDeque;
22 import java.util.Deque;
23 import java.util.concurrent.TimeUnit;
24 import java.util.concurrent.locks.ReadWriteLock;
25
26
27
28
29
30
31 public class ReadWriteLockNamedLock extends NamedLockSupport {
32 private enum Step {
33
34
35
36 SHARED,
37
38
39
40
41 EXCLUSIVE
42 }
43
44 private final ThreadLocal<Deque<Step>> threadSteps;
45
46 private final ReadWriteLock readWriteLock;
47
48 public ReadWriteLockNamedLock(
49 final String name, final NamedLockFactorySupport factory, final ReadWriteLock readWriteLock) {
50 super(name, factory);
51 this.threadSteps = ThreadLocal.withInitial(ArrayDeque::new);
52 this.readWriteLock = readWriteLock;
53 }
54
55 @Override
56 protected boolean doLockShared(final long time, final TimeUnit unit) throws InterruptedException {
57 Deque<Step> steps = threadSteps.get();
58 if (readWriteLock.readLock().tryLock(time, unit)) {
59 steps.push(Step.SHARED);
60 return true;
61 }
62 return false;
63 }
64
65 @Override
66 protected boolean doLockExclusively(final long time, final TimeUnit unit) throws InterruptedException {
67 Deque<Step> steps = threadSteps.get();
68 if (!steps.isEmpty()) {
69 if (!steps.contains(Step.EXCLUSIVE)) {
70 throw new LockUpgradeNotSupportedException(this);
71 }
72 }
73 if (readWriteLock.writeLock().tryLock(time, unit)) {
74 steps.push(Step.EXCLUSIVE);
75 return true;
76 }
77 return false;
78 }
79
80 @Override
81 protected void doUnlock() {
82 Deque<Step> steps = threadSteps.get();
83 if (steps.isEmpty()) {
84 throw new IllegalStateException("Wrong API usage: unlock without lock");
85 }
86 Step step = steps.pop();
87 if (Step.SHARED == step) {
88 readWriteLock.readLock().unlock();
89 } else if (Step.EXCLUSIVE == step) {
90 readWriteLock.writeLock().unlock();
91 }
92 }
93 }