Fix captured range bounds in launched for-loops
This commit is contained in:
parent
fbb1683ba3
commit
840cd32574
@ -2,70 +2,55 @@ import lyng.io.net
|
|||||||
|
|
||||||
val host = "127.0.0.1"
|
val host = "127.0.0.1"
|
||||||
val clientCount = 1000
|
val clientCount = 1000
|
||||||
val server: TcpServer = Net.tcpListen(0, host, clientCount, true) as TcpServer
|
val server = Net.tcpListen(0, host, clientCount, true) as TcpServer
|
||||||
val port: Int = server.localAddress().port
|
val port = server.localAddress().port
|
||||||
|
|
||||||
fun payloadFor(index: Int): String {
|
fun payloadFor(index: Int): String {
|
||||||
"$index:${Random.nextInt()}:${Random.nextInt()}"
|
"$index:${Random.nextInt()}:${Random.nextInt()}"
|
||||||
}
|
}
|
||||||
|
|
||||||
fun handleClient(client: TcpSocket): String {
|
fun handleClient(client: TcpSocket) {
|
||||||
try {
|
try {
|
||||||
val source = client.readLine()
|
val source = client.readLine()
|
||||||
if( source == null ) {
|
if( source != null ) {
|
||||||
return "server-eof"
|
client.writeUtf8("pong: $source\n")
|
||||||
|
client.flush()
|
||||||
}
|
}
|
||||||
val reply = "pong: $source"
|
|
||||||
client.writeUtf8(reply + "\n")
|
|
||||||
client.flush()
|
|
||||||
reply
|
|
||||||
} finally {
|
} finally {
|
||||||
client.close()
|
client.close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val serverJob: Deferred = launch {
|
launch {
|
||||||
var handlers: List<Deferred> = List()
|
|
||||||
try {
|
try {
|
||||||
for( i in 0..<1000 ) {
|
for( i in 0..<clientCount ) {
|
||||||
val client: TcpSocket = server.accept() as TcpSocket
|
val client = server.accept() as TcpSocket
|
||||||
handlers += launch {
|
launch {
|
||||||
handleClient(client)
|
handleClient(client)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
handlers.joinAll()
|
|
||||||
} finally {
|
} finally {
|
||||||
server.close()
|
server.close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val clientJobs: List<Deferred> = (0..<clientCount).map { index ->
|
val replies = (0..<clientCount).map { index ->
|
||||||
val payload = payloadFor(index)
|
val payload = payloadFor(index)
|
||||||
launch {
|
launch {
|
||||||
val socket: TcpSocket = Net.tcpConnect(host, port) as TcpSocket
|
val socket = Net.tcpConnect(host, port) as TcpSocket
|
||||||
try {
|
try {
|
||||||
socket.writeUtf8(payload + "\n")
|
socket.writeUtf8(payload + "\n")
|
||||||
socket.flush()
|
socket.flush()
|
||||||
val reply = socket.readLine()
|
val reply = socket.readLine()
|
||||||
if( reply == null ) {
|
assertEquals("pong: $payload", reply)
|
||||||
"client-eof:$payload"
|
reply
|
||||||
}
|
|
||||||
else {
|
|
||||||
assertEquals("pong: $payload", reply)
|
|
||||||
reply
|
|
||||||
}
|
|
||||||
} finally {
|
} finally {
|
||||||
socket.close()
|
socket.close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}.joinAll()
|
||||||
|
|
||||||
val replies = clientJobs.joinAll()
|
|
||||||
val serverReplies = serverJob.await() as List<Object>
|
|
||||||
|
|
||||||
assertEquals(clientCount, replies.size)
|
assertEquals(clientCount, replies.size)
|
||||||
assertEquals(clientCount, serverReplies.size)
|
|
||||||
assertEquals(replies.toSet, serverReplies.toSet)
|
|
||||||
|
|
||||||
val summary = "OK: $clientCount concurrent tcp clients"
|
val summary = "OK: $clientCount concurrent tcp clients"
|
||||||
println(summary)
|
println(summary)
|
||||||
|
|||||||
@ -7820,7 +7820,9 @@ class BytecodeCompiler(
|
|||||||
scopeSlotRefPosByKey[scopeKey] = ref.pos()
|
scopeSlotRefPosByKey[scopeKey] = ref.pos()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return resolved
|
if (resolved != null) return resolved
|
||||||
|
localSlotIndexByName[ref.name]?.let { return scopeSlotCount + it }
|
||||||
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun resolveLocalSlotByRefOrName(ref: LocalSlotRef): Int? {
|
private fun resolveLocalSlotByRefOrName(ref: LocalSlotRef): Int? {
|
||||||
@ -8672,6 +8674,11 @@ class BytecodeCompiler(
|
|||||||
collectLoopVarNamesRef(ref.targetRef)
|
collectLoopVarNamesRef(ref.targetRef)
|
||||||
collectLoopVarNamesRef(ref.indexRef)
|
collectLoopVarNamesRef(ref.indexRef)
|
||||||
}
|
}
|
||||||
|
is RangeRef -> {
|
||||||
|
ref.left?.let { collectLoopVarNamesRef(it) }
|
||||||
|
ref.right?.let { collectLoopVarNamesRef(it) }
|
||||||
|
ref.step?.let { collectLoopVarNamesRef(it) }
|
||||||
|
}
|
||||||
else -> {}
|
else -> {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -8798,6 +8805,11 @@ class BytecodeCompiler(
|
|||||||
collectScopeSlotsRef(ref.targetRef)
|
collectScopeSlotsRef(ref.targetRef)
|
||||||
collectScopeSlotsRef(ref.indexRef)
|
collectScopeSlotsRef(ref.indexRef)
|
||||||
}
|
}
|
||||||
|
is RangeRef -> {
|
||||||
|
ref.left?.let { collectScopeSlotsRef(it) }
|
||||||
|
ref.right?.let { collectScopeSlotsRef(it) }
|
||||||
|
ref.step?.let { collectScopeSlotsRef(it) }
|
||||||
|
}
|
||||||
is ClassOperatorRef -> {
|
is ClassOperatorRef -> {
|
||||||
collectScopeSlotsRef(ref.target)
|
collectScopeSlotsRef(ref.target)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -199,6 +199,25 @@ class TestCoroutines {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testLaunchCanUseCapturedRangeBoundInForLoop() = runTest {
|
||||||
|
eval(
|
||||||
|
"""
|
||||||
|
val count = 8
|
||||||
|
val outer = launch {
|
||||||
|
val jobs = []
|
||||||
|
for( i in 0..<count ) {
|
||||||
|
val x = i
|
||||||
|
jobs += launch { x }
|
||||||
|
}
|
||||||
|
jobs.joinAll()
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals([0,1,2,3,4,5,6,7], outer.await())
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testFlows() = runTest {
|
fun testFlows() = runTest {
|
||||||
eval("""
|
eval("""
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user