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  }