Skip to content

Commit 0cb2d59

Browse files
authored
Add support for IntLongMap (#18)
1 parent 2bef799 commit 0cb2d59

12 files changed

+777
-3
lines changed

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,14 @@ _Note_: currently the lib contains wrappers not for every primitive map. Feel fr
3232
<dependency>
3333
<groupId>com.trivago</groupId>
3434
<artifactId>fastutil-concurrent-wrapper</artifactId>
35-
<version>0.2.2</version>
35+
<version>0.2.3</version>
3636
</dependency>
3737
```
3838

3939
#### Gradle
4040

4141
```groovy
42-
implementation group: 'com.trivago', name: 'fastutil-concurrent-wrapper', version: '0.2.2'
42+
implementation group: 'com.trivago', name: 'fastutil-concurrent-wrapper', version: '0.2.3'
4343
```
4444

4545
## Usage
@@ -135,3 +135,4 @@ A-Z surname order
135135
- [@mchernyakov](https://github.com/mchernyakov)
136136
- [@erdoganf](https://github.com/erdoganf)
137137
- [@sarveswaran-m](https://github.com/sarveswaran-m)
138+
- [@p0nkr4t](https://github.com/p0nkr4t)

build.gradle

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ allprojects {
1616
}
1717

1818
group 'com.trivago'
19-
version '0.2.3-SNAPSHOT'
19+
version '0.2.4-SNAPSHOT'
2020

2121
mavenPublishing {
2222
pom {
@@ -46,6 +46,11 @@ mavenPublishing {
4646
name = "Sarveswaran Meenakshisundaram"
4747
url = "https://github.com/sarveswaran-m"
4848
}
49+
developer {
50+
id = "p0nkr4t"
51+
name = "Ivan Korovin"
52+
url = "https://github.com/p0nkr4t"
53+
}
4954
}
5055
scm {
5156
url = "https://github.com/trivago/fastutil-concurrent-wrapper"
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package com.trivago.fastutilconcurrentwrapper;
2+
3+
import com.trivago.fastutilconcurrentwrapper.map.ConcurrentBusyWaitingIntLongMap;
4+
import com.trivago.fastutilconcurrentwrapper.map.ConcurrentIntLongMap;
5+
6+
public final class ConcurrentIntLongMapBuilder {
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 long defaultValue = IntLongMap.DEFAULT_VALUE;
12+
13+
private ConcurrentIntLongMapBuilder() {
14+
15+
}
16+
17+
public static ConcurrentIntLongMapBuilder newBuilder() {
18+
return new ConcurrentIntLongMapBuilder();
19+
}
20+
21+
public ConcurrentIntLongMapBuilder withBuckets(int buckets) {
22+
this.buckets = buckets;
23+
return this;
24+
}
25+
26+
public ConcurrentIntLongMapBuilder withInitialCapacity(int initialCapacity) {
27+
this.initialCapacity = initialCapacity;
28+
return this;
29+
}
30+
31+
public ConcurrentIntLongMapBuilder withLoadFactor(float loadFactor) {
32+
this.loadFactor = loadFactor;
33+
return this;
34+
}
35+
36+
public ConcurrentIntLongMapBuilder withMode(MapMode mapMode) {
37+
this.mapMode = mapMode;
38+
return this;
39+
}
40+
41+
public ConcurrentIntLongMapBuilder withDefaultValue(long defaultValue) {
42+
this.defaultValue = defaultValue;
43+
return this;
44+
}
45+
46+
public IntLongMap build() {
47+
return mapMode.createMap(this);
48+
}
49+
50+
public enum MapMode {
51+
BUSY_WAITING {
52+
@Override
53+
IntLongMap createMap(ConcurrentIntLongMapBuilder builder) {
54+
return new ConcurrentBusyWaitingIntLongMap(
55+
builder.buckets,
56+
builder.initialCapacity,
57+
builder.loadFactor,
58+
builder.defaultValue);
59+
}
60+
},
61+
BLOCKING {
62+
@Override
63+
IntLongMap createMap(ConcurrentIntLongMapBuilder builder) {
64+
return new ConcurrentIntLongMap(
65+
builder.buckets,
66+
builder.initialCapacity,
67+
builder.loadFactor,
68+
builder.defaultValue);
69+
}
70+
};
71+
72+
abstract IntLongMap createMap(ConcurrentIntLongMapBuilder builder);
73+
}
74+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package com.trivago.fastutilconcurrentwrapper;
2+
3+
import it.unimi.dsi.fastutil.ints.Int2LongFunction;
4+
5+
import java.util.function.BiFunction;
6+
7+
public interface IntLongMap extends PrimitiveIntKeyMap {
8+
9+
long DEFAULT_VALUE = 0;
10+
11+
/**
12+
* @param key
13+
* @return 0 if the key is not present
14+
*/
15+
long get(int key);
16+
17+
long put(int key, long value);
18+
19+
long getDefaultValue();
20+
21+
long remove(int key);
22+
23+
boolean remove(int key, long value);
24+
25+
long computeIfAbsent(int key, Int2LongFunction mappingFunction);
26+
27+
long computeIfPresent(int key, BiFunction<Integer, Long, Long> mappingFunction);
28+
}
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
package com.trivago.fastutilconcurrentwrapper.map;
2+
3+
import com.trivago.fastutilconcurrentwrapper.IntLongMap;
4+
import com.trivago.fastutilconcurrentwrapper.wrapper.PrimitiveFastutilIntLongWrapper;
5+
import it.unimi.dsi.fastutil.ints.Int2LongFunction;
6+
7+
import java.util.concurrent.locks.Lock;
8+
import java.util.function.BiFunction;
9+
10+
public class ConcurrentBusyWaitingIntLongMap extends PrimitiveConcurrentMap implements IntLongMap {
11+
12+
private final IntLongMap[] maps;
13+
private final long defaultValue;
14+
15+
public ConcurrentBusyWaitingIntLongMap(int numBuckets,
16+
int initialCapacity,
17+
float loadFactor,
18+
long defaultValue) {
19+
super(numBuckets);
20+
21+
this.maps = new IntLongMap[numBuckets];
22+
this.defaultValue = defaultValue;
23+
24+
for (int i = 0; i < numBuckets; i++) {
25+
maps[i] = new PrimitiveFastutilIntLongWrapper(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(int 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 long get(int 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 long put(int key, long 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 long getDefaultValue() {
92+
return defaultValue;
93+
}
94+
95+
@Override
96+
public long remove(int 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(int key, long 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 long computeIfAbsent(int key, Int2LongFunction 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 long computeIfPresent(int key, BiFunction<Integer, Long, Long> 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+
}

0 commit comments

Comments
 (0)