Skip to content

Instantly share code, notes, and snippets.

View NikolaiRuhe's full-sized avatar

Nikolai Ruhe NikolaiRuhe

View GitHub Profile
@NikolaiRuhe
NikolaiRuhe / CancellingContinuation.swift
Last active October 26, 2024 16:44
A continuation that resumes automatically when the suspended task is cancelled.
import os.lock
/// `CancellingContinuation` is built on top of `CheckedContinuation` and
/// provides some additional features. It can be used as a drop-in replacement,
/// providing a similar API.
///
/// ## Automatic cancellation
/// When the suspended task is cancelled the continuation is automatically
/// resumed with a `CancellationError`. After that, normally resuming the
/// continuation from client is silently ignored.
import XCTest
final class BarrierTests: XCTestCase {
func test() async {
let subsystem = Subsystem()
await withTaskGroup(of: Void.self) { group in
for index in 0 ..< 100 {
group.addTask { subsystem.performWork(id: index) }
}
actor A {
var iterator: AsyncStream<Void>.Iterator
init() {
iterator = AsyncStream<Void> { _ in }.makeAsyncIterator()
}
func f() async {
await iterator.next() // Cannot call mutating async function 'next()' on actor-isolated property 'iterator'
}
}
extension Binding where Value: MutableCollection, Value.Element: Identifiable {
subscript(_ id: Value.Element.ID) -> Binding<Value.Element> {
let index = wrappedValue.firstIndex { $0.id == id }
guard let index else {
fatalError("id not found: \(id)")
}
return self[index]
}
}
import XCTest
import SwiftUI
final class CaptureListTests: XCTestCase {
func testCaptureList() throws {
withBound("foo") { $boundValue in
print("value: \(boundValue), binding type: \(type(of: $boundValue))")
}
}
func testRequestCancellation() async throws {
// Used to synchronize unit test with request task.
let meeting = TaskMeeting()
// This request just waits for the unit test in its handler.
let sut = Request(responseHandler: { _ in
try? await meeting.rendezvous {}
})
// TaskMeeting
// (c) 2022, Nikolai Ruhe
/// A type that synchronizes progress of two tasks.
public final actor TaskMeeting: Sendable {
private var completion: CheckedContinuation<Void, Error>? = nil
/// This method synchronizes two tasks so that both perform the closure at
/// the same time. Both tasks need to call `rendezvous`.
///
/// A type that synchronizes progress of two tasks.
///
/// After setup, two tasks should eventually call the `join` function. The
/// first task will suspend until the second task arrives and calls `join` as
/// well. Both tasks resume normally after that.
public final actor TaskRendezvous: Sendable {
private var completion: CheckedContinuation<Void, Error>? = nil
/// Suspends until a second task calls `join()` on this instance.
public func join() async throws {
@NikolaiRuhe
NikolaiRuhe / LocatedValueTest.swift
Created May 22, 2022 18:41
Using a result builder to gather source code locations for unit testing.
// example unit test:
func testAscii() async throws {
locate {
"Celcius"
"Farenheit"
"Kelvin"
"yes?"
"no?"
"yes;no;cancel"
func testCSV() throws {
let plainField = Prefix { $0 != .init(ascii: ",") && $0 != .init(ascii: "|") && $0 != .init(ascii: "\n") }
let quotedField = Parse {
"|".utf8
Many {
OneOf {
Parse { "||".utf8 }.map { Substring("").utf8 }
Prefix { $0 != .init(ascii: "|") }
}