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.Collections;
23 import java.util.Deque;
24 import java.util.Map;
25 import java.util.concurrent.ConcurrentHashMap;
26 import java.util.concurrent.TimeUnit;
27
28 import org.eclipse.aether.named.NamedLock;
29 import org.eclipse.aether.named.NamedLockKey;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
32
33
34
35
36 public abstract class NamedLockSupport implements NamedLock {
37 protected final Logger logger = LoggerFactory.getLogger(getClass());
38
39 private final NamedLockKey key;
40
41 private final NamedLockFactorySupport factory;
42
43 private final ConcurrentHashMap<Thread, Deque<String>> diagnosticState;
44
45 public NamedLockSupport(final NamedLockKey key, final NamedLockFactorySupport factory) {
46 this.key = key;
47 this.factory = factory;
48 this.diagnosticState = factory.isDiagnosticEnabled() ? new ConcurrentHashMap<>() : null;
49 }
50
51 @Override
52 public NamedLockKey key() {
53 return key;
54 }
55
56 @Override
57 public boolean lockShared(long time, TimeUnit unit) throws InterruptedException {
58 Deque<String> steps = null;
59 if (diagnosticState != null) {
60 steps = diagnosticState.computeIfAbsent(Thread.currentThread(), k -> new ArrayDeque<>());
61 }
62 if (steps != null) {
63 steps.push("wait-shared");
64 }
65 boolean result = doLockShared(time, unit);
66 if (steps != null) {
67 steps.pop();
68 if (result) {
69 steps.push("shared");
70 }
71 }
72 return result;
73 }
74
75 protected abstract boolean doLockShared(long time, TimeUnit unit) throws InterruptedException;
76
77 @Override
78 public boolean lockExclusively(long time, TimeUnit unit) throws InterruptedException {
79 Deque<String> steps = null;
80 if (diagnosticState != null) {
81 steps = diagnosticState.computeIfAbsent(Thread.currentThread(), k -> new ArrayDeque<>());
82 }
83 if (steps != null) {
84 steps.push("wait-exclusive");
85 }
86 boolean result = doLockExclusively(time, unit);
87 if (steps != null) {
88 steps.pop();
89 if (result) {
90 steps.push("exclusive");
91 }
92 }
93 return result;
94 }
95
96 protected abstract boolean doLockExclusively(long time, TimeUnit unit) throws InterruptedException;
97
98 @Override
99 public void unlock() {
100 doUnlock();
101 if (diagnosticState != null) {
102 diagnosticState
103 .computeIfAbsent(Thread.currentThread(), k -> new ArrayDeque<>())
104 .pop();
105 }
106 }
107
108 protected abstract void doUnlock();
109
110 @Override
111 public final void close() {
112 doClose();
113 }
114
115 protected void doClose() {
116 factory.closeLock(key);
117 }
118
119
120
121
122
123
124 public Map<Thread, Deque<String>> diagnosticState() {
125 if (diagnosticState != null) {
126 return diagnosticState;
127 } else {
128 return Collections.emptyMap();
129 }
130 }
131
132 @Override
133 public String toString() {
134 return getClass().getSimpleName() + "{" + "key='" + key + '\'' + '}';
135 }
136 }