vmgui now exits on exit

This commit is contained in:
minjaesong
2024-08-13 23:52:36 +09:00
parent 6325684610
commit adae75ab69
3 changed files with 75 additions and 57 deletions

View File

@@ -16,9 +16,9 @@ private class RenderRunnable(val playhead: AudioAdapter.Playhead) : Runnable {
private fun printdbg(msg: Any) { private fun printdbg(msg: Any) {
if (AudioAdapter.DBGPRN) println("[AudioAdapter] $msg") if (AudioAdapter.DBGPRN) println("[AudioAdapter] $msg")
} }
@Volatile private var exit = false
override fun run() { override fun run() {
while (!exit) { while (!Thread.currentThread().isInterrupted) {
try {
if (playhead.isPcmMode) { if (playhead.isPcmMode) {
val writeQueue = playhead.pcmQueue val writeQueue = playhead.pcmQueue
@@ -52,10 +52,10 @@ private class RenderRunnable(val playhead: AudioAdapter.Playhead) : Runnable {
Thread.sleep(1) Thread.sleep(1)
} }
playhead.audioDevice.dispose() catch (_: InterruptedException) {
Thread.currentThread().interrupt()
}
} }
fun stop() {
exit = true
} }
} }
@@ -63,17 +63,21 @@ private class WriteQueueingRunnable(val playhead: AudioAdapter.Playhead, val pcm
private fun printdbg(msg: Any) { private fun printdbg(msg: Any) {
if (AudioAdapter.DBGPRN) println("[AudioAdapter] $msg") if (AudioAdapter.DBGPRN) println("[AudioAdapter] $msg")
} }
@Volatile private var exit = false
override fun run() { override fun run() {
while (!exit) { while (!Thread.currentThread().isInterrupted) {
try {
playhead.let { playhead.let {
if (/*it.pcmQueue.size < it.getPcmQueueCapacity() &&*/ it.pcmUpload && it.pcmUploadLength > 0) { if (/*it.pcmQueue.size < it.getPcmQueueCapacity() &&*/ it.pcmUpload && it.pcmUploadLength > 0) {
printdbg("Downloading samples ${it.pcmUploadLength}") printdbg("Downloading samples ${it.pcmUploadLength}")
val samples = ByteArray(it.pcmUploadLength) val samples = ByteArray(it.pcmUploadLength)
UnsafeHelper.memcpyRaw(null, pcmBin.ptr, samples, UnsafeHelper.getArrayOffset(samples), it.pcmUploadLength.toLong()) UnsafeHelper.memcpyRaw(
null,
pcmBin.ptr,
samples,
UnsafeHelper.getArrayOffset(samples),
it.pcmUploadLength.toLong()
)
it.pcmQueue.addLast(samples) it.pcmQueue.addLast(samples)
it.pcmUploadLength = 0 it.pcmUploadLength = 0
@@ -88,9 +92,10 @@ private class WriteQueueingRunnable(val playhead: AudioAdapter.Playhead, val pcm
Thread.sleep(1) Thread.sleep(1)
} }
catch (_: InterruptedException) {
Thread.currentThread().interrupt()
}
} }
fun stop() {
exit = true
} }
} }
@@ -125,6 +130,9 @@ class AudioAdapter(val vm: VM) : PeriBase(VM.PERITYPE_SOUND) {
private val writeQueueingRunnables: Array<WriteQueueingRunnable> private val writeQueueingRunnables: Array<WriteQueueingRunnable>
private val writeQueueingThreads: Array<Thread> private val writeQueueingThreads: Array<Thread>
private val renderThreadGroup = ThreadGroup("AudioRenderThreadGroup")
private val writeQueueingGroup = ThreadGroup("AudioQriteQueueingThreadGroup")
private val threadExceptionHandler = Thread.UncaughtExceptionHandler { thread, throwable -> private val threadExceptionHandler = Thread.UncaughtExceptionHandler { thread, throwable ->
throwable.printStackTrace() throwable.printStackTrace()
} }
@@ -163,9 +171,9 @@ class AudioAdapter(val vm: VM) : PeriBase(VM.PERITYPE_SOUND) {
renderRunnables = Array(4) { RenderRunnable(playheads[it]) } renderRunnables = Array(4) { RenderRunnable(playheads[it]) }
renderThreads = Array(4) { Thread(renderRunnables[it], "AudioRenderHead${it+1}!$hash") } renderThreads = Array(4) { Thread(renderThreadGroup, renderRunnables[it], "AudioRenderHead${it+1}!$hash") }
writeQueueingRunnables = Array(4) { WriteQueueingRunnable(playheads[it], pcmBin) } writeQueueingRunnables = Array(4) { WriteQueueingRunnable(playheads[it], pcmBin) }
writeQueueingThreads = Array(4) { Thread(writeQueueingRunnables[it], "AudioQueueingHead${it+1}!$hash") } writeQueueingThreads = Array(4) { Thread(writeQueueingGroup, writeQueueingRunnables[it], "AudioQueueingHead${it+1}!$hash") }
// printdbg("AudioAdapter latency: ${audioDevice.latency}") // printdbg("AudioAdapter latency: ${audioDevice.latency}")
renderThreads.forEach { it.uncaughtExceptionHandler = threadExceptionHandler; it.start() } renderThreads.forEach { it.uncaughtExceptionHandler = threadExceptionHandler; it.start() }
@@ -266,18 +274,24 @@ class AudioAdapter(val vm: VM) : PeriBase(VM.PERITYPE_SOUND) {
} }
} }
private var disposed = false
override fun dispose() { override fun dispose() {
if (!disposed) {
disposed = true
System.err.println("Dispose AudioAdapter") System.err.println("Dispose AudioAdapter")
renderRunnables.forEach { it.stop() } renderThreadGroup.interrupt()
renderThreads.forEach { it.interrupt() } writeQueueingGroup.interrupt()
writeQueueingRunnables.forEach { it.stop() }
writeQueueingThreads.forEach { it.interrupt() }
playheads.forEach { it.dispose() } playheads.forEach { it.dispose() }
sampleBin.destroy() sampleBin.destroy()
pcmBin.destroy() pcmBin.destroy()
mediaFrameBin.destroy() mediaFrameBin.destroy()
mediaDecodedBin.destroy() mediaDecodedBin.destroy()
} }
else {
System.err.println("AudioAdapter already disposed")
}
}
override fun getVM(): VM { override fun getVM(): VM {
return vm return vm
@@ -435,7 +449,7 @@ class AudioAdapter(val vm: VM) : PeriBase(VM.PERITYPE_SOUND) {
fun dispose() { fun dispose() {
// audioDevice.dispose() is called by RenderRunnable.stop() // audioDevice.dispose() is called by RenderRunnable.stop()
System.err.println("AudioDevice dispose ${parent.renderThreads[index]}") System.err.println("AudioDevice dispose ${parent.renderThreads[index]}")
try { audioDevice.dispose() } catch (e: GdxRuntimeException) { println(" "+ e.message) } try { audioDevice.dispose() } catch (e: GdxRuntimeException) { System.err.println(" "+ e.message) }
} }
companion object { companion object {

View File

@@ -54,7 +54,7 @@ class VMEmuExecutableWrapper(val windowWidth: Int, val windowHeight: Int, var pa
// println("App Dispose") // println("App Dispose")
executable.dispose() executable.dispose()
SQTEX.dispose() SQTEX.dispose()
exitProcess(1) exitProcess(0)
} }
} }

View File

@@ -14,6 +14,7 @@ import java.util.*
import java.util.concurrent.atomic.AtomicBoolean import java.util.concurrent.atomic.AtomicBoolean
import java.util.concurrent.atomic.AtomicLong import java.util.concurrent.atomic.AtomicLong
import kotlin.coroutines.* import kotlin.coroutines.*
import kotlin.system.exitProcess
class EmulInstance( class EmulInstance(
@@ -320,6 +321,9 @@ class VMGUI(val loaderInfo: EmulInstance, val viewportWidth: Int, val viewportHe
crtShader.dispose() crtShader.dispose()
gpuFBO.dispose() gpuFBO.dispose()
vm.dispose() vm.dispose()
System.err.println("VM disposed: ${vm.id}")
exitProcess(0)
} }
companion object { companion object {