From aa84df400e65b9fa8ea2ded0b1d8ac7556ff7c16 Mon Sep 17 00:00:00 2001 From: Bixilon Date: Wed, 2 Jun 2021 22:11:36 +0200 Subject: [PATCH] custom SynchronizedMap --- .../gui/rendering/chunk/WorldRenderer.kt | 9 +- .../java/de/bixilon/minosoft/util/KUtil.kt | 9 +- .../java/de/bixilon/minosoft/util/Queue.kt | 1 + .../util/collections/SynchronizedMap.kt | 192 ++++++++++++++++++ 4 files changed, 203 insertions(+), 8 deletions(-) create mode 100644 src/main/java/de/bixilon/minosoft/util/collections/SynchronizedMap.kt diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/WorldRenderer.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/WorldRenderer.kt index def19190b..e18ab0545 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/WorldRenderer.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/WorldRenderer.kt @@ -47,6 +47,7 @@ import de.bixilon.minosoft.util.KUtil.synchronizedMapOf import de.bixilon.minosoft.util.KUtil.synchronizedSetOf import de.bixilon.minosoft.util.KUtil.toSynchronizedMap import de.bixilon.minosoft.util.MMath +import de.bixilon.minosoft.util.collections.SynchronizedMap import de.bixilon.minosoft.util.task.ThreadPoolRunnable import glm_.vec2.Vec2i import glm_.vec3.Vec3i @@ -61,10 +62,10 @@ class WorldRenderer( lateinit var chunkShader: Shader - val allChunkSections: MutableMap> = synchronizedMapOf() - val visibleChunks: MutableMap> = synchronizedMapOf() + val allChunkSections: SynchronizedMap> = synchronizedMapOf() + val visibleChunks: SynchronizedMap> = synchronizedMapOf() val queuedChunks: MutableSet = synchronizedSetOf() - private val preparationTasks: MutableMap> = synchronizedMapOf() + private val preparationTasks: SynchronizedMap> = synchronizedMapOf() private var allBlocks: Collection? = null @@ -428,7 +429,7 @@ class WorldRenderer( private fun onFrustumChange(frustum: Frustum) { visibleChunks.clear() for ((chunkLocation, indexMap) in allChunkSections.toSynchronizedMap()) { - val visibleIndexMap: MutableMap = synchronizedMapOf() + val visibleIndexMap: SynchronizedMap = synchronizedMapOf() for ((index, mesh) in indexMap.toSynchronizedMap()) { if (frustum.containsChunk(chunkLocation, mesh.lowestBlockHeight, mesh.highestBlockHeight)) { visibleIndexMap[index] = mesh diff --git a/src/main/java/de/bixilon/minosoft/util/KUtil.kt b/src/main/java/de/bixilon/minosoft/util/KUtil.kt index d000f35f1..e60f8c52a 100644 --- a/src/main/java/de/bixilon/minosoft/util/KUtil.kt +++ b/src/main/java/de/bixilon/minosoft/util/KUtil.kt @@ -17,6 +17,7 @@ import de.bixilon.minosoft.data.entities.entities.Entity import de.bixilon.minosoft.data.mappings.ResourceLocation import de.bixilon.minosoft.protocol.network.connection.PlayConnection import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition +import de.bixilon.minosoft.util.collections.SynchronizedMap import de.bixilon.minosoft.util.enum.AliasableEnum import sun.misc.Unsafe import java.util.* @@ -60,8 +61,8 @@ object KUtil { return ResourceLocation(this) } - fun synchronizedMapOf(vararg pairs: Pair): MutableMap { - return Collections.synchronizedMap(mutableMapOf(*pairs)) + fun synchronizedMapOf(vararg pairs: Pair): SynchronizedMap { + return SynchronizedMap(mutableMapOf(*pairs)) } fun synchronizedSetOf(vararg values: V): MutableSet { @@ -84,11 +85,11 @@ object KUtil { return synchronizedCopy { Collections.synchronizedMap(this.toMutableMap()) } } - fun List.toSynchronizedList(): MutableList { + fun Collection.toSynchronizedList(): MutableList { return synchronizedCopy { Collections.synchronizedList(this.toMutableList()) } } - fun Set.toSynchronizedSet(): MutableSet { + fun Collection.toSynchronizedSet(): MutableSet { return synchronizedCopy { Collections.synchronizedSet(this.toMutableSet()) } } diff --git a/src/main/java/de/bixilon/minosoft/util/Queue.kt b/src/main/java/de/bixilon/minosoft/util/Queue.kt index 905f75143..37a270a2e 100644 --- a/src/main/java/de/bixilon/minosoft/util/Queue.kt +++ b/src/main/java/de/bixilon/minosoft/util/Queue.kt @@ -19,6 +19,7 @@ import de.bixilon.minosoft.util.KUtil.toSynchronizedList class Queue { private val queue: MutableList = synchronizedListOf() + @Synchronized fun add(runnable: Runnable) { queue += runnable } diff --git a/src/main/java/de/bixilon/minosoft/util/collections/SynchronizedMap.kt b/src/main/java/de/bixilon/minosoft/util/collections/SynchronizedMap.kt new file mode 100644 index 000000000..39012907b --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/util/collections/SynchronizedMap.kt @@ -0,0 +1,192 @@ +/* + * Minosoft + * Copyright (C) 2021 Moritz Zwerger + * + * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program. If not, see . + * + * This software is not affiliated with Mojang AB, the original developer of Minecraft. + */ + +package de.bixilon.minosoft.util.collections + +import de.bixilon.minosoft.util.KUtil.toSynchronizedList +import de.bixilon.minosoft.util.KUtil.toSynchronizedSet +import java.util.function.BiConsumer +import java.util.function.BiFunction +import java.util.function.Function + +class SynchronizedMap( + private val original: MutableMap, +) : MutableMap { + private val lock = Object() + override val size: Int + get() = synchronized(lock) { original.size } + + override fun containsKey(key: K): Boolean { + synchronized(lock) { + return original.containsKey(key) + } + } + + override fun containsValue(value: V): Boolean { + synchronized(lock) { + return original.containsValue(value) + } + } + + override fun get(key: K): V? { + synchronized(lock) { + return original[key] + } + } + + override fun isEmpty(): Boolean { + synchronized(lock) { + return original.isEmpty() + } + } + + override val entries: MutableSet> + get() { + synchronized(lock) { + return original.entries.toSynchronizedSet() + } + } + override val keys: MutableSet + get() { + synchronized(lock) { + return original.keys.toSynchronizedSet() + } + } + override val values: MutableCollection + get() { + synchronized(lock) { + return original.values.toSynchronizedList() + } + } + + override fun clear() { + synchronized(lock) { + original.clear() + } + } + + override fun put(key: K, value: V): V? { + synchronized(lock) { + return original.put(key, value) + } + } + + override fun putAll(from: Map) { + synchronized(lock) { + return original.putAll(from) + } + } + + override fun remove(key: K): V? { + synchronized(lock) { + return original.remove(key) + } + } + + override fun hashCode(): Int { + synchronized(lock) { + return original.hashCode() + } + } + + override fun toString(): String { + synchronized(lock) { + return original.toString() + } + } + + override fun putIfAbsent(key: K, value: V): V? { + synchronized(lock) { + return original.putIfAbsent(key, value) + } + } + + override fun forEach(action: BiConsumer) { + synchronized(lock) { + return original.forEach(action) + } + } + + override fun getOrDefault(key: K, defaultValue: V): V { + synchronized(lock) { + return original.getOrDefault(key, defaultValue) + } + } + + fun getOrPut(key: K, defaultValue: () -> V): V { + synchronized(lock) { + var value = get(key) + return if (value == null) { + value = defaultValue() + put(key, value) + value + } else { + value + } + } + } + + override fun remove(key: K, value: V): Boolean { + synchronized(lock) { + return original.remove(key, value) + } + } + + override fun equals(other: Any?): Boolean { + synchronized(lock) { + return original == other + } + } + + override fun replaceAll(function: BiFunction) { + synchronized(lock) { + return original.replaceAll(function) + } + } + + override fun compute(key: K, remappingFunction: BiFunction): V? { + synchronized(lock) { + return original.compute(key, remappingFunction) + } + } + + override fun computeIfAbsent(key: K, mappingFunction: Function): V { + synchronized(lock) { + return original.computeIfAbsent(key, mappingFunction) + } + } + + override fun computeIfPresent(key: K, remappingFunction: BiFunction): V? { + synchronized(lock) { + return original.computeIfPresent(key, remappingFunction) + } + } + + override fun replace(key: K, value: V): V? { + synchronized(lock) { + return original.replace(key, value) + } + } + + override fun merge(key: K, value: V, remappingFunction: BiFunction): V? { + synchronized(lock) { + return original.merge(key, value, remappingFunction) + } + } + + override fun replace(key: K, oldValue: V, newValue: V): Boolean { + synchronized(lock) { + return original.replace(key, oldValue, newValue) + } + } +}