Fix UUIDIntModifiersMap nested race condition resulting in wrong final value

This commit is contained in:
DBotThePony 2024-05-31 16:36:48 +07:00
parent ff8d2aa5f3
commit 5fdfd9ee2c
Signed by: DBot
GPG Key ID: DCC23B5715498507

View File

@ -15,7 +15,10 @@ class UUIDIntModifiersMap(private val observer: (Int) -> Unit, private val backi
var value: Int = 0 var value: Int = 0
private set private set
private var ignoreRecompute = false
fun recompute() { fun recompute() {
if (ignoreRecompute) return
var value = 0 var value = 0
for (mapValue in backingMap.values) { for (mapValue in backingMap.values) {
@ -35,9 +38,15 @@ class UUIDIntModifiersMap(private val observer: (Int) -> Unit, private val backi
return false return false
} }
this.value += value - (old ?: 0) ignoreRecompute = true
observer.invoke(this.value)
return true try {
this.value += value - (old ?: 0)
observer.invoke(this.value)
return true
} finally {
ignoreRecompute = false
}
} }
operator fun get(key: UUID): Int? { operator fun get(key: UUID): Int? {
@ -53,17 +62,29 @@ class UUIDIntModifiersMap(private val observer: (Int) -> Unit, private val backi
return false return false
} }
val old = backingMap.remove(key) ?: return true ignoreRecompute = true
value -= old
return true try {
val old = backingMap.remove(key) ?: return true
value -= old
return true
} finally {
ignoreRecompute = false
}
} }
fun clear() { fun clear() {
backingMap.clear() ignoreRecompute = true
val old = this.value
this.value = 0 try {
if (old != this.value) { backingMap.clear()
observer.invoke(this.value) } finally {
ignoreRecompute = false
if (this.value != 0) {
this.value = 0
observer.invoke(0)
}
} }
} }
@ -83,19 +104,24 @@ class UUIDIntModifiersMap(private val observer: (Int) -> Unit, private val backi
nbt ?: return nbt ?: return
val old = this.value val old = this.value
this.value = 0 this.value = 0
ignoreRecompute = true
for (value in nbt) { try {
value as CompoundTag for (value in nbt) {
value as CompoundTag
if (value.contains("key", "value")) { if (value.contains("key", "value")) {
val int = value.getInt("value") val int = value.getInt("value")
backingMap.put(value.getUUID("key"), int) backingMap.put(value.getUUID("key"), int)
this.value += int this.value += int
}
} }
}
if (old != this.value) { if (old != this.value) {
observer.invoke(this.value) observer.invoke(this.value)
}
} finally {
ignoreRecompute = false
} }
} }
} }