[Enhancement]Improve swift concurrency task lifecycle - #861
Conversation
SDK Size
|
Public Interface+ public protocol Signposting
+ public actor SerialActorQueue
+
+ nonisolated public var unownedExecutor: UnownedSerialExecutor
+
+
+ public init(file: StaticString = #file)
+
+
+ @discardableResult public nonisolated func async(file: StaticString = #file,function: StaticString = #function,line: UInt = #line,@_inheritActorContext operation: @escaping Operation)-> QueueTask
+ @discardableResult public nonisolated func async(file: StaticString = #file,function: StaticString = #function,line: UInt = #line,@_inheritActorContext operation: @escaping @Sendable() async -> Void)-> QueueTask
+ @discardableResult public nonisolated func sync(@_inheritActorContext operation: @escaping @Sendable() async throws -> Output)async throws -> Output
+ @discardableResult public nonisolated func async(file: StaticString = #file,function: StaticString = #function,line: UInt = #line,@_inheritActorContext operation: sending @escaping @Sendable @isolated(any) () async throws (Failure) -> Void)-> QueueTask
+ @discardableResult public nonisolated func sync(@_inheritActorContext operation: sending @escaping @Sendable @isolated(any) () async throws (Failure) -> Output)async throws -> Output
+ public nonisolated func cancelAll()
+
+
+ public final class QueueTask: @unchecked Sendable
- public final class SerialActorQueue: Sendable
-
- public init()
-
-
- public func cancelAll()
- public func async(file: StaticString = #file,functionName: StaticString = #function,line: UInt = #line,_ block: @Sendable @escaping () async throws -> Void)
- public func sync(_ block: @Sendable @escaping () async throws -> T)async throws -> T
public final class CurrentDevice: @unchecked Sendable
+ case simulator
extension Task
- public func store(in disposableBag: DisposableBag,key: String = UUID().uuidString)
+ @discardableResult public init(disposableBag: DisposableBag,identifier: String = UUIDProviderKey.currentValue.get().uuidString,priority: TaskPriority? = nil,subsystem: LogSubsystem = .other,file: StaticString = #file,function: StaticString = #function,line: UInt = #line,@_inheritActorContext block: @Sendable @escaping () async -> Success)
+ @discardableResult public init(disposableBag: DisposableBag,identifier: String = UUIDProviderKey.currentValue.get().uuidString,priority: TaskPriority? = nil,subsystem: LogSubsystem = .other,file: StaticString = #file,function: StaticString = #function,line: UInt = #line,@_inheritActorContext block: @Sendable @escaping () async throws -> Success)
+
+
+ public func store(in disposableBag: DisposableBag,identifier: String = UUID().uuidString)
- public enum CallingState: Equatable, CustomStringConvertible
+ public enum CallingState: Equatable, CustomStringConvertible, Sendable
public final class DisposableBag: @unchecked Sendable
+ public func completed(_ key: String)
extension Publisher
- public func sinkTask(storeIn disposableBag: DisposableBag? = nil,identifier: String? = nil,receiveCompletion: @escaping (@Sendable(Subscribers.Completion<Failure>) -> Void) = { _ in },receiveValue: @escaping (@Sendable(Output) async throws -> Void))-> AnyCancellable
+ public func sinkTask(storeIn disposableBag: DisposableBag,identifier: String = UUIDProviderKey.currentValue.get().uuidString,file: StaticString = #file,function: StaticString = #function,line: UInt = #line,receiveCompletion: @escaping (@Sendable(Subscribers.Completion<Failure>) -> Void) = { _ in },receiveValue: @escaping (@Sendable(Output) async throws -> Void))-> AnyCancellable
- public func sinkTask(queue: SerialActorQueue,receiveCompletion: @escaping (@Sendable(Subscribers.Completion<Failure>) -> Void) = { _ in },receiveValue: @escaping (@Sendable(Output) async throws -> Void))-> AnyCancellable
+ public func sinkTask(queue: SerialActorQueue,file: StaticString = #file,function: StaticString = #function,line: UInt = #line,receiveCompletion: @escaping (@Sendable(Subscribers.Completion<Failure>) -> Void) = { _ in },receiveValue: @escaping (@Sendable(Output) async throws -> Void))-> AnyCancellable |
Public Interface+ extension OperationQueue
+
+ public func addTaskOperation(file: StaticString = #file,function: StaticString = #function,line: UInt = #line,operation: sending @escaping @Sendable @isolated(any) () async throws (Failure) -> Void)
+ public func addSynchronousTaskOperation(file: StaticString = #file,function: StaticString = #function,line: UInt = #line,timeout: TimeInterval = 10,operation: sending @escaping @Sendable @isolated(any) () async throws (Failure) -> Output)async throws -> Output
+ public protocol Signposting
- public final class SerialActorQueue: Sendable
-
- public init()
-
-
- public func cancelAll()
- public func async(file: StaticString = #file,functionName: StaticString = #function,line: UInt = #line,_ block: @Sendable @escaping () async throws -> Void)
- public func sync(_ block: @Sendable @escaping () async throws -> T)async throws -> T
- public enum CallingState: Equatable, CustomStringConvertible
+ public enum CallingState: Equatable, CustomStringConvertible, Sendable
extension Publisher
- public func sinkTask(storeIn disposableBag: DisposableBag? = nil,identifier: String? = nil,receiveCompletion: @escaping (@Sendable(Subscribers.Completion<Failure>) -> Void) = { _ in },receiveValue: @escaping (@Sendable(Output) async throws -> Void))-> AnyCancellable
+ public func sinkTask(storeIn disposableBag: DisposableBag,identifier: String = UUIDProviderKey.currentValue.get().uuidString,file: StaticString = #file,function: StaticString = #function,line: UInt = #line,receiveCompletion: @escaping (@Sendable(Subscribers.Completion<Failure>) -> Void) = { _ in },receiveValue: @escaping (@Sendable(Output) async throws -> Void))-> AnyCancellable
- public func sinkTask(queue: SerialActorQueue,receiveCompletion: @escaping (@Sendable(Subscribers.Completion<Failure>) -> Void) = { _ in },receiveValue: @escaping (@Sendable(Output) async throws -> Void))-> AnyCancellable
public final class CurrentDevice: @unchecked Sendable
+ case simulator
public final class DisposableBag: @unchecked Sendable
+ public func completed(_ key: String)
extension Task
- public func store(in disposableBag: DisposableBag,key: String = UUID().uuidString)
+ @discardableResult public init(disposableBag: DisposableBag,identifier: String = UUIDProviderKey.currentValue.get().uuidString,priority: TaskPriority? = nil,subsystem: LogSubsystem = .other,file: StaticString = #file,function: StaticString = #function,line: UInt = #line,@_inheritActorContext block: @Sendable @escaping () async -> Success)
+ @discardableResult public init(disposableBag: DisposableBag,identifier: String = UUIDProviderKey.currentValue.get().uuidString,priority: TaskPriority? = nil,subsystem: LogSubsystem = .other,file: StaticString = #file,function: StaticString = #function,line: UInt = #line,@_inheritActorContext block: @Sendable @escaping () async throws -> Success)
+
+
+ public func store(in disposableBag: DisposableBag,identifier: String = UUID().uuidString) |
Public Interface+ extension OperationQueue
+
+ public func addTaskOperation(file: StaticString = #file,function: StaticString = #function,line: UInt = #line,operation: sending @escaping @Sendable @isolated(any) () async throws (Failure) -> Void)
+ public func addSynchronousTaskOperation(file: StaticString = #file,function: StaticString = #function,line: UInt = #line,timeout: TimeInterval = 10,operation: sending @escaping @Sendable @isolated(any) () async throws (Failure) -> Output)async throws -> Output
+ public protocol Signposting
- public final class SerialActorQueue: Sendable
-
- public init()
-
-
- public func cancelAll()
- public func async(file: StaticString = #file,functionName: StaticString = #function,line: UInt = #line,_ block: @Sendable @escaping () async throws -> Void)
- public func sync(_ block: @Sendable @escaping () async throws -> T)async throws -> T
- public enum CallingState: Equatable, CustomStringConvertible
+ public enum CallingState: Equatable, CustomStringConvertible, Sendable
public final class DisposableBag: @unchecked Sendable
+ public func completed(_ key: String)
public final class CurrentDevice: @unchecked Sendable
+ case simulator
extension Publisher
- public func sinkTask(storeIn disposableBag: DisposableBag? = nil,identifier: String? = nil,receiveCompletion: @escaping (@Sendable(Subscribers.Completion<Failure>) -> Void) = { _ in },receiveValue: @escaping (@Sendable(Output) async throws -> Void))-> AnyCancellable
+ public func sinkTask(storeIn disposableBag: DisposableBag,identifier: String = UUIDProviderKey.currentValue.get().uuidString,file: StaticString = #file,function: StaticString = #function,line: UInt = #line,receiveCompletion: @escaping (@Sendable(Subscribers.Completion<Failure>) -> Void) = { _ in },receiveValue: @escaping (@Sendable(Output) async throws -> Void))-> AnyCancellable
- public func sinkTask(queue: SerialActorQueue,receiveCompletion: @escaping (@Sendable(Subscribers.Completion<Failure>) -> Void) = { _ in },receiveValue: @escaping (@Sendable(Output) async throws -> Void))-> AnyCancellable
extension Task
- public func store(in disposableBag: DisposableBag,key: String = UUID().uuidString)
+ @discardableResult public init(disposableBag: DisposableBag,identifier: String = UUIDProviderKey.currentValue.get().uuidString,priority: TaskPriority? = nil,subsystem: LogSubsystem = .other,file: StaticString = #file,function: StaticString = #function,line: UInt = #line,@_inheritActorContext block: @Sendable @escaping () async -> Success)
+ @discardableResult public init(disposableBag: DisposableBag,identifier: String = UUIDProviderKey.currentValue.get().uuidString,priority: TaskPriority? = nil,subsystem: LogSubsystem = .other,file: StaticString = #file,function: StaticString = #function,line: UInt = #line,@_inheritActorContext block: @Sendable @escaping () async throws -> Success)
+
+
+ public func store(in disposableBag: DisposableBag,identifier: String = UUID().uuidString) |
Public Interface+ public protocol Signposting
+ extension OperationQueue
+
+ public func addTaskOperation(file: StaticString = #file,function: StaticString = #function,line: UInt = #line,operation: sending @escaping @Sendable @isolated(any) () async throws (Failure) -> Void)
+ public func addSynchronousTaskOperation(file: StaticString = #file,function: StaticString = #function,line: UInt = #line,timeout: TimeInterval = 10,operation: sending @escaping @Sendable @isolated(any) () async throws (Failure) -> Output)async throws -> Output
- public final class SerialActorQueue: Sendable
-
- public init()
-
-
- public func cancelAll()
- public func async(file: StaticString = #file,functionName: StaticString = #function,line: UInt = #line,_ block: @Sendable @escaping () async throws -> Void)
- public func sync(_ block: @Sendable @escaping () async throws -> T)async throws -> T
- public enum CallingState: Equatable, CustomStringConvertible
+ public enum CallingState: Equatable, CustomStringConvertible, Sendable
public final class DisposableBag: @unchecked Sendable
+ public func completed(_ key: String)
extension Task
- public func store(in disposableBag: DisposableBag,key: String = UUID().uuidString)
+ @discardableResult public init(disposableBag: DisposableBag,identifier: String = UUIDProviderKey.currentValue.get().uuidString,priority: TaskPriority? = nil,subsystem: LogSubsystem = .other,file: StaticString = #file,function: StaticString = #function,line: UInt = #line,@_inheritActorContext block: @Sendable @escaping () async -> Success)
+ @discardableResult public init(disposableBag: DisposableBag,identifier: String = UUIDProviderKey.currentValue.get().uuidString,priority: TaskPriority? = nil,subsystem: LogSubsystem = .other,file: StaticString = #file,function: StaticString = #function,line: UInt = #line,@_inheritActorContext block: @Sendable @escaping () async throws -> Success)
+
+
+ public func store(in disposableBag: DisposableBag,identifier: String = UUID().uuidString)
public final class CurrentDevice: @unchecked Sendable
+ case simulator
extension Publisher
- public func sinkTask(storeIn disposableBag: DisposableBag? = nil,identifier: String? = nil,receiveCompletion: @escaping (@Sendable(Subscribers.Completion<Failure>) -> Void) = { _ in },receiveValue: @escaping (@Sendable(Output) async throws -> Void))-> AnyCancellable
+ public func sinkTask(storeIn disposableBag: DisposableBag,identifier: String = UUIDProviderKey.currentValue.get().uuidString,file: StaticString = #file,function: StaticString = #function,line: UInt = #line,receiveCompletion: @escaping (@Sendable(Subscribers.Completion<Failure>) -> Void) = { _ in },receiveValue: @escaping (@Sendable(Output) async throws -> Void))-> AnyCancellable
- public func sinkTask(queue: SerialActorQueue,receiveCompletion: @escaping (@Sendable(Subscribers.Completion<Failure>) -> Void) = { _ in },receiveValue: @escaping (@Sendable(Output) async throws -> Void))-> AnyCancellable |
martinmitrevski
left a comment
There was a problem hiding this comment.
Impressive work 👏 Added a few small comments and we should check the failed checks before merging.
|
|
||
| /// Deinitializes the instance, deallocating the unfair lock. | ||
| deinit { | ||
| lock.deinitialize(count: 1) |
There was a problem hiding this comment.
Because the allocated capacity was 1, so we are only deinitializing what we allocated intially.
There was a problem hiding this comment.
Yes, but the problem is what if we change something in the future - we always have to remember to update this as well?
| /// Cleans up resources when the instance is being deallocated. | ||
| deinit { | ||
| peerConnection.transceivers.forEach { $0.stopInternal() } | ||
| // swiftlint:disable discourage_task_init |
There was a problem hiding this comment.
maybe we're too strict with this rule?
There was a problem hiding this comment.
That's actually intended. The plan is to avoid having Tasks that there is no way to control their lifecycle (e.g. cancel them). Do you think we should relax it?
There was a problem hiding this comment.
I think so - we should have this only in the core parts. What do you think?
2cd6cc1 to
6a6c124
Compare
Public Interface+ extension OperationQueue
+
+ public func addTaskOperation(file: StaticString = #file,function: StaticString = #function,line: UInt = #line,operation: sending @escaping @Sendable @isolated(any) () async throws (Failure) -> Void)
+ public func addSynchronousTaskOperation(file: StaticString = #file,function: StaticString = #function,line: UInt = #line,timeout: TimeInterval = 5,operation: sending @escaping @Sendable @isolated(any) () async throws (Failure) -> Output)async throws -> Output
+ public protocol Signposting
- public final class SerialActorQueue: Sendable
-
- public init()
-
-
- public func cancelAll()
- public func async(file: StaticString = #file,functionName: StaticString = #function,line: UInt = #line,_ block: @Sendable @escaping () async throws -> Void)
- public func sync(_ block: @Sendable @escaping () async throws -> T)async throws -> T
- public enum CallingState: Equatable, CustomStringConvertible
+ public enum CallingState: Equatable, CustomStringConvertible, Sendable
public final class CurrentDevice: @unchecked Sendable
+ case simulator
public final class DisposableBag: @unchecked Sendable
+ public func completed(_ key: String)
extension Publisher
- public func sinkTask(storeIn disposableBag: DisposableBag? = nil,identifier: String? = nil,receiveCompletion: @escaping (@Sendable(Subscribers.Completion<Failure>) -> Void) = { _ in },receiveValue: @escaping (@Sendable(Output) async throws -> Void))-> AnyCancellable
+ public func sinkTask(storeIn disposableBag: DisposableBag,identifier: String = UUIDProviderKey.currentValue.get().uuidString,file: StaticString = #file,function: StaticString = #function,line: UInt = #line,receiveCompletion: @escaping (@Sendable(Subscribers.Completion<Failure>) -> Void) = { _ in },receiveValue: @escaping (@Sendable(Output) async throws -> Void))-> AnyCancellable
- public func sinkTask(queue: SerialActorQueue,receiveCompletion: @escaping (@Sendable(Subscribers.Completion<Failure>) -> Void) = { _ in },receiveValue: @escaping (@Sendable(Output) async throws -> Void))-> AnyCancellable
extension Task
- public func store(in disposableBag: DisposableBag,key: String = UUID().uuidString)
+ @discardableResult public init(disposableBag: DisposableBag,identifier: String = UUIDProviderKey.currentValue.get().uuidString,priority: TaskPriority? = nil,subsystem: LogSubsystem = .other,file: StaticString = #file,function: StaticString = #function,line: UInt = #line,@_inheritActorContext block: @Sendable @escaping () async -> Success)
+ @discardableResult public init(disposableBag: DisposableBag,identifier: String = UUIDProviderKey.currentValue.get().uuidString,priority: TaskPriority? = nil,subsystem: LogSubsystem = .other,file: StaticString = #file,function: StaticString = #function,line: UInt = #line,@_inheritActorContext block: @Sendable @escaping () async throws -> Success)
+
+
+ public func store(in disposableBag: DisposableBag,identifier: String = UUID().uuidString) |
Public Interface+ public protocol Signposting
+ extension OperationQueue
+
+ public func addTaskOperation(file: StaticString = #file,function: StaticString = #function,line: UInt = #line,operation: sending @escaping @Sendable @isolated(any) () async throws (Failure) -> Void)
+ public func addSynchronousTaskOperation(file: StaticString = #file,function: StaticString = #function,line: UInt = #line,timeout: TimeInterval = 5,operation: sending @escaping @Sendable @isolated(any) () async throws (Failure) -> Output)async throws -> Output
- public final class SerialActorQueue: Sendable
-
- public init()
-
-
- public func cancelAll()
- public func async(file: StaticString = #file,functionName: StaticString = #function,line: UInt = #line,_ block: @Sendable @escaping () async throws -> Void)
- public func sync(_ block: @Sendable @escaping () async throws -> T)async throws -> T
- public enum CallingState: Equatable, CustomStringConvertible
+ public enum CallingState: Equatable, CustomStringConvertible, Sendable
extension Publisher
- public func sinkTask(storeIn disposableBag: DisposableBag? = nil,identifier: String? = nil,receiveCompletion: @escaping (@Sendable(Subscribers.Completion<Failure>) -> Void) = { _ in },receiveValue: @escaping (@Sendable(Output) async throws -> Void))-> AnyCancellable
+ public func sinkTask(storeIn disposableBag: DisposableBag,identifier: String = UUIDProviderKey.currentValue.get().uuidString,file: StaticString = #file,function: StaticString = #function,line: UInt = #line,receiveCompletion: @escaping (@Sendable(Subscribers.Completion<Failure>) -> Void) = { _ in },receiveValue: @escaping (@Sendable(Output) async throws -> Void))-> AnyCancellable
- public func sinkTask(queue: SerialActorQueue,receiveCompletion: @escaping (@Sendable(Subscribers.Completion<Failure>) -> Void) = { _ in },receiveValue: @escaping (@Sendable(Output) async throws -> Void))-> AnyCancellable
public final class CurrentDevice: @unchecked Sendable
+ case simulator
extension Task
- public func store(in disposableBag: DisposableBag,key: String = UUID().uuidString)
+ @discardableResult public init(disposableBag: DisposableBag,identifier: String = UUIDProviderKey.currentValue.get().uuidString,priority: TaskPriority? = nil,subsystem: LogSubsystem = .other,file: StaticString = #file,function: StaticString = #function,line: UInt = #line,@_inheritActorContext block: @Sendable @escaping () async -> Success)
+ @discardableResult public init(disposableBag: DisposableBag,identifier: String = UUIDProviderKey.currentValue.get().uuidString,priority: TaskPriority? = nil,subsystem: LogSubsystem = .other,file: StaticString = #file,function: StaticString = #function,line: UInt = #line,@_inheritActorContext block: @Sendable @escaping () async throws -> Success)
+
+
+ public func store(in disposableBag: DisposableBag,identifier: String = UUID().uuidString)
public final class DisposableBag: @unchecked Sendable
+ public func completed(_ key: String) |
Public Interface+ public protocol Signposting
- public final class SerialActorQueue: Sendable
-
- public init()
-
-
- public func cancelAll()
- public func async(file: StaticString = #file,functionName: StaticString = #function,line: UInt = #line,_ block: @Sendable @escaping () async throws -> Void)
- public func sync(_ block: @Sendable @escaping () async throws -> T)async throws -> T
public final class CurrentDevice: @unchecked Sendable
+ case simulator
public final class DisposableBag: @unchecked Sendable
+ public func completed(_ key: String)
extension Publisher
- public func sinkTask(storeIn disposableBag: DisposableBag? = nil,identifier: String? = nil,receiveCompletion: @escaping (@Sendable(Subscribers.Completion<Failure>) -> Void) = { _ in },receiveValue: @escaping (@Sendable(Output) async throws -> Void))-> AnyCancellable
+ public func sinkTask(storeIn disposableBag: DisposableBag,identifier: String = UUIDProviderKey.currentValue.get().uuidString,file: StaticString = #file,function: StaticString = #function,line: UInt = #line,receiveCompletion: @escaping (@Sendable(Subscribers.Completion<Failure>) -> Void) = { _ in },receiveValue: @escaping (@Sendable(Output) async throws -> Void))-> AnyCancellable
- public func sinkTask(queue: SerialActorQueue,receiveCompletion: @escaping (@Sendable(Subscribers.Completion<Failure>) -> Void) = { _ in },receiveValue: @escaping (@Sendable(Output) async throws -> Void))-> AnyCancellable
- public enum CallingState: Equatable, CustomStringConvertible
+ public enum CallingState: Equatable, CustomStringConvertible, Sendable
extension Task
- public func store(in disposableBag: DisposableBag,key: String = UUID().uuidString)
+ @discardableResult public init(disposableBag: DisposableBag,identifier: String = UUIDProviderKey.currentValue.get().uuidString,priority: TaskPriority? = nil,subsystem: LogSubsystem = .other,file: StaticString = #file,function: StaticString = #function,line: UInt = #line,@_inheritActorContext block: @Sendable @escaping () async -> Success)
+ @discardableResult public init(disposableBag: DisposableBag,identifier: String = UUIDProviderKey.currentValue.get().uuidString,priority: TaskPriority? = nil,subsystem: LogSubsystem = .other,file: StaticString = #file,function: StaticString = #function,line: UInt = #line,@_inheritActorContext block: @Sendable @escaping () async throws -> Success)
+
+
+ public func store(in disposableBag: DisposableBag,identifier: String = UUID().uuidString) |
|



🎯 Goal
Improve Swift Concurrency Task lifecycle by 1. providing a simple way to manage a Task's lifecycle, 2. avoid keeping Tasks in memory to reduce memory usage.
☑️ Contributor Checklist