/
ONotThreadRWLockManager.java
105 lines (88 loc) · 2.51 KB
/
ONotThreadRWLockManager.java
1
2
3
4
5
6
7
8
9
10
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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
package com.orientechnologies.common.concur.lock;
import com.orientechnologies.common.exception.OException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class ONotThreadRWLockManager<T> implements OSimpleRWLockManager<T> {
private class LockGuard {
private int count;
private Condition condition;
private boolean shared;
public LockGuard(int count, Condition condition, boolean shared) {
this.count = count;
this.condition = condition;
this.shared = shared;
}
}
private final Lock lock = new ReentrantLock();
private final Map<T, LockGuard> map = new HashMap<>();
public ONotThreadRWLockManager() {
}
public void lock(T key, boolean shared, long timeout) {
lock.lock();
try {
try {
LockGuard c;
do {
c = map.get(key);
if (c != null) {
if (c.shared && shared) {
c.count++;
return;
} else {
if (timeout == 0) {
c.condition.await();
} else {
if (!c.condition.await(timeout, TimeUnit.MILLISECONDS)) {
throw new OLockException(String.format("Time out acquire lock for resource: '%s' ", key));
}
}
}
}
} while (c != null);
c = new LockGuard(1, lock.newCondition(), shared);
map.put(key, c);
} catch (InterruptedException e) {
throw OException.wrapException(new OInterruptedException("Interrupted Lock"), e);
}
} finally {
lock.unlock();
}
}
public void unlock(T key, boolean shared) {
lock.lock();
try {
LockGuard c = map.get(key);
assert c != null;
if (c.shared != shared) {
throw new OLockException("Impossible to release a not acquired lock");
}
c.count--;
if (c.count == 0) {
map.remove(key);
c.condition.signalAll();
}
} finally {
lock.unlock();
}
}
@Override
public void acquireReadLock(T key, long timeout) {
lock(key, true, timeout);
}
@Override
public void acquireWriteLock(T key, long timeout) {
lock(key, false, timeout);
}
@Override
public void releaseReadLock(T key) {
unlock(key, true);
}
@Override
public void releaseWriteLock(T key) {
unlock(key, false);
}
}