Skip to content

Commit 9d38702

Browse files
committed
MP-11740 Introduce Long2ShortMap
1 parent ea714e6 commit 9d38702

11 files changed

Lines changed: 786 additions & 0 deletions
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package com.trivago.fastutilconcurrentwrapper;
2+
3+
import com.trivago.fastutilconcurrentwrapper.map.ConcurrentBusyWaitingLongShortMap;
4+
import com.trivago.fastutilconcurrentwrapper.map.ConcurrentLongShortMap;
5+
6+
public final class ConcurrentLongShortMapBuilder {
7+
private MapMode mapMode = MapMode.BLOCKING;
8+
private int buckets = 8;
9+
private int initialCapacity = 100_000;
10+
private float loadFactor = 0.8f;
11+
private short defaultValue = LongShortMap.DEFAULT_VALUE;
12+
13+
private ConcurrentLongShortMapBuilder() {
14+
15+
}
16+
17+
public static ConcurrentLongShortMapBuilder newBuilder() {
18+
return new ConcurrentLongShortMapBuilder();
19+
}
20+
21+
public ConcurrentLongShortMapBuilder withBuckets(int buckets) {
22+
this.buckets = buckets;
23+
return this;
24+
}
25+
26+
public ConcurrentLongShortMapBuilder withInitialCapacity(int initialCapacity) {
27+
this.initialCapacity = initialCapacity;
28+
return this;
29+
}
30+
31+
public ConcurrentLongShortMapBuilder withLoadFactor(float loadFactor) {
32+
this.loadFactor = loadFactor;
33+
return this;
34+
}
35+
36+
public ConcurrentLongShortMapBuilder withMode(MapMode mapMode) {
37+
this.mapMode = mapMode;
38+
return this;
39+
}
40+
41+
public ConcurrentLongShortMapBuilder withDefaultValue(short defaultValue) {
42+
this.defaultValue = defaultValue;
43+
return this;
44+
}
45+
46+
public LongShortMap build() {
47+
return mapMode.createMap(this);
48+
}
49+
50+
public enum MapMode {
51+
BUSY_WAITING {
52+
@Override
53+
LongShortMap createMap(ConcurrentLongShortMapBuilder builder) {
54+
return new ConcurrentBusyWaitingLongShortMap(
55+
builder.buckets,
56+
builder.initialCapacity,
57+
builder.loadFactor,
58+
builder.defaultValue);
59+
}
60+
},
61+
BLOCKING {
62+
@Override
63+
LongShortMap createMap(ConcurrentLongShortMapBuilder builder) {
64+
return new ConcurrentLongShortMap(
65+
builder.buckets,
66+
builder.initialCapacity,
67+
builder.loadFactor,
68+
builder.defaultValue);
69+
}
70+
};
71+
72+
abstract LongShortMap createMap(ConcurrentLongShortMapBuilder builder);
73+
}
74+
}
75+
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package com.trivago.fastutilconcurrentwrapper;
2+
3+
import it.unimi.dsi.fastutil.longs.Long2ShortFunction;
4+
5+
import java.util.function.BiFunction;
6+
7+
public interface LongShortMap extends PrimitiveLongKeyMap {
8+
9+
short DEFAULT_VALUE = 0;
10+
11+
/**
12+
* @param key key to get
13+
* @return configured LongShortMap.getDefaultValue(), if the key is not present
14+
*/
15+
short get(long key);
16+
17+
short put(long key, short value);
18+
19+
short getDefaultValue();
20+
21+
short remove(long key);
22+
23+
boolean remove(long key, short value);
24+
25+
short computeIfAbsent(long key, Long2ShortFunction mappingFunction);
26+
27+
short computeIfPresent(long key, BiFunction<Long, Short, Short> mappingFunction);
28+
}
29+
Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
package com.trivago.fastutilconcurrentwrapper.map;
2+
3+
import com.trivago.fastutilconcurrentwrapper.LongShortMap;
4+
import com.trivago.fastutilconcurrentwrapper.wrapper.PrimitiveFastutilLongShortWrapper;
5+
import it.unimi.dsi.fastutil.longs.Long2ShortFunction;
6+
7+
import java.util.concurrent.locks.Lock;
8+
import java.util.function.BiFunction;
9+
10+
public class ConcurrentBusyWaitingLongShortMap extends PrimitiveConcurrentMap implements LongShortMap {
11+
12+
private final LongShortMap[] maps;
13+
private final short defaultValue;
14+
15+
public ConcurrentBusyWaitingLongShortMap(int numBuckets,
16+
int initialCapacity,
17+
float loadFactor,
18+
short defaultValue) {
19+
super(numBuckets);
20+
21+
this.maps = new LongShortMap[numBuckets];
22+
this.defaultValue = defaultValue;
23+
24+
for (int i = 0; i < numBuckets; i++) {
25+
maps[i] = new PrimitiveFastutilLongShortWrapper(initialCapacity, loadFactor, defaultValue);
26+
}
27+
}
28+
29+
@Override
30+
public int size() {
31+
return super.size(maps);
32+
}
33+
34+
@Override
35+
public boolean isEmpty() {
36+
return super.isEmpty(maps);
37+
}
38+
39+
@Override
40+
public boolean containsKey(long key) {
41+
int bucket = getBucket(key);
42+
43+
Lock readLock = locks[bucket].readLock();
44+
45+
while (true) {
46+
if (readLock.tryLock()) {
47+
try {
48+
return maps[bucket].containsKey(key);
49+
} finally {
50+
readLock.unlock();
51+
}
52+
}
53+
}
54+
}
55+
56+
@Override
57+
public short get(long key) {
58+
int bucket = getBucket(key);
59+
60+
Lock readLock = locks[bucket].readLock();
61+
62+
while (true) {
63+
if (readLock.tryLock()) {
64+
try {
65+
return maps[bucket].get(key);
66+
} finally {
67+
readLock.unlock();
68+
}
69+
}
70+
}
71+
}
72+
73+
@Override
74+
public short put(long key, short value) {
75+
int bucket = getBucket(key);
76+
77+
Lock writeLock = locks[bucket].writeLock();
78+
79+
while (true) {
80+
if (writeLock.tryLock()) {
81+
try {
82+
return maps[bucket].put(key, value);
83+
} finally {
84+
writeLock.unlock();
85+
}
86+
}
87+
}
88+
}
89+
90+
@Override
91+
public short getDefaultValue() {
92+
return defaultValue;
93+
}
94+
95+
@Override
96+
public short remove(long key) {
97+
int bucket = getBucket(key);
98+
99+
Lock writeLock = locks[bucket].writeLock();
100+
101+
while (true) {
102+
if (writeLock.tryLock()) {
103+
try {
104+
return maps[bucket].remove(key);
105+
} finally {
106+
writeLock.unlock();
107+
}
108+
}
109+
}
110+
}
111+
112+
@Override
113+
public boolean remove(long key, short value) {
114+
int bucket = getBucket(key);
115+
116+
Lock writeLock = locks[bucket].writeLock();
117+
118+
while (true) {
119+
if (writeLock.tryLock()) {
120+
try {
121+
return maps[bucket].remove(key, value);
122+
} finally {
123+
writeLock.unlock();
124+
}
125+
}
126+
}
127+
}
128+
129+
@Override
130+
public short computeIfAbsent(long key, Long2ShortFunction mappingFunction) {
131+
int bucket = getBucket(key);
132+
133+
Lock writeLock = locks[bucket].writeLock();
134+
135+
while (true) {
136+
if (writeLock.tryLock()) {
137+
try {
138+
return maps[bucket].computeIfAbsent(key, mappingFunction);
139+
} finally {
140+
writeLock.unlock();
141+
}
142+
}
143+
}
144+
}
145+
146+
@Override
147+
public short computeIfPresent(long key, BiFunction<Long, Short, Short> mappingFunction) {
148+
int bucket = getBucket(key);
149+
150+
Lock writeLock = locks[bucket].writeLock();
151+
152+
while (true) {
153+
if (writeLock.tryLock()) {
154+
try {
155+
return maps[bucket].computeIfPresent(key, mappingFunction);
156+
} finally {
157+
writeLock.unlock();
158+
}
159+
}
160+
}
161+
}
162+
}
163+

0 commit comments

Comments
 (0)