diff --git a/src/builder/resources/speiger/assets/collections/templates/maps/impl/concurrent/ConcurrentOpenHashMap.template b/src/builder/resources/speiger/assets/collections/templates/maps/impl/concurrent/ConcurrentOpenHashMap.template
index ec69e613..2d856550 100644
--- a/src/builder/resources/speiger/assets/collections/templates/maps/impl/concurrent/ConcurrentOpenHashMap.template
+++ b/src/builder/resources/speiger/assets/collections/templates/maps/impl/concurrent/ConcurrentOpenHashMap.template
@@ -4,7 +4,7 @@ import java.util.Arrays;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Objects;
-import java.util.concurrent.locks.ReentrantLock;
+import java.util.concurrent.locks.StampedLock;
import java.util.function.Consumer;
import java.util.function.BiFunction;
@@ -78,6 +78,8 @@ import speiger.src.collections.utils.HashUtil;
* A TypeSpecific ConcurrentHashMap implementation that is based on Guavas approach and backing array implementations.
* Like Guavas implementation this solution can be accessed by multiple threads, but it is not as flexible as Javas implementation.
* The concurrencyLevel decides how many pools exist, and each pool can be accessed by 1 thread for writing and as many threads for reading.
+ * Though it is ill adviced to iterate over the collection using the Iterator if the Map is written to. Keep that in mind.
+ *
*
* @Type(T)
* @ValueType(V)
@@ -607,10 +609,16 @@ public class CONCURRENT_HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY
public void forEach(Consumer super MAP.Entry KEY_VALUE_GENERIC_TYPE> action) {
for(int i = 0,m=segments.length;i= 0) return VALUE_EQUALS(entry.ENTRY_VALUE(), seg.values[index]);
+ long stamp = seg.readLock();
+ try {
+ int index = seg.findIndex(hash, key);
+ if(index >= 0) return VALUE_EQUALS(entry.ENTRY_VALUE(), seg.values[index]);
+ }
+ finally {
+ seg.unlockRead(stamp);
+ }
}
else {
Map.Entry, ?> entry = (Map.Entry, ?>)o;
int hash = getHashCode(entry.getKey());
Segment KEY_VALUE_GENERIC_TYPE seg = getSegment(hash);
- int index = seg.findIndex(hash, entry.getKey());
- if(index >= 0) return Objects.equals(entry.getValue(), VALUE_TO_OBJ(seg.values[index]));
+ long stamp = seg.readLock();
+ try {
+ int index = seg.findIndex(hash, entry.getKey());
+ if(index >= 0) return Objects.equals(entry.getValue(), VALUE_TO_OBJ(seg.values[index]));
+ }
+ finally {
+ seg.unlockRead(stamp);
+ }
}
}
return false;
@@ -865,10 +938,16 @@ public class CONCURRENT_HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY
Objects.requireNonNull(action);
for(int i = 0,m=segments.length;i= 0;
+ long stamp = readLock();
+ try {
+ return findIndex(hash, key) >= 0;
+ }
+ finally {
+ unlockRead(stamp);
+ }
}
#endif
@Deprecated
protected boolean containsKey(int hash, Object key) {
- return findIndex(hash, key) >= 0;
+ long stamp = readLock();
+ try {
+ return findIndex(hash, key) >= 0;
+ }
+ finally {
+ unlockRead(stamp);
+ }
}
#if !VALUE_OBJECT
protected boolean containsValue(VALUE_TYPE value) {
- int index = firstIndex;
- while(index != -1) {
- if(VALUE_EQUALS(values[index], value)) return true;
- index = (int)links[index];
+ long stamp = readLock();
+ try {
+ int index = firstIndex;
+ while(index != -1) {
+ if(VALUE_EQUALS(values[index], value)) return true;
+ index = (int)links[index];
+ }
+ return false;
+ }
+ finally {
+ unlockRead(stamp);
}
- return false;
}
#endif
@Deprecated
protected boolean containsValue(Object value) {
- int index = firstIndex;
- while(index != -1) {
+ long stamp = readLock();
+ try {
+ int index = firstIndex;
+ while(index != -1) {
#if VALUE_OBJECT
- if(VALUE_EQUALS(values[index], value)) return true;
+ if(VALUE_EQUALS(values[index], value)) return true;
#else
- if((value == null && values[index] == getDefaultReturnValue()) || EQUALS_VALUE_TYPE(values[index], value)) return true;
+ if((value == null && values[index] == getDefaultReturnValue()) || EQUALS_VALUE_TYPE(values[index], value)) return true;
#endif
- index = (int)links[index];
+ index = (int)links[index];
+ }
+ return false;
+ }
+ finally {
+ unlockRead(stamp);
}
- return false;
}
#if !TYPE_OBJECT
protected VALUE_TYPE get(int hash, KEY_TYPE key) {
- int slot = findIndex(hash, key);
- return slot < 0 ? getDefaultReturnValue() : values[slot];
+ long stamp = readLock();
+ try {
+ int slot = findIndex(hash, key);
+ return slot < 0 ? getDefaultReturnValue() : values[slot];
+ }
+ finally {
+ unlockRead(stamp);
+ }
}
#endif
protected VALUE_TYPE get(int hash, Object key) {
- int slot = findIndex(hash, key);
- return slot < 0 ? getDefaultReturnValue() : values[slot];
+ long stamp = readLock();
+ try {
+ int slot = findIndex(hash, key);
+ return slot < 0 ? getDefaultReturnValue() : values[slot];
+ }
+ finally {
+ unlockRead(stamp);
+ }
}
#if TYPE_OBJECT && VALUE_OBJECT
protected VALUE_TYPE getOrDefault(int hash, Object key, VALUE_TYPE defaultValue) {
- int slot = findIndex(hash, key);
- return slot < 0 ? defaultValue : values[slot];
+ long stamp = readLock();
+ try {
+ int slot = findIndex(hash, key);
+ return slot < 0 ? defaultValue : values[slot];
+ }
+ finally {
+ unlockRead(stamp);
+ }
}
#else
protected VALUE_TYPE getOrDefault(int hash, KEY_TYPE key, VALUE_TYPE defaultValue) {
- int slot = findIndex(hash, key);
- return slot < 0 ? defaultValue : values[slot];
+ long stamp = readLock();
+ try {
+ int slot = findIndex(hash, key);
+ return slot < 0 ? defaultValue : values[slot];
+ }
+ finally {
+ unlockRead(stamp);
+ }
}
#endif
protected void forEach(BI_CONSUMER KEY_VALUE_GENERIC_TYPE action) {
- int index = firstIndex;
- while(index != -1) {
- action.accept(keys[index], values[index]);
- index = (int)links[index];
+ long stamp = readLock();
+ try {
+ int index = firstIndex;
+ while(index != -1) {
+ action.accept(keys[index], values[index]);
+ index = (int)links[index];
+ }
+ }
+ finally {
+ unlockRead(stamp);
}
}
#if !TYPE_OBJECT
protected VALUE_TYPE remove(int hash, KEY_TYPE key) {
- lock();
+ long stamp = writeLock();
try {
int slot = findIndex(hash, key);
if(slot < 0) return getDefaultReturnValue();
return removeIndex(slot);
}
finally {
- unlock();
+ unlockWrite(stamp);
}
}
#endif
protected VALUE_TYPE removeOrDefault(int hash, KEY_TYPE key, VALUE_TYPE defaultValue) {
- lock();
+ long stamp = writeLock();
try {
int slot = findIndex(hash, key);
if(slot < 0) return defaultValue;
return removeIndex(slot);
}
finally {
- unlock();
+ unlockWrite(stamp);
}
}
protected CLASS_VALUE_TYPE remove(int hash, Object key) {
- lock();
+ long stamp = writeLock();
try {
int slot = findIndex(hash, key);
if(slot < 0) return VALUE_TO_OBJ(getDefaultReturnValue());
return VALUE_TO_OBJ(removeIndex(slot));
}
finally {
- unlock();
+ unlockWrite(stamp);
}
}
#if !TYPE_OBJECT || !VALUE_OBJECT
protected boolean remove(int hash, KEY_TYPE key, VALUE_TYPE value) {
- lock();
+ long stamp = writeLock();
try {
if(KEY_EQUALS_NULL(key)) {
if(containsNull && VALUE_EQUALS(value, values[nullIndex])) {
@@ -1767,37 +2016,44 @@ public class CONCURRENT_HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY
}
}
finally {
- unlock();
+ unlockWrite(stamp);
}
}
#endif
protected boolean remove(int hash, Object key, Object value) {
- if(key == null) {
- if(containsNull && EQUALS_VALUE_TYPE(values[nullIndex], value)) {
- removeNullIndex();
- return true;
+ long stamp = writeLock();
+ try
+ {
+ if(key == null) {
+ if(containsNull && EQUALS_VALUE_TYPE(values[nullIndex], value)) {
+ removeNullIndex();
+ return true;
+ }
+ return false;
}
- return false;
- }
- int pos = hash & mask;
- KEY_TYPE current = keys[pos];
- if(KEY_EQUALS_NULL(current)) return false;
- if(EQUALS_KEY_TYPE(current, key) && EQUALS_VALUE_TYPE(values[pos], value)) {
- removeIndex(pos);
- return true;
- }
- while(true) {
- if(KEY_EQUALS_NULL((current = keys[pos = (++pos & mask)]))) return false;
- else if(EQUALS_KEY_TYPE(current, key) && EQUALS_VALUE_TYPE(values[pos], value)){
+ int pos = hash & mask;
+ KEY_TYPE current = keys[pos];
+ if(KEY_EQUALS_NULL(current)) return false;
+ if(EQUALS_KEY_TYPE(current, key) && EQUALS_VALUE_TYPE(values[pos], value)) {
removeIndex(pos);
return true;
}
+ while(true) {
+ if(KEY_EQUALS_NULL((current = keys[pos = (++pos & mask)]))) return false;
+ else if(EQUALS_KEY_TYPE(current, key) && EQUALS_VALUE_TYPE(values[pos], value)){
+ removeIndex(pos);
+ return true;
+ }
+ }
+ }
+ finally {
+ unlockWrite(stamp);
}
}
protected boolean replace(int hash, KEY_TYPE key, VALUE_TYPE oldValue, VALUE_TYPE newValue) {
- lock();
+ long stamp = writeLock();
try {
int index = findIndex(hash, key);
if(index < 0 || values[index] != oldValue) return false;
@@ -1805,12 +2061,12 @@ public class CONCURRENT_HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY
return true;
}
finally {
- unlock();
+ unlockWrite(stamp);
}
}
protected VALUE_TYPE replace(int hash, KEY_TYPE key, VALUE_TYPE value) {
- lock();
+ long stamp = writeLock();
try {
int index = findIndex(hash, key);
if(index < 0) return getDefaultReturnValue();
@@ -1819,12 +2075,12 @@ public class CONCURRENT_HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY
return oldValue;
}
finally {
- unlock();
+ unlockWrite(stamp);
}
}
protected VALUE_TYPE compute(int hash, KEY_TYPE key, UNARY_OPERATOR KEY_VALUE_GENERIC_TYPE mappingFunction) {
- lock();
+ long stamp = writeLock();
try {
int index = findIndex(hash, key);
if(index < 0) {
@@ -1842,12 +2098,12 @@ public class CONCURRENT_HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY
return newValue;
}
finally {
- unlock();
+ unlockWrite(stamp);
}
}
protected VALUE_TYPE computeIfAbsent(int hash, KEY_TYPE key, FUNCTION KEY_VALUE_GENERIC_TYPE mappingFunction) {
- lock();
+ long stamp = writeLock();
try {
int index = findIndex(hash, key);
if(index < 0) {
@@ -1865,12 +2121,12 @@ public class CONCURRENT_HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY
return newValue;
}
finally {
- unlock();
+ unlockWrite(stamp);
}
}
protected VALUE_TYPE supplyIfAbsent(int hash, KEY_TYPE key, VALUE_SUPPLIER VALUE_GENERIC_TYPE valueProvider) {
- lock();
+ long stamp = writeLock();
try {
int index = findIndex(hash, key);
if(index < 0) {
@@ -1888,12 +2144,12 @@ public class CONCURRENT_HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY
return newValue;
}
finally {
- unlock();
+ unlockWrite(stamp);
}
}
protected VALUE_TYPE computeIfPresent(int hash, KEY_TYPE key, UNARY_OPERATOR KEY_VALUE_GENERIC_TYPE mappingFunction) {
- lock();
+ long stamp = writeLock();
try {
int index = findIndex(hash, key);
if(index < 0 || VALUE_EQUALS(values[index], getDefaultReturnValue())) return getDefaultReturnValue();
@@ -1906,12 +2162,12 @@ public class CONCURRENT_HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY
return newValue;
}
finally {
- unlock();
+ unlockWrite(stamp);
}
}
protected VALUE_TYPE merge(int hash, KEY_TYPE key, VALUE_TYPE value, VALUE_UNARY_OPERATOR VALUE_VALUE_GENERIC_TYPE mappingFunction) {
- lock();
+ long stamp = writeLock();
try {
int index = findIndex(hash, key);
VALUE_TYPE newValue = index < 0 || VALUE_EQUALS(values[index], getDefaultReturnValue()) ? value : mappingFunction.APPLY_VALUE(values[index], value);
@@ -1924,13 +2180,13 @@ public class CONCURRENT_HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY
return newValue;
}
finally {
- unlock();
+ unlockWrite(stamp);
}
}
protected void clear() {
if(size == 0) return;
- lock();
+ long stamp = writeLock();
try {
size = 0;
containsNull = false;
@@ -1940,14 +2196,14 @@ public class CONCURRENT_HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY
lastIndex = -1;
}
finally {
- unlock();
+ unlockWrite(stamp);
}
}
protected boolean trim(int size) {
int request = Math.max(minCapacity, HashUtil.nextPowerOfTwo((int)Math.ceil(size / loadFactor)));
if(request >= size || this.size > Math.min((int)Math.ceil(request * loadFactor), request - 1)) return false;
- lock();
+ long stamp = writeLock();
try {
try {
rehash(request);
@@ -1956,7 +2212,7 @@ public class CONCURRENT_HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY
return true;
}
finally {
- unlock();
+ unlockWrite(stamp);
}
}
@@ -1966,7 +2222,7 @@ public class CONCURRENT_HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY
clear();
return;
}
- lock();
+ long stamp = writeLock();
try {
if(nullIndex != -1) {
nullIndex = request;
@@ -1983,7 +2239,7 @@ public class CONCURRENT_HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY
containsNull = false;
}
finally {
- unlock();
+ unlockWrite(stamp);
}
}