mirror of
https://github.com/apple/sourcekit-lsp.git
synced 2026-03-02 18:23:24 +01:00
Refactor DocumentManager threading for Swift 6
Replaces DispatchQueue with ThreadSafeBox, relaxes T: Sendable constraints, and removes @unchecked Sendable from Document.
This commit is contained in:
@@ -23,8 +23,8 @@ extension sourcekitd_api_values: @unchecked Sendable {}
|
||||
fileprivate extension ThreadSafeBox {
|
||||
/// If the wrapped value is `nil`, run `compute` and store the computed value. If it is not `nil`, return the stored
|
||||
/// value.
|
||||
func computeIfNil<WrappedValue>(compute: () -> WrappedValue) -> WrappedValue where T == WrappedValue? {
|
||||
return withLock { value in
|
||||
func computeIfNil<WrappedValue: Sendable>(compute: () -> WrappedValue) -> WrappedValue where T == WrappedValue? {
|
||||
return withLock { (value: inout WrappedValue?) -> WrappedValue in
|
||||
if let value {
|
||||
return value
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ package struct DocumentSnapshot: Identifiable, Sendable {
|
||||
}
|
||||
}
|
||||
|
||||
package final class Document: @unchecked Sendable {
|
||||
package final class Document {
|
||||
package let uri: DocumentURI
|
||||
package let language: Language
|
||||
var latestVersion: Int
|
||||
|
||||
@@ -15,12 +15,26 @@ import Foundation
|
||||
/// A thread safe container that contains a value of type `T`.
|
||||
///
|
||||
/// - Note: Unchecked sendable conformance because value is guarded by a lock.
|
||||
package class ThreadSafeBox<T: Sendable>: @unchecked Sendable {
|
||||
package final class ThreadSafeBox<T>: Sendable {
|
||||
/// Lock guarding `_value`.
|
||||
private let lock = NSLock()
|
||||
|
||||
private var _value: T
|
||||
private nonisolated(unsafe) var _value: T
|
||||
|
||||
package init(initialValue: T) {
|
||||
_value = initialValue
|
||||
}
|
||||
|
||||
/// Restrict the result of the body to `Sendable` so callers can safely use
|
||||
/// the returned value outside the lock without requiring `T: Sendable`.
|
||||
package func withLock<Result: Sendable>(_ body: (inout T) throws -> Result) rethrows -> Result {
|
||||
return try lock.withLock {
|
||||
return try body(&_value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension ThreadSafeBox where T: Sendable {
|
||||
package var value: T {
|
||||
get {
|
||||
return lock.withLock {
|
||||
@@ -39,16 +53,6 @@ package class ThreadSafeBox<T: Sendable>: @unchecked Sendable {
|
||||
}
|
||||
}
|
||||
|
||||
package init(initialValue: T) {
|
||||
_value = initialValue
|
||||
}
|
||||
|
||||
package func withLock<Result>(_ body: (inout T) throws -> Result) rethrows -> Result {
|
||||
return try lock.withLock {
|
||||
return try body(&_value)
|
||||
}
|
||||
}
|
||||
|
||||
/// If the value in the box is an optional, return it and reset it to `nil`
|
||||
/// in an atomic operation.
|
||||
package func takeValue<U>() -> T where U? == T {
|
||||
|
||||
Reference in New Issue
Block a user