ぜのぜ

しりとりしようぜのぜのぜのぜ

609日目

日記

今日書いたコード

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