Skip to content

Commit 86a90ad

Browse files
author
Oleksandr Dzhychko
committed
fix(model-datastructure): make MapBasedStore thread safe
Make it thread safe by using a synchronized map. Missing thread safety is the suspected issue for such error messages ``` 2024-03-20 08:58:01,282 [ 48184] ERROR - #com.intellij.ide.plugins.PluginManager - Equal objects must have equal hashcodes. During rehashing, Trove discovered that the following two objects claim to be equal (as in java.lang.Object.equals()) but their hashCodes (or those calculated by your TObjectHashingStrategy) are not equal.This violates the general contract of java.lang.Object.hashCode(). See bullet point two in that method's documentation. object #1 =class java.lang.String id= 996201210 hashCode= -209607169 toString= sHB6r*02gLuXVEvI31E7v9ijDVL5VSdSO8F9OO-2z2CA; object #2 =class java.lang.String id= 1530156665 hashCode= -209607169 toString= sHB6r*02gLuXVEvI31E7v9ijDVL5VSdSO8F9OO-2z2CA [Warning] apparent concurrent modification of the key set. Size before and after rehash() do not match 81 vs 83 java.lang.IllegalArgumentException: Equal objects must have equal hashcodes. During rehashing, Trove discovered that the following two objects claim to be equal (as in java.lang.Object.equals()) but their hashCodes (or those calculated by your TObjectHashingStrategy) are not equal.This violates the general contract of java.lang.Object.hashCode(). See bullet point two in that method's documentation. object #1 =class java.lang.String id= 996201210 hashCode= -209607169 toString= sHB6r*02gLuXVEvI31E7v9ijDVL5VSdSO8F9OO-2z2CA; object #2 =class java.lang.String id= 1530156665 hashCode= -209607169 toString= sHB6r*02gLuXVEvI31E7v9ijDVL5VSdSO8F9OO-2z2CA [Warning] apparent concurrent modification of the key set. Size before and after rehash() do not match 81 vs 83 at gnu.trove.impl.hash.TObjectHash.buildObjectContractViolation(TObjectHash.java:464) at gnu.trove.impl.hash.TObjectHash.throwObjectContractViolation(TObjectHash.java:448) at gnu.trove.map.hash.THashMap.rehash(THashMap.java:403) at gnu.trove.impl.hash.THash.ensureCapacity(THash.java:175) at gnu.trove.map.hash.THashMap.putAll(THashMap.java:551) at org.modelix.model.persistent.MapBasedStore.putAll(MapBasedStore.kt:54) ```
1 parent bdeb7f0 commit 86a90ad

File tree

4 files changed

+14
-1
lines changed

4 files changed

+14
-1
lines changed

kotlin-utils/src/commonMain/kotlin/org/modelix/kotlin/utils/DataStructures.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,5 @@ package org.modelix.kotlin.utils
2929
* Therefore, the memory efficient maps are used sparingly for only the very big maps.
3030
*/
3131
expect fun <K, V> createMemoryEfficientMap(): MutableMap<K, V>
32+
33+
expect fun <K, V> MutableMap<K, V>.toSynchronizedMap(): MutableMap<K, V>

kotlin-utils/src/jsMain/kotlin/org/modelix/kotlin/utils/DataStructures.js.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,8 @@
1717
package org.modelix.kotlin.utils
1818

1919
actual fun <K, V> createMemoryEfficientMap(): MutableMap<K, V> = HashMap()
20+
21+
actual fun <K, V> MutableMap<K, V>.toSynchronizedMap(): MutableMap<K, V> {
22+
// Because JS is single-threaded, no extra measures are needed.
23+
return this
24+
}

kotlin-utils/src/jvmMain/kotlin/org/modelix/kotlin/utils/DataStructures.jvm.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,10 @@
1717
package org.modelix.kotlin.utils
1818

1919
import gnu.trove.map.hash.THashMap
20+
import java.util.Collections
2021

2122
actual fun <K, V> createMemoryEfficientMap(): MutableMap<K, V> = THashMap()
23+
24+
actual fun <K, V> MutableMap<K, V>.toSynchronizedMap(): MutableMap<K, V> {
25+
return Collections.synchronizedMap(this)
26+
}

model-datastructure/src/commonMain/kotlin/org/modelix/model/persistent/MapBasedStore.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package org.modelix.model.persistent
1717

1818
import org.modelix.kotlin.utils.createMemoryEfficientMap
19+
import org.modelix.kotlin.utils.toSynchronizedMap
1920
import org.modelix.model.IKeyListener
2021
import org.modelix.model.IKeyValueStore
2122
import org.modelix.model.lazy.IBulkQuery
@@ -26,7 +27,7 @@ import org.modelix.model.lazy.NonBulkQuery
2627
open class MapBaseStore : MapBasedStore()
2728

2829
open class MapBasedStore : IKeyValueStore {
29-
private val map: MutableMap<String?, String?> = createMemoryEfficientMap()
30+
private val map = createMemoryEfficientMap<String?, String?>().toSynchronizedMap()
3031
override fun get(key: String): String? {
3132
return map[key]
3233
}

0 commit comments

Comments
 (0)