Skip to content

Add support for IntLongMap #18

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,14 @@ _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.2</version>
<version>0.2.3</version>
</dependency>
```

#### Gradle

```groovy
implementation group: 'com.trivago', name: 'fastutil-concurrent-wrapper', version: '0.2.2'
implementation group: 'com.trivago', name: 'fastutil-concurrent-wrapper', version: '0.2.3'
```

## Usage
Expand Down Expand Up @@ -135,3 +135,4 @@ A-Z surname order
- [@mchernyakov](https://github.com/mchernyakov)
- [@erdoganf](https://github.com/erdoganf)
- [@sarveswaran-m](https://github.com/sarveswaran-m)
- [@p0nkr4t](https://github.com/p0nkr4t)
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.3-SNAPSHOT'
version '0.2.4-SNAPSHOT'

mavenPublishing {
pom {
Expand Down Expand Up @@ -46,6 +46,11 @@ mavenPublishing {
name = "Sarveswaran Meenakshisundaram"
url = "https://github.com/sarveswaran-m"
}
developer {
id = "p0nkr4t"
name = "Ivan Korovin"
url = "https://github.com/p0nkr4t"
}
}
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.ConcurrentBusyWaitingIntLongMap;
import com.trivago.fastutilconcurrentwrapper.map.ConcurrentIntLongMap;

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

private ConcurrentIntLongMapBuilder() {

}

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

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

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

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

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

public ConcurrentIntLongMapBuilder withDefaultValue(long defaultValue) {
this.defaultValue = defaultValue;
return this;
}

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

public enum MapMode {
BUSY_WAITING {
@Override
IntLongMap createMap(ConcurrentIntLongMapBuilder builder) {
return new ConcurrentBusyWaitingIntLongMap(
builder.buckets,
builder.initialCapacity,
builder.loadFactor,
builder.defaultValue);
}
},
BLOCKING {
@Override
IntLongMap createMap(ConcurrentIntLongMapBuilder builder) {
return new ConcurrentIntLongMap(
builder.buckets,
builder.initialCapacity,
builder.loadFactor,
builder.defaultValue);
}
};

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

import it.unimi.dsi.fastutil.ints.Int2LongFunction;

import java.util.function.BiFunction;

public interface IntLongMap extends PrimitiveIntKeyMap {

long DEFAULT_VALUE = 0;

/**
* @param key
* @return 0 if the key is not present
*/
long get(int key);

long put(int key, long value);

long getDefaultValue();

long remove(int key);

boolean remove(int key, long value);

long computeIfAbsent(int key, Int2LongFunction mappingFunction);

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

import com.trivago.fastutilconcurrentwrapper.IntLongMap;
import com.trivago.fastutilconcurrentwrapper.wrapper.PrimitiveFastutilIntLongWrapper;
import it.unimi.dsi.fastutil.ints.Int2LongFunction;

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

public class ConcurrentBusyWaitingIntLongMap extends PrimitiveConcurrentMap implements IntLongMap {

private final IntLongMap[] maps;
private final long defaultValue;

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

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

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

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

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

@Override
public boolean containsKey(int 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 long get(int 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 long put(int key, long 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 long getDefaultValue() {
return defaultValue;
}

@Override
public long remove(int 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(int key, long 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 long computeIfAbsent(int key, Int2LongFunction 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 long computeIfPresent(int key, BiFunction<Integer, Long, Long> 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