Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support for LongIntMap
Browse files Browse the repository at this point in the history
sarveswaran-m committed Oct 11, 2023
1 parent a665d67 commit fee9de5
Showing 5 changed files with 491 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package com.trivago.fastutilconcurrentwrapper;

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

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,29 @@
package com.trivago.fastutilconcurrentwrapper;

import it.unimi.dsi.fastutil.ints.Int2LongFunction;
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 0 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();
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
package com.trivago.fastutilconcurrentwrapper.map;

import com.trivago.fastutilconcurrentwrapper.IntIntMap;
import com.trivago.fastutilconcurrentwrapper.LongIntMap;
import com.trivago.fastutilconcurrentwrapper.wrapper.PrimitiveFastutilIntIntWrapper;
import com.trivago.fastutilconcurrentwrapper.wrapper.PrimitiveFastutilLongIntWrapper;
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
import it.unimi.dsi.fastutil.longs.Long2IntFunction;

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

public class ConcurrentLongIntMap extends PrimitiveConcurrentMap implements LongIntMap {

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

public ConcurrentLongIntMap(
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();
readLock.lock();
try {
return maps[bucket].containsKey(key);
} finally {
readLock.unlock();
}
}

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

int result;

Lock readLock = locks[bucket].readLock();
readLock.lock();
try {
result = maps[bucket].get(l);
} finally {
readLock.unlock();
}

return result;
}

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

int result;

Lock writeLock = locks[bucket].writeLock();
writeLock.lock();
try {
result = maps[bucket].put(key, value);
} finally {
writeLock.unlock();
}

return result;
}

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

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

Lock writeLock = locks[bucket].writeLock();
writeLock.lock();
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();
writeLock.lock();
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();
writeLock.lock();
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();
writeLock.lock();
try {
return maps[bucket].computeIfPresent(key, mappingFunction);
} finally {
writeLock.unlock();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package com.trivago.fastutilconcurrentwrapper.wrapper;

import com.trivago.fastutilconcurrentwrapper.LongIntMap;
import com.trivago.fastutilconcurrentwrapper.LongLongMap;
import it.unimi.dsi.fastutil.longs.Long2IntFunction;
import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap;
import it.unimi.dsi.fastutil.longs.Long2LongFunction;
import it.unimi.dsi.fastutil.longs.Long2LongOpenHashMap;

import java.util.function.BiFunction;

public class PrimitiveFastutilLongIntWrapper implements LongIntMap {
private final Long2IntOpenHashMap map;
private final int defaultValue;

public PrimitiveFastutilLongIntWrapper(int initialCapacity, float loadFactor) {
this(initialCapacity, loadFactor, LongIntMap.DEFAULT_VALUE);
}

public PrimitiveFastutilLongIntWrapper(int initialCapacity, float loadFactor, int defaultValue) {
this.defaultValue = defaultValue;
this.map = new Long2IntOpenHashMap(initialCapacity, loadFactor);
}

@Override
public int get(long key) {
return map.getOrDefault(key, defaultValue);
}

@Override
public int put(long key, int value) {
return map.put(key, value);
}

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

@Override
public int remove(long key) {
return map.remove(key);
}

@Override
public boolean remove(long key, int value) {
return map.remove(key, value);
}

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

@Override
public boolean containsKey(long key) {
return map.containsKey(key);
}

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

@Override
public int computeIfAbsent(long key, Long2IntFunction mappingFunction) {
return map.computeIfAbsent(key, mappingFunction);
}

@Override
public int computeIfPresent(long key, BiFunction<Long, Integer, Integer> mappingFunction) {
return map.computeIfPresent(key, mappingFunction);
}
}

0 comments on commit fee9de5

Please sign in to comment.