better multithreaded streams behavior

This commit is contained in:
2018-11-28 02:18:39 -05:00
parent 14eb1a87f7
commit 660a54eda5
8 changed files with 118 additions and 71 deletions

View File

@@ -1,52 +0,0 @@
package befide.befunge.b93
import befide.befunge.b93.state.*
import befide.befunge.core.*
import befide.befunge.core.util.readAll
import java.io.PipedReader
import java.io.PipedWriter
import java.util.*
class Interpreter93(stdinSrc: PipedWriter, stdoutDest: PipedReader)
: MutableInterpreter<Vec2, Data93, PointerMode>() {
override val ip = Pointer93()
override val funge = Funge93()
override val stack = Stack<Data93>()
override fun stackDefault() = Data93.ZERO
override val stdin: PipedReader = PipedReader(stdinSrc)
override val stdout: PipedWriter = PipedWriter(stdoutDest)
override val instructionSet = B93Instructions() + B93Extras()
}
fun main(args: Array<String>) {
val stdinSrc = PipedWriter()
val stdoutDest = PipedReader()
val int = Interpreter93(stdinSrc, stdoutDest)
int.funge.onChange += { (pos, from, to) ->
println("$pos from $from to $to")
}
int.onIpChange += { (_, to) ->
println("ip to ${to.pos}")
}
int.funge.src = """2>:3g" "-!v\ g30 <
|!`"O":+1_:.:03p>03g+:"O"`|
@ ^ p3\" ":<
2 234567890123456789012345678901234567890123456789012345678901234567890123456789"""
// int.funge.src = """fedc;ba9876;54321>:#._@"""
while (int.ip.mode != PointerMode.Terminated) {
int.step()
}
print(stdoutDest.readAll())
}

View File

@@ -45,23 +45,27 @@ class B93Instructions : InstructionSet<Vec2, Data93, PointerMode> {
'\\' -> pop(2).let { (b, a) -> push(b, a) }
'$' -> pop(1)
'.' -> pop(1).let { (n) -> stdout.write("${n.data} ") }
',' -> pop(1).let { (ch) -> stdout.write(ch.data.toChar().toString()) }
'.' -> pop(1).let { (n) -> stdout?.write("${n.data} ") }
',' -> pop(1).let { (ch) -> stdout?.write(ch.data.toChar().toString()) }
'p' -> pop(3).let { (y, x, n) -> funge[Vec2(x.data.toInt(), y.data.toInt())] = n }
'g' -> pop(2).let { (y, x) -> push(funge[Vec2(x.data.toInt(), y.data.toInt())]) }
'~' -> push(Data93(stdin.read().toLong()))
'~' -> push(Data93(stdin?.read()?.toLong() ?: 0L))
'&' -> {
val chars = generateSequence {
stdin.read().takeIf { it.toChar().isDigit() }
stdin?.read()?.toChar()?.takeIf { it.isDigit() }
}
val long = chars.joinToString("").toLong()
val long = chars.joinToString("") {
it.toString()
}.ifEmpty { "0" }.toLong()
push(Data93(long))
}
'@' -> mode = PointerMode.Terminated
' ' -> do move() while (next.char == ' ')
else -> return false
}
}

View File

@@ -0,0 +1,31 @@
package befide.befunge.b93
import befide.befunge.b93.state.*
import befide.befunge.core.*
import befide.befunge.core.util.readAll
import com.sun.imageio.spi.OutputStreamImageOutputStreamSpi
import java.io.*
import java.util.*
import kotlin.concurrent.thread
import kotlin.concurrent.timer
class Interpreter93(override var stdin: Reader? = null, override var stdout: Writer? = null)
: MutableInterpreter<Vec2, Data93, PointerMode>() {
override val ip = Pointer93()
override val funge = Funge93()
override val stack = Stack<Data93>()
override fun stackDefault() = Data93.ZERO
override val instructionSet = B93Instructions() + B93Extras()
override fun run(afterEach: () -> Unit) {
while (mode != PointerMode.Terminated) {
step()
afterEach()
stdout?.flush()
}
}
}

View File

@@ -0,0 +1,67 @@
package befide.befunge.b93
import befide.befunge.core.util.readAll
import java.io.PipedReader
import java.io.PipedWriter
import kotlin.concurrent.thread
import kotlin.concurrent.timer
fun runSync() {
val int = Interpreter93(System.`in`.reader(), System.out.writer())
// interactive calculator
int.funge.src = "\" :b ]%/*-+[ a\">:#,_&~~\$a3*0p& .@"
int.run {}
println()
}
fun runThreaded() {
val stdout = PipedReader()
val stdin = PipedWriter()
val int = Interpreter93(PipedReader(stdin), PipedWriter(stdout))
// incrementer
int.funge.src = ":.&+"
val input = timer("input", period = 50L) {
generateSequence {
System.`in`.read().takeUnless { it == -1 }
}.forEach(stdin::write)
}
val output = timer("output", period = 500L) {
print(stdout.readAll())
}
val stepper = thread {
int.run { Thread.sleep(50L) }
}
// input, output, and computation happen concurrently at this point.
stepper.join()
input.cancel()
output.cancel()
println(stdout.readAll())
int.stdout?.close()
stdout.close()
int.stdin?.close()
stdin.close()
}
fun main(args: Array<String>) {
println("synchronous:")
runSync()
println()
println("threaded:")
runThreaded()
}

View File

@@ -8,6 +8,8 @@ import befide.befunge.core.state.Pointer
import befide.befunge.core.util.Event
import java.io.PipedReader
import java.io.PipedWriter
import java.io.Reader
import java.io.Writer
interface Interpreter<V, D : Data, M : Enum<M>> {
val ip: Pointer<V, M>
@@ -20,14 +22,15 @@ interface Interpreter<V, D : Data, M : Enum<M>> {
val delta: V get() = ip.delta
val pos: V get() = ip.pos
val instr: D get() = funge[ip.pos]
val next: D get() = funge[funge.next(pos, delta)]
val onIpChange: Event<IpChange<V, M>>
val onStackChange: Event<StackChange<D>>
val stdin: PipedReader
val stdout: PipedWriter
var stdin: Reader?
val stdout: Writer?
fun step()
fun reset()
fun run(afterEach: () -> Unit)
}

View File

@@ -68,9 +68,4 @@ abstract class MutableInterpreter<V, D : Data, M : Enum<M>>
notifyStack(StackOp.Push) { stack.push(datum) }
}
}
override fun reset() {
stdin.readAll()
stdout.flush()
}
}

View File

@@ -1,6 +1,7 @@
package befide.befunge.core.util
import java.io.PipedReader
import java.io.Reader
import java.util.*
import kotlin.random.Random
@@ -19,10 +20,8 @@ infix fun Long.mod(o: Long): Long {
fun <T> List<T>.chooseOne(): T = this[Random.nextInt(size)]
fun PipedReader.readAll(): String = generateSequence {
if (ready()) read().toChar() else null
}.joinToString("")
fun <T> Boolean.orNull(block: () -> T): T? = if (this) block() else null
inline fun <reified T> Stack<T>.pop(n: Int): List<T> {
return (0 until n).map { pop() }
}
fun Reader.readAll(): String = generateSequence {
ready().orNull { read().toChar() }
}.joinToString("")