Skip to content

Commit

Permalink
full Swift 6 data race safety
Browse files Browse the repository at this point in the history
  • Loading branch information
alexeichhorn committed Oct 21, 2024
1 parent b6f2253 commit ab20ded
Show file tree
Hide file tree
Showing 4 changed files with 17 additions and 15 deletions.
2 changes: 1 addition & 1 deletion Package.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// swift-tools-version:5.5
// swift-tools-version:6.0
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription
Expand Down
22 changes: 12 additions & 10 deletions Sources/YouTubeKit/Extensions/Concurrency.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import Foundation
@available(iOS 13.0, watchOS 6.0, tvOS 13.0, macOS 10.15, *)
extension Sequence {

func asyncMap<T>(_ transform: (Element) async throws -> T) async rethrows -> [T] {
func asyncMap<T: Sendable>(_ transform: (Element) async throws -> T, isolation: isolated (any Actor)? = #isolation) async rethrows -> [T] where Element: Sendable {
var values = [T]()

for element in self {
Expand All @@ -20,16 +20,18 @@ extension Sequence {
return values
}

func concurrentMap<T: Sendable>(_ transform: @escaping @Sendable (Element) async -> T) async -> [T] where Element: Sendable {

let tasks = map { element in
Task {
await transform(element)
func concurrentMap<T: Sendable>(_ transform: @Sendable (Element) async -> T) async -> [T] where Element: Sendable {
return await withoutActuallyEscaping(transform) { escapingTransform in

let tasks = map { element in
Task {
await escapingTransform(element)
}
}

return await tasks.asyncMap { task in
await task.value
}
}

return await tasks.asyncMap { task in
await task.value
}
}

Expand Down
2 changes: 1 addition & 1 deletion Sources/YouTubeKit/Extensions/Retry.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ extension Task {
// A static function that attempts to execute a block of code with each method in a provided array.
// If the block throws an error, the function will try the next method.
// If all methods have been tried and all have thrown errors, the function will throw the last error encountered.
static func retry<Method>(with methods: [Method], block: (Method) async throws -> Success) async throws -> Success where Failure == Never {
static func retry<Method: Sendable>(with methods: [Method], block: (Method) async throws -> Success, isolation: isolated (any Actor)? = #isolation) async throws -> Success where Failure == Never {

var lastError: any Error = RetryError.emptyMethods

Expand Down
6 changes: 3 additions & 3 deletions Sources/YouTubeKit/YouTube.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import Foundation
@preconcurrency import os.log

@available(iOS 13.0, watchOS 6.0, tvOS 13.0, macOS 10.15, *)
public class YouTube {
public actor YouTube {

private var _js: String?
private var _jsURL: URL?
Expand Down Expand Up @@ -81,7 +81,7 @@ public class YouTube {
}

/// - parameter methods: Methods used to extract streams from the video - ordered by priority (Default: only local)
public convenience init(url: URL, proxies: [String: URL] = [:], useOAuth: Bool = false, allowOAuthCache: Bool = false, methods: [ExtractionMethod] = [.local]) {
public init(url: URL, proxies: [String: URL] = [:], useOAuth: Bool = false, allowOAuthCache: Bool = false, methods: [ExtractionMethod] = [.local]) {
let videoID = Extraction.extractVideoID(from: url.absoluteString) ?? ""
self.init(videoID: videoID, proxies: proxies, useOAuth: useOAuth, allowOAuthCache: allowOAuthCache, methods: methods)
}
Expand Down Expand Up @@ -220,7 +220,7 @@ public class YouTube {
var streams = [Stream]()
var existingITags = Set<Int>()

func process(streamingData: InnerTube.StreamingData, videoInfo: InnerTube.VideoInfo) async throws {
func process(streamingData: InnerTube.StreamingData, videoInfo: InnerTube.VideoInfo, isolation: isolated (any Actor)? = #isolation) async throws {

var streamManifest = Extraction.applyDescrambler(streamData: streamingData)

Expand Down

0 comments on commit ab20ded

Please sign in to comment.