Skip to content

Commit 3b68f15

Browse files
authored
Merge pull request #1394 from ahoppen/thread-safe-box-sendable
Require `ThreadSafeBox.T` to be Sendable
2 parents d806163 + c7bf59e commit 3b68f15

File tree

4 files changed

+15
-4
lines changed

4 files changed

+15
-4
lines changed

Sources/SKSupport/AsyncUtils.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ public extension Task where Failure == Never {
9898
///
9999
/// If the task executing `withCancellableCheckedThrowingContinuation` gets
100100
/// cancelled, `cancel` is invoked with the handle that `operation` provided.
101-
public func withCancellableCheckedThrowingContinuation<Handle, Result>(
101+
public func withCancellableCheckedThrowingContinuation<Handle: Sendable, Result>(
102102
_ operation: (_ continuation: CheckedContinuation<Result, any Error>) -> Handle,
103103
cancel: @Sendable (Handle) -> Void
104104
) async throws -> Result {

Sources/SKSupport/ThreadSafeBox.swift

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ extension NSLock {
2424
/// A thread safe container that contains a value of type `T`.
2525
///
2626
/// - Note: Unchecked sendable conformance because value is guarded by a lock.
27-
public class ThreadSafeBox<T>: @unchecked Sendable {
27+
public class ThreadSafeBox<T: Sendable>: @unchecked Sendable {
2828
/// Lock guarding `_value`.
2929
private let lock = NSLock()
3030

@@ -41,6 +41,11 @@ public class ThreadSafeBox<T>: @unchecked Sendable {
4141
_value = newValue
4242
}
4343
}
44+
_modify {
45+
lock.lock()
46+
defer { lock.unlock() }
47+
yield &_value
48+
}
4449
}
4550

4651
public init(initialValue: T) {

Sources/SKTestSupport/TestSourceKitLSPClient.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ fileprivate struct NotificationTimeoutError: Error, CustomStringConvertible {
3838
/// that the server sends to the client.
3939
public final class TestSourceKitLSPClient: MessageHandler {
4040
/// A function that takes a request and returns the request's response.
41-
public typealias RequestHandler<Request: RequestType> = (Request) -> Request.Response
41+
public typealias RequestHandler<Request: RequestType> = @Sendable (Request) -> Request.Response
4242

4343
/// The ID that should be assigned to the next request sent to the `server`.
4444
/// `nonisolated(unsafe)` is fine because `nextRequestID` is atomic.
@@ -70,7 +70,7 @@ public final class TestSourceKitLSPClient: MessageHandler {
7070
///
7171
/// `isOneShort` if the request handler should only serve a single request and should be removed from
7272
/// `requestHandlers` after it has been called.
73-
private nonisolated(unsafe) var requestHandlers: ThreadSafeBox<[(requestHandler: Any, isOneShot: Bool)]> =
73+
private nonisolated(unsafe) var requestHandlers: ThreadSafeBox<[(requestHandler: Sendable, isOneShot: Bool)]> =
7474
ThreadSafeBox(initialValue: [])
7575

7676
/// A closure that is called when the `TestSourceKitLSPClient` is destructed.

Sources/SourceKitD/SourceKitD.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,12 @@ import Dispatch
1515
import Foundation
1616
import SKSupport
1717

18+
#if compiler(>=6)
19+
extension sourcekitd_api_request_handle_t: @retroactive @unchecked Sendable {}
20+
#else
21+
extension sourcekitd_api_request_handle_t: @unchecked Sendable {}
22+
#endif
23+
1824
/// Access to sourcekitd API, taking care of initialization, shutdown, and notification handler
1925
/// multiplexing.
2026
///

0 commit comments

Comments
 (0)