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 import org.eclipse.aether.named.NamedLockKey;
27
28
29
30
31
32
33 public class ReadWriteLockNamedLock extends NamedLockSupport {
34 private enum Step {
35
36
37
38 SHARED,
39
40
41
42
43 EXCLUSIVE
44 }
45
46 private final ThreadLocal<Deque<Step>> threadSteps;
47
48 private final ReadWriteLock readWriteLock;
49
50 public ReadWriteLockNamedLock(
51 final NamedLockKey key, final NamedLockFactorySupport factory, final ReadWriteLock readWriteLock) {
52 super(key, factory);
53 this.threadSteps = ThreadLocal.withInitial(ArrayDeque::new);
54 this.readWriteLock = readWriteLock;
55 }
56
57 @Override
58 protected boolean doLockShared(final long time, final TimeUnit unit) throws InterruptedException {
59 Deque<Step> steps = threadSteps.get();
60 if (readWriteLock.readLock().tryLock(time, unit)) {
61 steps.push(Step.SHARED);
62 return true;
63 }
64 return false;
65 }
66
67 @Override
68 protected boolean doLockExclusively(final long time, final TimeUnit unit) throws InterruptedException {
69 Deque<Step> steps = threadSteps.get();
70 if (!steps.isEmpty()) {
71 if (!steps.contains(Step.EXCLUSIVE)) {
72 throw new LockUpgradeNotSupportedException(this);
73 }
74 }
75 if (readWriteLock.writeLock().tryLock(time, unit)) {
76 steps.push(Step.EXCLUSIVE);
77 return true;
78 }
79 return false;
80 }
81
82 @Override
83 protected void doUnlock() {
84 Deque<Step> steps = threadSteps.get();
85 if (steps.isEmpty()) {
86 throw new IllegalStateException("Wrong API usage: unlock without lock");
87 }
88 Step step = steps.pop();
89 if (Step.SHARED == step) {
90 readWriteLock.readLock().unlock();
91 } else if (Step.EXCLUSIVE == step) {
92 readWriteLock.writeLock().unlock();
93 }
94 }
95 }