Skip to content

Commit db6fdaf

Browse files
committed
Deadline
1 parent 17051a9 commit db6fdaf

File tree

1 file changed

+45
-0
lines changed

1 file changed

+45
-0
lines changed

Sources/TaskTimeout.swift

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,51 @@ private struct Transferring<Value>: Sendable {
8383
self.value = value
8484
}
8585
}
86+
87+
// ⚠️ Pattern that the region based isolation checker does not understand how to check. Please file a bug
88+
@available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *)
89+
public func withThrowingTimeout<T>(
90+
isolation: isolated (any Actor)? = #isolation,
91+
until instant: ContinuousClock.Instant,
92+
tolerance: ContinuousClock.Instant.Duration? = nil,
93+
body: () async throws -> sending T
94+
) async throws -> sending T {
95+
let transferringBody = { try await Transferring(body()) }
96+
typealias NonSendableClosure = () async throws -> Transferring<T>
97+
typealias SendableClosure = @Sendable () async throws -> Transferring<T>
98+
return try await withoutActuallyEscaping(transferringBody) {
99+
(_ fn: @escaping NonSendableClosure) async throws -> Transferring<T> in
100+
let sendableFn = unsafeBitCast(fn, to: SendableClosure.self)
101+
return try await _withThrowingTimeout(
102+
until: instant,
103+
tolerance: tolerance,
104+
body: sendableFn
105+
)
106+
}.value
107+
}
108+
109+
110+
@available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *)
111+
private func _withThrowingTimeout<T: Sendable>(
112+
isolation: isolated (any Actor)? = #isolation,
113+
until instant: ContinuousClock.Instant,
114+
tolerance: ContinuousClock.Instant.Duration? = nil,
115+
body: @Sendable @escaping () async throws -> T
116+
) async throws -> T {
117+
try await withThrowingTaskGroup(of: T.self) { group in
118+
group.addTask {
119+
try await body()
120+
}
121+
group.addTask {
122+
try await Task.sleep(until: instant, tolerance: tolerance, clock: ContinuousClock())
123+
throw TimeoutError(timeout: 1)
124+
}
125+
let success = try await group.next()!
126+
group.cancelAll()
127+
return success
128+
}
129+
}
130+
86131
#else
87132
public func withThrowingTimeout<T>(
88133
seconds: TimeInterval,

0 commit comments

Comments
 (0)