Skip to content

Commit

Permalink
Add support for longintmap (#14)
Browse files Browse the repository at this point in the history
* Add support for LongIntMap

* Update list of developers & bump up java version to 17

* Add unit-tests for IntMap implementations

* Add unit-tests for IntMap builder

* Add unit-tests for IntMap builder

* Fix code-convention violations

* Bump up to 0.2.2
  • Loading branch information
sarveswaran-m authored Oct 16, 2023
1 parent a665d67 commit 987fce3
Show file tree
Hide file tree
Showing 18 changed files with 967 additions and 130 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ _Note_: currently the lib contains wrappers not for every primitive map. Feel fr
<dependency>
<groupId>com.trivago</groupId>
<artifactId>fastutil-concurrent-wrapper</artifactId>
<version>0.2.1</version>
<version>0.2.2</version>
</dependency>
```

Expand Down
7 changes: 6 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ allprojects {
}

group 'com.trivago'
version '0.2.2-SNAPSHOT'
version '0.2.2'

mavenPublishing {
pom {
Expand All @@ -41,6 +41,11 @@ mavenPublishing {
name = "Fehim Erdogan"
url = "https://github.com/erdoganf"
}
developer {
id = "sarveswaran-m"
name = "Sarveswaran Meenakshisundaram"
url = "https://github.com/sarveswaran-m"
}
}
scm {
url = "https://github.com/trivago/fastutil-concurrent-wrapper"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package com.trivago.fastutilconcurrentwrapper;

import com.trivago.fastutilconcurrentwrapper.map.ConcurrentBusyWaitingLongIntMap;
import com.trivago.fastutilconcurrentwrapper.map.ConcurrentLongIntMap;

public final class ConcurrentLongIntMapBuilder {
private MapMode mapMode = MapMode.BLOCKING;
private int buckets = 8;
private int initialCapacity = 100_000;
private float loadFactor = 0.8f;
private int defaultValue = LongIntMap.DEFAULT_VALUE;

private ConcurrentLongIntMapBuilder() {

}

public static ConcurrentLongIntMapBuilder newBuilder() {
return new ConcurrentLongIntMapBuilder();
}

public ConcurrentLongIntMapBuilder withBuckets(int buckets) {
this.buckets = buckets;
return this;
}

public ConcurrentLongIntMapBuilder withInitialCapacity(int initialCapacity) {
this.initialCapacity = initialCapacity;
return this;
}

public ConcurrentLongIntMapBuilder withLoadFactor(float loadFactor) {
this.loadFactor = loadFactor;
return this;
}

public ConcurrentLongIntMapBuilder withMode(MapMode mapMode) {
this.mapMode = mapMode;
return this;
}

public ConcurrentLongIntMapBuilder withDefaultValue(int defaultValue) {
this.defaultValue = defaultValue;
return this;
}

public LongIntMap build() {
return mapMode.createMap(this);
}

public enum MapMode {
BUSY_WAITING {
@Override
LongIntMap createMap(ConcurrentLongIntMapBuilder builder) {
return new ConcurrentBusyWaitingLongIntMap(
builder.buckets,
builder.initialCapacity,
builder.loadFactor,
builder.defaultValue);
}
},
BLOCKING {
@Override
LongIntMap createMap(ConcurrentLongIntMapBuilder builder) {
return new ConcurrentLongIntMap(
builder.buckets,
builder.initialCapacity,
builder.loadFactor,
builder.defaultValue);
}
};

abstract LongIntMap createMap(ConcurrentLongIntMapBuilder builder);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.trivago.fastutilconcurrentwrapper;

import it.unimi.dsi.fastutil.longs.Long2IntFunction;

import java.util.function.BiFunction;

public interface LongIntMap extends PrimitiveLongKeyMap {

int DEFAULT_VALUE = 0;

/**
* @param key key to get
* @return configured LongIntMap.getDefaultValue(), if the key is not present
*/
int get(long key);

int put(long key, int value);

int getDefaultValue();

int remove(long key);

boolean remove(long key, int value);

int computeIfAbsent(long key, Long2IntFunction mappingFunction);

int computeIfPresent(long key, BiFunction<Long, Integer, Integer> mappingFunction);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
package com.trivago.fastutilconcurrentwrapper.map;

import com.trivago.fastutilconcurrentwrapper.LongIntMap;
import com.trivago.fastutilconcurrentwrapper.LongLongMap;
import com.trivago.fastutilconcurrentwrapper.wrapper.PrimitiveFastutilLongIntWrapper;
import com.trivago.fastutilconcurrentwrapper.wrapper.PrimitiveFastutilLongLongWrapper;
import it.unimi.dsi.fastutil.longs.Long2IntFunction;
import it.unimi.dsi.fastutil.longs.Long2LongFunction;

import java.util.concurrent.locks.Lock;
import java.util.function.BiFunction;

public class ConcurrentBusyWaitingLongIntMap extends PrimitiveConcurrentMap implements LongIntMap {

private final LongIntMap[] maps;
private final int defaultValue;

public ConcurrentBusyWaitingLongIntMap(int numBuckets,
int initialCapacity,
float loadFactor,
int defaultValue) {
super(numBuckets);

this.maps = new LongIntMap[numBuckets];
this.defaultValue = defaultValue;

for (int i = 0; i < numBuckets; i++) {
maps[i] = new PrimitiveFastutilLongIntWrapper(initialCapacity, loadFactor, defaultValue);
}
}

@Override
public int size() {
return super.size(maps);
}

@Override
public boolean isEmpty() {
return super.isEmpty(maps);
}

@Override
public boolean containsKey(long key) {
int bucket = getBucket(key);

Lock readLock = locks[bucket].readLock();

while (true) {
if (readLock.tryLock()) {
try {
return maps[bucket].containsKey(key);
} finally {
readLock.unlock();
}
}
}
}

@Override
public int get(long key) {
int bucket = getBucket(key);

Lock readLock = locks[bucket].readLock();

while (true) {
if (readLock.tryLock()) {
try {
return maps[bucket].get(key);
} finally {
readLock.unlock();
}
}
}
}

@Override
public int put(long key, int value) {
int bucket = getBucket(key);

Lock writeLock = locks[bucket].writeLock();

while (true) {
if (writeLock.tryLock()) {
try {
return maps[bucket].put(key, value);
} finally {
writeLock.unlock();
}
}
}
}

@Override
public int getDefaultValue() {
return defaultValue;
}

@Override
public int remove(long key) {
int bucket = getBucket(key);

Lock writeLock = locks[bucket].writeLock();

while (true) {
if (writeLock.tryLock()) {
try {
return maps[bucket].remove(key);
} finally {
writeLock.unlock();
}
}
}
}

@Override
public boolean remove(long key, int value) {
int bucket = getBucket(key);

Lock writeLock = locks[bucket].writeLock();

while (true) {
if (writeLock.tryLock()) {
try {
return maps[bucket].remove(key, value);
} finally {
writeLock.unlock();
}
}
}
}

@Override
public int computeIfAbsent(long key, Long2IntFunction mappingFunction) {
int bucket = getBucket(key);

Lock writeLock = locks[bucket].writeLock();

while (true) {
if (writeLock.tryLock()) {
try {
return maps[bucket].computeIfAbsent(key, mappingFunction);
} finally {
writeLock.unlock();
}
}
}
}

@Override
public int computeIfPresent(long key, BiFunction<Long, Integer, Integer> mappingFunction) {
int bucket = getBucket(key);

Lock writeLock = locks[bucket].writeLock();

while (true) {
if (writeLock.tryLock()) {
try {
return maps[bucket].computeIfPresent(key, mappingFunction);
} finally {
writeLock.unlock();
}
}
}
}
}
Loading

0 comments on commit 987fce3

Please sign in to comment.