fix
This commit is contained in:
parent
c63734960b
commit
37042fb3c1
@ -7,6 +7,7 @@ actor SDLPacketReaderService {
|
||||
}
|
||||
|
||||
typealias EventHandler = @Sendable (Event) async -> Void
|
||||
private typealias PacketReadResult = (packets: [Data], protocols: [NSNumber])?
|
||||
|
||||
private final class CancellationToken: @unchecked Sendable {
|
||||
private let lock = NSLock()
|
||||
@ -27,45 +28,6 @@ actor SDLPacketReaderService {
|
||||
}
|
||||
}
|
||||
|
||||
private final class PacketReadContinuation: @unchecked Sendable {
|
||||
typealias Result = (packets: [Data], protocols: [NSNumber])?
|
||||
|
||||
private let lock = NSLock()
|
||||
private var continuation: CheckedContinuation<Result, Never>?
|
||||
private var finished: Bool = false
|
||||
|
||||
func set(_ continuation: CheckedContinuation<Result, Never>) {
|
||||
lock.lock()
|
||||
if finished {
|
||||
lock.unlock()
|
||||
continuation.resume(returning: nil)
|
||||
return
|
||||
}
|
||||
|
||||
self.continuation = continuation
|
||||
lock.unlock()
|
||||
}
|
||||
|
||||
func resume(returning result: Result) {
|
||||
lock.lock()
|
||||
guard !finished else {
|
||||
lock.unlock()
|
||||
return
|
||||
}
|
||||
|
||||
finished = true
|
||||
let continuation = self.continuation
|
||||
self.continuation = nil
|
||||
lock.unlock()
|
||||
|
||||
continuation?.resume(returning: result)
|
||||
}
|
||||
|
||||
func cancel() {
|
||||
resume(returning: nil)
|
||||
}
|
||||
}
|
||||
|
||||
private let provider: NEPacketTunnelProvider
|
||||
private let onEvent: EventHandler
|
||||
private var readTask: Task<Void, Never>?
|
||||
@ -119,8 +81,8 @@ actor SDLPacketReaderService {
|
||||
readTask?.cancel()
|
||||
}
|
||||
|
||||
private static func readPackets(from provider: NEPacketTunnelProvider) async -> PacketReadContinuation.Result {
|
||||
let readContinuation = PacketReadContinuation()
|
||||
private static func readPackets(from provider: NEPacketTunnelProvider) async -> PacketReadResult {
|
||||
let readContinuation = OnceContinuation<PacketReadResult, Never>()
|
||||
|
||||
return await withTaskCancellationHandler {
|
||||
await withCheckedContinuation { continuation in
|
||||
@ -130,7 +92,7 @@ actor SDLPacketReaderService {
|
||||
}
|
||||
}
|
||||
} onCancel: {
|
||||
readContinuation.cancel()
|
||||
readContinuation.resume(returning: nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
56
Tun/Punchnet/OnceContinuation.swift
Normal file
56
Tun/Punchnet/OnceContinuation.swift
Normal file
@ -0,0 +1,56 @@
|
||||
//
|
||||
// OnceContinuation.swift
|
||||
// Tun
|
||||
//
|
||||
// Created by Codex on 2026/5/7.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
final class OnceContinuation<Value, Failure: Error>: @unchecked Sendable {
|
||||
private let lock = NSLock()
|
||||
private var continuation: CheckedContinuation<Value, Failure>?
|
||||
private var result: Result<Value, Failure>?
|
||||
|
||||
func set(_ continuation: CheckedContinuation<Value, Failure>) {
|
||||
lock.lock()
|
||||
if let result {
|
||||
lock.unlock()
|
||||
continuation.resume(with: result)
|
||||
return
|
||||
}
|
||||
|
||||
let hasPendingContinuation = self.continuation != nil
|
||||
if !hasPendingContinuation {
|
||||
self.continuation = continuation
|
||||
}
|
||||
lock.unlock()
|
||||
|
||||
if hasPendingContinuation {
|
||||
preconditionFailure("OnceContinuation can only store one pending continuation")
|
||||
}
|
||||
}
|
||||
|
||||
func resume(returning value: Value) {
|
||||
resume(with: .success(value))
|
||||
}
|
||||
|
||||
func resume(throwing error: Failure) {
|
||||
resume(with: .failure(error))
|
||||
}
|
||||
|
||||
func resume(with result: Result<Value, Failure>) {
|
||||
lock.lock()
|
||||
guard self.result == nil else {
|
||||
lock.unlock()
|
||||
return
|
||||
}
|
||||
|
||||
self.result = result
|
||||
let continuation = self.continuation
|
||||
self.continuation = nil
|
||||
lock.unlock()
|
||||
|
||||
continuation?.resume(with: result)
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user