日記
今日書いたコード
困りを再現するテストを書いた · Gurrium/ReadGraphemeCluster@8d2f4ab · GitHub
感想
"ここ"がないとスタックする。FileHandle.bytes.unicodeScalarsをfor-awaitで待つとタスクがキャンセルされてもawaitで待ち続けるっぽい。(もしくは、awaitで待ち続けるのでタスクがキャンセルされない?)
1つのgrapheme clusterを入力したあとにタイムアウトするようにコードを書いているので、scalarを読むたびにタウムアウトする以上に待つ必要があると複数のscalarからなるgrapheme clusterを読めなくなる。
適当なAsyncSequenceを実装すると同じところでスタックしなかったのでFileHandle.bytes.unicodeScalarsの実装が悪いのかも。
actor Flag {
var content: Bool
init(content: Bool) {
self.content = content
}
func set(_ content: Bool) {
self.content = content
}
}
func test_cancellingTask() async throws {
let pipe = Pipe()
let handle = pipe.fileHandleForReading
let flag = Flag(content: true)
try pipe.fileHandleForWriting.write(contentsOf: Array("a".utf8))
let groupResult = try await withThrowingTaskGroup(of: Bool.self) { group in
group.addTask {
for try await scalar in handle.bytes.unicodeScalars {
// var it = handle.bytes.unicodeScalars.makeAsyncIterator()
// while let scalar = try await it.next() { // これでも同じ
print(scalar)
await flag.set(false)
try await Task.sleep(nanoseconds: 50_000) // ここ
}
return true
}
group.addTask {
while await flag.content {
try await Task.sleep(nanoseconds: 1_000)
}
print("timeout")
return false
}
let ret = try await group.next()!
group.cancelAll()
XCTAssertFalse(try XCTUnwrap(ret))
return ret
}
print("groupResult:", groupResult)
}
ところでFileHandle.bytes.characters*1が生えてたので終わり。あほくさ。