Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 2 additions & 5 deletions Sources/BuildServerIntegration/SwiftPMBuildServer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ package import SKOptions
import SourceControl
@preconcurrency package import SourceKitLSPAPI
import SwiftExtensions
import Synchronization
@_spi(SourceKitLSP) import ToolsProtocolsSwiftExtensions
import TSCExtensions
package import ToolchainRegistry
Expand Down Expand Up @@ -80,7 +79,7 @@ fileprivate extension TSCBasic.AbsolutePath {
}
}

private let preparationTaskID = Atomic<UInt32>(0)
private let preparationTaskID: AtomicUInt32 = AtomicUInt32(initialValue: 0)

/// Swift Package Manager build server and workspace support.
///
Expand Down Expand Up @@ -831,9 +830,7 @@ package actor SwiftPMBuildServer: BuiltInBuildServer {
}
let start = ContinuousClock.now

let taskID: TaskId = TaskId(
id: "preparation-\(preparationTaskID.wrappingAdd(1, ordering: .relaxed).oldValue)"
)
let taskID: TaskId = TaskId(id: "preparation-\(preparationTaskID.fetchAndIncrement())")
connectionToSourceKitLSP.send(
BuildServerProtocol.OnBuildLogMessageNotification(
type: .info,
Expand Down
7 changes: 3 additions & 4 deletions Sources/CompletionScoringTestSupport/TestExtensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
package import CompletionScoring
import Foundation
import SwiftExtensions
import Synchronization
@_spi(SourceKitLSP) import ToolsProtocolsSwiftExtensions
import XCTest

Expand Down Expand Up @@ -103,7 +102,7 @@ extension XCTestCase {
UserDefaults.standard.string(forKey: "TestMeasurementLogPath")
}()

static let printBeginingOfLog = Atomic<Bool>(true)
static let printBeginingOfLog = AtomicBool(initialValue: true)

private static func openPerformanceLog() throws -> FileHandle? {
try measurementsLogFile.map { path in
Expand All @@ -116,9 +115,9 @@ extension XCTestCase {
}
let logFD = try FileHandle(forWritingAtPath: path).unwrap(orThrow: "Opening \(path) failed")
try logFD.seekToEnd()
if printBeginingOfLog.load(ordering: .relaxed) {
if printBeginingOfLog.value {
try logFD.print("========= \(Date().description(with: .current)) =========")
printBeginingOfLog.store(false, ordering: .relaxed)
printBeginingOfLog.value = false
}
return logFD
}
Expand Down
11 changes: 4 additions & 7 deletions Sources/Diagnose/DiagnoseCommand.swift
Original file line number Diff line number Diff line change
Expand Up @@ -222,8 +222,8 @@ package struct DiagnoseCommand: AsyncParsableCommand {
let outputFileUrl = bundlePath.appending(component: "log.txt")
try FileManager.default.createFile(at: outputFileUrl, contents: nil)
let fileHandle = try FileHandle(forWritingTo: outputFileUrl)
let bytesCollected = ThreadSafeBox<Int32>(initialValue: 0)
let processExited = ThreadSafeBox<Bool>(initialValue: false)
let bytesCollected = AtomicInt32(initialValue: 0)
let processExited = AtomicBool(initialValue: false)
// 50 MB is an average log size collected by sourcekit-lsp diagnose.
// It's a good proxy to show some progress indication for the majority of the time.
let expectedLogSize = 50_000_000
Expand All @@ -239,11 +239,8 @@ package struct DiagnoseCommand: AsyncParsableCommand {
outputRedirection: .stream(
stdout: { @Sendable bytes in
try? fileHandle.write(contentsOf: bytes)
let totalBytes = bytesCollected.withLock { value -> Int32 in
value += Int32(bytes.count)
return value
}
var progress = Double(totalBytes) / Double(expectedLogSize)
bytesCollected.value += Int32(bytes.count)
var progress = Double(bytesCollected.value) / Double(expectedLogSize)
if progress > 1 {
// The log is larger than we expected. Halt at 100%
progress = 1
Expand Down
7 changes: 2 additions & 5 deletions Sources/InProcessClient/InProcessSourceKitLSPClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ public import Foundation
public import SKOptions
package import SourceKitLSP
import SwiftExtensions
import Synchronization
import TSCExtensions
package import ToolchainRegistry
@_spi(SourceKitLSP) import ToolsProtocolsSwiftExtensions
Expand All @@ -30,7 +29,7 @@ import struct TSCBasic.AbsolutePath
public final class InProcessSourceKitLSPClient: Sendable {
private let server: SourceKitLSPServer

private let nextRequestID = Atomic<UInt32>(0)
private let nextRequestID = AtomicUInt32(initialValue: 0)

public convenience init(
toolchainPath: URL?,
Expand Down Expand Up @@ -124,9 +123,7 @@ public final class InProcessSourceKitLSPClient: Sendable {
_ request: R,
reply: @Sendable @escaping (LSPResult<R.Response>) -> Void
) -> RequestID {
let requestID = RequestID.string(
"sk-\(Int(nextRequestID.wrappingAdd(1, ordering: .relaxed).oldValue))"
)
let requestID = RequestID.string("sk-\(Int(nextRequestID.fetchAndIncrement()))")
server.handle(request, id: requestID, reply: reply)
return requestID
}
Expand Down
9 changes: 3 additions & 6 deletions Sources/SKTestSupport/MultiEntrySemaphore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
//===----------------------------------------------------------------------===//

import SwiftExtensions
import Synchronization
@_spi(SourceKitLSP) import ToolsProtocolsSwiftExtensions
import XCTest

Expand All @@ -22,21 +21,19 @@ import XCTest
/// done, all index operations should be able to run, not just one.
package final class MultiEntrySemaphore: Sendable {
private let name: String
private let signaled = Atomic<Bool>(false)
private let signaled = AtomicBool(initialValue: false)

package init(name: String) {
self.name = name
}

package func signal() {
signaled.store(true, ordering: .releasing)
signaled.value = true
}

package func waitOrThrow() async throws {
do {
try await repeatUntilExpectedResult(sleepInterval: .seconds(0.01)) {
signaled.load(ordering: .acquiring)
}
try await repeatUntilExpectedResult(sleepInterval: .seconds(0.01)) { signaled.value }
} catch {
struct TimeoutError: Error, CustomStringConvertible {
let name: String
Expand Down
12 changes: 4 additions & 8 deletions Sources/SKTestSupport/TestSourceKitLSPClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import SourceKitD
package import SourceKitLSP
import SwiftExtensions
package import SwiftSyntax
import Synchronization
package import ToolchainRegistry
@_spi(SourceKitLSP) import ToolsProtocolsSwiftExtensions
import XCTest
Expand Down Expand Up @@ -94,7 +93,7 @@ package final class TestSourceKitLSPClient: MessageHandler, Sendable {
package typealias RequestHandler<Request: RequestType> = @Sendable (Request) -> Request.Response

/// The ID that should be assigned to the next request sent to the `server`.
private let nextRequestID = Atomic<UInt32>(0)
private let nextRequestID = AtomicUInt32(initialValue: 0)

/// The server that handles the requests.
package let server: SourceKitLSPServer
Expand Down Expand Up @@ -243,10 +242,7 @@ package final class TestSourceKitLSPClient: MessageHandler, Sendable {
// It's really unfortunate that there are no async deinits. If we had async
// deinits, we could await the sending of a ShutdownRequest.
let shutdownSemaphore = WrappedSemaphore(name: "Shutdown")
server.handle(
ShutdownRequest(),
id: .number(Int(nextRequestID.wrappingAdd(1, ordering: .relaxed).oldValue))
) { result in
server.handle(ShutdownRequest(), id: .number(Int(nextRequestID.fetchAndIncrement()))) { result in
shutdownSemaphore.signal()
}
shutdownSemaphore.waitOrXCTFail()
Expand Down Expand Up @@ -293,7 +289,7 @@ package final class TestSourceKitLSPClient: MessageHandler, Sendable {
_ request: R,
completionHandler: @Sendable @escaping (LSPResult<R.Response>) -> Void
) -> RequestID {
let requestID = RequestID.number(Int(nextRequestID.wrappingAdd(1, ordering: .relaxed).oldValue))
let requestID = RequestID.number(Int(nextRequestID.fetchAndIncrement()))
let replyOutstanding = ThreadSafeBox<Bool?>(initialValue: true)
let timeoutTask = Task {
try await Task.sleep(for: defaultTimeoutDuration)
Expand Down Expand Up @@ -405,7 +401,7 @@ package final class TestSourceKitLSPClient: MessageHandler, Sendable {
line: UInt = #line
) async throws -> Value where R.Response == VoidResponse {
// Register a one-shot handler that records when the request arrives.
let received = ThreadSafeBox<Bool>(initialValue: false)
let received = AtomicBool(initialValue: false)
self.handleSingleRequest { (_: R) in
received.value = true
return VoidResponse()
Expand Down
5 changes: 2 additions & 3 deletions Sources/SemanticIndex/PreparationTaskDescription.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,20 @@ import Foundation
@_spi(SourceKitLSP) import LanguageServerProtocolExtensions
@_spi(SourceKitLSP) import SKLogging
import SwiftExtensions
import Synchronization
@_spi(SourceKitLSP) import ToolsProtocolsSwiftExtensions

import struct TSCBasic.AbsolutePath
import class TSCBasic.Process

private let preparationIDForLogging = Atomic<UInt32>(1)
private let preparationIDForLogging = AtomicUInt32(initialValue: 1)

/// Describes a task to prepare a set of targets.
///
/// This task description can be scheduled in a `TaskScheduler`.
package struct PreparationTaskDescription: IndexTaskDescription {
package static let idPrefix = "prepare"

package let id = preparationIDForLogging.wrappingAdd(1, ordering: .relaxed).oldValue
package let id = preparationIDForLogging.fetchAndIncrement()

/// The targets that should be prepared.
package let targetsToPrepare: [BuildTargetIdentifier]
Expand Down
25 changes: 12 additions & 13 deletions Sources/SemanticIndex/TaskScheduler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import Foundation
@_spi(SourceKitLSP) import LanguageServerProtocolExtensions
@_spi(SourceKitLSP) package import SKLogging
import SwiftExtensions
import Synchronization
@_spi(SourceKitLSP) import ToolsProtocolsSwiftExtensions

/// See comment on ``TaskDescriptionProtocol/dependencies(to:taskPriority:)``
Expand Down Expand Up @@ -128,18 +127,18 @@ package actor QueuedTask<TaskDescription: TaskDescriptionProtocol> {
/// Every time `execute` gets called, a new task is placed in this continuation. See comment on `executionTask`.
private let executionTaskCreatedContinuation: AsyncStream<Task<ExecutionTaskFinishStatus, Never>>.Continuation

private let _priority: Atomic<UInt8>
private let _priority: AtomicUInt8

/// The latest known priority of the task.
///
/// This starts off as the priority with which the task is being created. If higher priority tasks start depending on
/// it, the priority may get elevated.
nonisolated var priority: TaskPriority {
get {
TaskPriority(rawValue: _priority.load(ordering: .relaxed))
TaskPriority(rawValue: _priority.value)
}
set {
_priority.store(newValue.rawValue, ordering: .relaxed)
_priority.value = newValue.rawValue
}
}

Expand All @@ -149,13 +148,13 @@ package actor QueuedTask<TaskDescription: TaskDescriptionProtocol> {
private var cancelledToBeRescheduled: Bool = false

/// Whether `resultTask` has been cancelled.
private let resultTaskCancelled = Atomic<Bool>(false)
private let resultTaskCancelled: AtomicBool = .init(initialValue: false)

private let _isExecuting = Atomic<Bool>(false)
private let _isExecuting: AtomicBool = .init(initialValue: false)

/// Whether the task is currently executing or still queued to be executed later.
package nonisolated var isExecuting: Bool {
return _isExecuting.load(ordering: .relaxed)
return _isExecuting.value
}

package nonisolated func cancel() {
Expand Down Expand Up @@ -189,7 +188,7 @@ package actor QueuedTask<TaskDescription: TaskDescriptionProtocol> {
taskPriorityChangedCallback: @escaping @Sendable (_ newPriority: TaskPriority) -> Void,
executionStateChangedCallback: (@Sendable (QueuedTask, TaskExecutionState) async -> Void)?
) async {
self._priority = Atomic<UInt8>(priority.rawValue)
self._priority = AtomicUInt8(initialValue: priority.rawValue)
self.description = description
self.executionStateChangedCallback = executionStateChangedCallback

Expand Down Expand Up @@ -222,7 +221,7 @@ package actor QueuedTask<TaskDescription: TaskDescriptionProtocol> {
taskPriorityChangedCallback(self.priority)
}
} onCancel: {
self.resultTaskCancelled.store(true, ordering: .relaxed)
self.resultTaskCancelled.value = true
}
}
}
Expand All @@ -243,15 +242,15 @@ package actor QueuedTask<TaskDescription: TaskDescriptionProtocol> {
}
precondition(executionTask == nil, "Task started twice")
let task = Task.detached(priority: self.priority) {
if !Task.isCancelled && !self.resultTaskCancelled.load(ordering: .relaxed) {
if !Task.isCancelled && !self.resultTaskCancelled.value {
await self.description.execute()
}
return await self.finalizeExecution()
}
_isExecuting.store(true, ordering: .relaxed)
_isExecuting.value = true
executionTask = task
executionTaskCreatedContinuation.yield(task)
if self.resultTaskCancelled.load(ordering: .relaxed) {
if self.resultTaskCancelled.value {
// The queued task might have been cancelled after the execution ask was started but before the task was yielded
// to `executionTaskCreatedContinuation`. In that case the result task will simply cancel the await on the
// `executionTaskCreatedStream` and hence not call `valuePropagatingCancellation` on the execution task. This
Expand All @@ -266,7 +265,7 @@ package actor QueuedTask<TaskDescription: TaskDescriptionProtocol> {
/// Implementation detail of `execute` that is called after `self.description.execute()` finishes.
private func finalizeExecution() async -> ExecutionTaskFinishStatus {
self.executionTask = nil
_isExecuting.store(false, ordering: .relaxed)
_isExecuting.value = false
if Task.isCancelled && self.cancelledToBeRescheduled {
await executionStateChangedCallback?(self, .cancelledToBeRescheduled)
self.cancelledToBeRescheduled = false
Expand Down
5 changes: 2 additions & 3 deletions Sources/SemanticIndex/UpdateIndexStoreTaskDescription.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import Foundation
@_spi(SourceKitLSP) import LanguageServerProtocolExtensions
@_spi(SourceKitLSP) import SKLogging
import SwiftExtensions
import Synchronization
import TSCExtensions
import ToolchainRegistry
@_spi(SourceKitLSP) import ToolsProtocolsSwiftExtensions
Expand All @@ -31,7 +30,7 @@ import enum TSCBasic.SystemError
import WinSDK
#endif

private let updateIndexStoreIDForLogging = Atomic<UInt32>(1)
private let updateIndexStoreIDForLogging = AtomicUInt32(initialValue: 1)

package enum FileToIndex: CustomLogStringConvertible, Hashable {
/// A non-header file
Expand Down Expand Up @@ -115,7 +114,7 @@ private enum UpdateIndexStorePartition {
/// This task description can be scheduled in a `TaskScheduler`.
package struct UpdateIndexStoreTaskDescription: IndexTaskDescription {
package static let idPrefix = "update-indexstore"
package let id = updateIndexStoreIDForLogging.wrappingAdd(1, ordering: .relaxed).oldValue
package let id = updateIndexStoreIDForLogging.fetchAndIncrement()

/// The files that should be indexed.
package let filesToIndex: [FileAndOutputPath]
Expand Down
2 changes: 1 addition & 1 deletion Sources/SwiftExtensions/AsyncUtils.swift
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ package func withTimeoutResult<T: Sendable>(
body: @escaping @Sendable () async throws -> T,
resultReceivedAfterTimeout: @escaping @Sendable (_ result: T) async -> Void
) async throws -> WithTimeoutResult<T> {
let didHitTimeout = ThreadSafeBox<Bool>(initialValue: false)
let didHitTimeout = AtomicBool(initialValue: false)

let stream = AsyncThrowingStream<WithTimeoutResult<T>, any Error> { continuation in
Task {
Expand Down
5 changes: 2 additions & 3 deletions Sources/SwiftLanguageService/CodeCompletionSession.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,12 @@ import SwiftExtensions
import SwiftParser
@_spi(SourceKitLSP) import SwiftRefactor
import SwiftSyntax
import Synchronization
@_spi(SourceKitLSP) import ToolsProtocolsSwiftExtensions

/// Uniquely identifies a code completion session. We need this so that when resolving a code completion item, we can
/// verify that the item to resolve belongs to the code completion session that is currently open.
struct CompletionSessionID: Equatable, Codable {
private static let nextSessionID = Atomic<UInt32>(0)
private static let nextSessionID = AtomicUInt32(initialValue: 0)

let value: UInt32

Expand All @@ -39,7 +38,7 @@ struct CompletionSessionID: Equatable, Codable {
}

static func next() -> CompletionSessionID {
return CompletionSessionID(value: nextSessionID.wrappingAdd(1, ordering: .relaxed).oldValue)
return CompletionSessionID(value: nextSessionID.fetchAndIncrement())
}

init(from decoder: any Decoder) throws {
Expand Down
2 changes: 1 addition & 1 deletion Sources/TSCExtensions/Process+Run.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ extension Process {
/// Should the process not terminate on SIGINT after 2 seconds, it is terminated using `SIGKILL`.
@discardableResult
package func waitUntilExitStoppingProcessOnTaskCancellation() async throws -> ProcessResult {
let hasExited = ThreadSafeBox<Bool>(initialValue: false)
let hasExited = AtomicBool(initialValue: false)
return try await withTaskCancellationHandler {
defer {
hasExited.value = true
Expand Down