日記
今日書いたコード
困りを再現するテストを書いた · 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が生えてたので終わり。あほくさ。