Skip to content

Commit a94e7cc

Browse files
authored
Add async-friendly WritableStream, create _AsyncFileSystem module (#7831)
Existing `WritableByteStream` protocol used by `AsyncProcess` is not thread-safe. It's new `WritableStream` replacement is, with an added conformance to the existing `OpenWritableFile`. That one is built on top `AsyncFS`, which has been moved to the `Basics` module. That allows us to adopt it in `AsyncProcess` in the future. This is NFC, new API is adopted solely by `QueryEngine`, which is exercised only in tests.
1 parent 8b83dee commit a94e7cc

22 files changed

+595
-294
lines changed

Package.swift

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,9 +174,23 @@ let package = Package(
174174

175175
.systemLibrary(name: "SPMSQLite3", pkgConfig: systemSQLitePkgConfig),
176176

177+
.target(
178+
name: "_AsyncFileSystem",
179+
dependencies: [
180+
.product(name: "SystemPackage", package: "swift-system"),
181+
],
182+
exclude: ["CMakeLists.txt"],
183+
swiftSettings: [
184+
.enableExperimentalFeature("StrictConcurrency"),
185+
.enableExperimentalFeature("AccessLevelOnImport"),
186+
.enableExperimentalFeature("InternalImportsByDefault")
187+
]
188+
),
189+
177190
.target(
178191
name: "Basics",
179192
dependencies: [
193+
"_AsyncFileSystem",
180194
"SPMSQLite3",
181195
.product(name: "DequeModule", package: "swift-collections"),
182196
.product(name: "OrderedCollections", package: "swift-collections"),
@@ -482,6 +496,7 @@ let package = Package(
482496
.target(
483497
name: "QueryEngine",
484498
dependencies: [
499+
"_AsyncFileSystem",
485500
"Basics",
486501
.product(name: "Crypto", package: "swift-crypto"),
487502
],
@@ -603,6 +618,14 @@ let package = Package(
603618

604619
// MARK: SwiftPM tests
605620

621+
.testTarget(
622+
name: "_AsyncFileSystemTests",
623+
dependencies: [
624+
"_AsyncFileSystem",
625+
"_InternalTestSupport",
626+
]
627+
),
628+
606629
.testTarget(
607630
name: "SourceKitLSPAPITests",
608631
dependencies: [

Sources/Basics/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@ add_library(Basics
1111
Archiver/TarArchiver.swift
1212
Archiver/ZipArchiver.swift
1313
Archiver/UniversalArchiver.swift
14-
AsyncProcess.swift
1514
AuthorizationProvider.swift
1615
Cancellator.swift
1716
Collections/ByteString+Extensions.swift
1817
Collections/Dictionary+Extensions.swift
1918
Collections/IdentifiableSet.swift
2019
Collections/String+Extensions.swift
20+
Concurrency/AsyncProcess.swift
2121
Concurrency/ConcurrencyHelpers.swift
2222
Concurrency/NSLock+Extensions.swift
2323
Concurrency/SendableBox.swift
@@ -77,6 +77,7 @@ add_library(Basics
7777
Vendor/Triple.swift
7878
Vendor/Triple+Platforms.swift)
7979
target_link_libraries(Basics PUBLIC
80+
_AsyncFileSystem
8081
SwiftCollections::DequeModule
8182
SwiftCollections::OrderedCollections
8283
SwiftSystem::SystemPackage

Sources/Basics/AsyncProcess.swift renamed to Sources/Basics/Concurrency/AsyncProcess.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -452,7 +452,7 @@ package final class AsyncProcess {
452452
/// stdin. If needed, the stream can be closed using the close() API. Otherwise, the stream will be closed
453453
/// automatically.
454454
@discardableResult
455-
package func launch() throws -> WritableByteStream {
455+
package func launch() throws -> any WritableByteStream {
456456
precondition(
457457
self.arguments.count > 0 && !self.arguments[0].isEmpty,
458458
"Need at least one argument to launch the process."

Sources/Basics/Concurrency/ConcurrencyHelpers.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,17 @@ extension DispatchQueue {
5252
// As of Swift 5.7 and 5.8 swift-corelibs-foundation doesn't have `Sendable` annotations yet.
5353
extension URL: @unchecked Sendable {}
5454
#endif
55+
56+
extension DispatchQueue {
57+
package func scheduleOnQueue<T>(work: @escaping @Sendable () throws -> T) async throws -> T {
58+
try await withCheckedThrowingContinuation { continuation in
59+
self.async {
60+
do {
61+
continuation.resume(returning: try work())
62+
} catch {
63+
continuation.resume(throwing: error)
64+
}
65+
}
66+
}
67+
}
68+
}

Sources/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
# This source file is part of the Swift open source project
22
#
3-
# Copyright (c) 2014 - 2021 Apple Inc. and the Swift project authors
3+
# Copyright (c) 2014 - 2024 Apple Inc. and the Swift project authors
44
# Licensed under Apache License v2.0 with Runtime Library Exception
55
#
66
# See http://swift.org/LICENSE.txt for license information
77
# See http://swift.org/CONTRIBUTORS.txt for Swift project authors
88

99
add_compile_definitions(USE_IMPL_ONLY_IMPORTS)
1010

11+
add_subdirectory(_AsyncFileSystem)
1112
add_subdirectory(Basics)
1213
add_subdirectory(Build)
1314
add_subdirectory(Commands)

Sources/QueryEngine/FileSystem/FileCacheRecord.swift renamed to Sources/QueryEngine/FileCacheRecord.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13+
import struct _AsyncFileSystem.OpenReadableFile
14+
1315
// FIXME: need a new swift-system tag to remove `@preconcurrency`
1416
@preconcurrency import struct SystemPackage.FilePath
1517

@@ -37,3 +39,13 @@ extension FileCacheRecord: Codable {
3739
try container.encode(self.hash, forKey: .hash)
3840
}
3941
}
42+
43+
extension OpenReadableFile {
44+
func hash(with hashFunction: inout some HashFunction) async throws {
45+
let stream = try await self.read()
46+
47+
for try await bytes in stream {
48+
hashFunction.update(data: bytes)
49+
}
50+
}
51+
}

Sources/QueryEngine/FileSystem/AsyncFileSystem.swift

Lines changed: 0 additions & 44 deletions
This file was deleted.

Sources/QueryEngine/FileSystem/OpenReadableFile.swift

Lines changed: 0 additions & 54 deletions
This file was deleted.

Sources/QueryEngine/FileSystem/OpenWritableFile.swift

Lines changed: 0 additions & 32 deletions
This file was deleted.

Sources/QueryEngine/FileSystem/ReadableFileStream.swift

Lines changed: 0 additions & 104 deletions
This file was deleted.

0 commit comments

Comments
 (0)