From 0c6736ef90e8e91a6d86c25f74e68ce77f83fae1 Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Wed, 11 Oct 2023 21:56:22 +0700 Subject: [PATCH] Misc fixes --- .../kstarbound/api/IStarboundFileSystem.kt | 10 ++++++---- .../kstarbound/client/StarboundClient.kt | 20 ++++++++++++++++++- .../kstarbound/util/HashTableInterner.kt | 10 ++++++---- 3 files changed, 31 insertions(+), 9 deletions(-) diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/api/IStarboundFileSystem.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/api/IStarboundFileSystem.kt index 0d4fbadf..cd5e393e 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/api/IStarboundFileSystem.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/api/IStarboundFileSystem.kt @@ -1,13 +1,15 @@ package ru.dbotthepony.kstarbound.api import com.google.common.collect.ImmutableMap -import com.google.gson.JsonElement -import com.google.gson.JsonParser import com.google.gson.stream.JsonReader -import ru.dbotthepony.kstarbound.Starbound import ru.dbotthepony.kstarbound.io.StarboundPak import ru.dbotthepony.kstarbound.stream -import java.io.* +import java.io.BufferedInputStream +import java.io.File +import java.io.FileNotFoundException +import java.io.InputStream +import java.io.InputStreamReader +import java.io.Reader import java.nio.ByteBuffer import java.util.stream.Stream diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/client/StarboundClient.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/client/StarboundClient.kt index ac21dad0..175532d5 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/client/StarboundClient.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/client/StarboundClient.kt @@ -74,6 +74,8 @@ import java.nio.ByteOrder import java.time.Duration import java.util.* import java.util.concurrent.ForkJoinPool +import java.util.concurrent.ForkJoinWorkerThread +import java.util.concurrent.atomic.AtomicInteger import java.util.concurrent.locks.LockSupport import java.util.concurrent.locks.ReentrantLock import java.util.function.IntConsumer @@ -86,10 +88,26 @@ class StarboundClient : Closeable { val camera = Camera(this) val input = UserInput() val thread: Thread = Thread.currentThread() + private val threadCounter = AtomicInteger() // client specific executor which will accept tasks which involve probable // callback to foreground executor to initialize thread-unsafe data // In above case too many threads will introduce big congestion for resources, stalling entire workload; wasting cpu resources - val backgroundExecutor = ForkJoinPool(Runtime.getRuntime().availableProcessors().coerceAtMost(4)) + val backgroundExecutor = ForkJoinPool(Runtime.getRuntime().availableProcessors().coerceAtMost(4), { + object : ForkJoinWorkerThread(it) { + init { + name = "Background Executor for '${thread.name}'-${threadCounter.incrementAndGet()}" + } + + override fun onTermination(exception: Throwable?) { + super.onTermination(exception) + + if (exception != null) { + LOGGER.error("$this encountered an exception while executing task", exception) + } + } + } + }, null, false) + val foregroundExecutor = ManualExecutorService(thread) val capabilities: GLCapabilities diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/util/HashTableInterner.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/util/HashTableInterner.kt index fd1f6dc6..be56ad6d 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/util/HashTableInterner.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/util/HashTableInterner.kt @@ -7,6 +7,8 @@ import ru.dbotthepony.kstarbound.stream import java.lang.ref.ReferenceQueue import java.lang.ref.WeakReference import java.util.concurrent.locks.LockSupport +import java.util.concurrent.locks.ReentrantLock +import kotlin.concurrent.withLock // hand-rolled interner, which has similar performance to ConcurrentHashMap // (given there is no strong congestion, otherwise it performs somewhere above Caffeine interner), @@ -124,7 +126,7 @@ class HashTableInterner(private val segmentBits: Int) : Interner { actualSegmentBits = result } - private val locks: Array = Array(1.shl(segmentBits)) { Any() } + private val locks: Array = Array(1.shl(segmentBits)) { ReentrantLock() } private val segments: Array = Array(1.shl(segmentBits)) { Segment(32, locks[it]) } init { @@ -137,7 +139,7 @@ class HashTableInterner(private val segmentBits: Int) : Interner { // while this increase memory usage (linked list), this greatly // simplify logic, and make scanning a bit faster because we don't jump to neighbour nodes // (assuming past our neighbour there is no such key) - private inner class Segment(val size: Int, private val lock: Any) { + private inner class Segment(val size: Int, private val lock: ReentrantLock) { private val queue = ReferenceQueue() val mask = size - 1 @@ -183,7 +185,7 @@ class HashTableInterner(private val segmentBits: Int) : Interner { var p: Ref? = queue.poll() as Ref? ?: return 0 var any = 0 - synchronized(lock) { + lock.withLock { while (p != null) { check(remove(p!!)) { "Unable to remove null entry $p at hash ${hash(p!!)}" } p = queue.poll() as Ref? @@ -234,7 +236,7 @@ class HashTableInterner(private val segmentBits: Int) : Interner { val find = segment.search(sample) if (find != null) return find - synchronized(locks[segmentIndex]) { + locks[segmentIndex].withLock { segment = segments[segmentIndex] val find = segment.search(sample)