From 9b261ce4f10a061d2d4a8d547bbfb397572a6975 Mon Sep 17 00:00:00 2001 From: Rintaro Ishizaki Date: Thu, 21 May 2026 10:58:11 -0700 Subject: [PATCH 1/2] Migrate atomics to Synchronization.Atomic, drop ToolsProtocolsCAtomics Replace the AtomicBool/UInt8/UInt32/Int32 wrapper classes (backed by a small C atomics shim) with Synchronization.Atomic. All sites use .sequentiallyConsistent ordering to match the prior shim's behavior; relaxing per-site is left as a follow-up. The ToolsProtocolsCAtomics target is removed from Package.swift and CMake. --- Package.swift | 11 +- Sources/CMakeLists.txt | 1 - .../JSONRPCConnection.swift | 5 +- .../LocalConnection.swift | 5 +- .../QueueBasedMessageHandler.swift | 5 +- .../RequestAndReply.swift | 7 +- Sources/SKLogging/LoggingScope.swift | 5 +- Sources/SKLogging/NonDarwinLogging.swift | 5 +- Sources/ToolsProtocolsCAtomics/CAtomics.c | 11 -- Sources/ToolsProtocolsCAtomics/CMakeLists.txt | 4 - .../include/ToolsProtocolsCAtomics.h | 78 ------------ .../include/module.modulemap | 4 - .../AsyncUtils.swift | 2 +- .../Atomics.swift | 111 ------------------ .../CMakeLists.txt | 5 - 15 files changed, 22 insertions(+), 237 deletions(-) delete mode 100644 Sources/ToolsProtocolsCAtomics/CAtomics.c delete mode 100644 Sources/ToolsProtocolsCAtomics/CMakeLists.txt delete mode 100644 Sources/ToolsProtocolsCAtomics/include/ToolsProtocolsCAtomics.h delete mode 100644 Sources/ToolsProtocolsCAtomics/include/module.modulemap delete mode 100644 Sources/ToolsProtocolsSwiftExtensions/Atomics.swift diff --git a/Package.swift b/Package.swift index 9aa83bf5d..1e9bb2f01 100644 --- a/Package.swift +++ b/Package.swift @@ -52,13 +52,6 @@ var targets: [Target] = [ swiftSettings: globalSwiftSettings ), - // MARK: ToolsProtocolsCAtomics - - .target( - name: "ToolsProtocolsCAtomics", - dependencies: [] - ), - // MARK: LanguageServerProtocol .target( @@ -153,7 +146,7 @@ var targets: [Target] = [ .target( name: "ToolsProtocolsSwiftExtensions", - dependencies: ["ToolsProtocolsCAtomics"], + dependencies: [], exclude: ["CMakeLists.txt"], swiftSettings: globalSwiftSettings ), @@ -161,7 +154,7 @@ var targets: [Target] = [ // SourceKit-LSP SPI target. Builds ToolsProtocolsSwiftExtensions with an alternate module name to avoid runtime type collisions. .target( name: "_ToolsProtocolsSwiftExtensionsForPlugin", - dependencies: ["ToolsProtocolsCAtomics"], + dependencies: [], exclude: ["CMakeLists.txt"], swiftSettings: globalSwiftSettings ), diff --git a/Sources/CMakeLists.txt b/Sources/CMakeLists.txt index f1dab2859..066d83a99 100644 --- a/Sources/CMakeLists.txt +++ b/Sources/CMakeLists.txt @@ -2,7 +2,6 @@ add_compile_options("$<$:SHELL:-package-name swift_langu add_compile_options("$<$:SHELL:-DRESILIENT_LIBRARIES>") add_compile_options("$<$:SHELL:-swift-version 6>") add_subdirectory(BuildServerProtocol) -add_subdirectory(ToolsProtocolsCAtomics) add_subdirectory(LanguageServerProtocol) add_subdirectory(LanguageServerProtocolTransport) add_subdirectory(SKLogging) diff --git a/Sources/LanguageServerProtocolTransport/JSONRPCConnection.swift b/Sources/LanguageServerProtocolTransport/JSONRPCConnection.swift index 16ced07e8..4c8cfae9c 100644 --- a/Sources/LanguageServerProtocolTransport/JSONRPCConnection.swift +++ b/Sources/LanguageServerProtocolTransport/JSONRPCConnection.swift @@ -13,6 +13,7 @@ public import Foundation public import LanguageServerProtocol @_spi(SourceKitLSP) import SKLogging +import Synchronization @_spi(SourceKitLSP) import ToolsProtocolsSwiftExtensions #if canImport(Android) @@ -85,7 +86,7 @@ public final class JSONRPCConnection: Connection { private nonisolated(unsafe) var state: State = .created /// An integer that hasn't been used for a request ID yet. - let nextRequestIDStorage = AtomicUInt32(initialValue: 0) + let nextRequestIDStorage = Atomic(0) struct OutstandingRequest: Sendable { var responseType: ResponseType.Type @@ -597,7 +598,7 @@ public final class JSONRPCConnection: Connection { /// Request id for the next outgoing request. public func nextRequestID() -> RequestID { - return .string("sk-\(nextRequestIDStorage.fetchAndIncrement())") + return .string("sk-\(nextRequestIDStorage.wrappingAdd(1, ordering: .sequentiallyConsistent).oldValue)") } // MARK: Connection interface diff --git a/Sources/LanguageServerProtocolTransport/LocalConnection.swift b/Sources/LanguageServerProtocolTransport/LocalConnection.swift index f910ceb13..a5773e1ad 100644 --- a/Sources/LanguageServerProtocolTransport/LocalConnection.swift +++ b/Sources/LanguageServerProtocolTransport/LocalConnection.swift @@ -14,6 +14,7 @@ import Dispatch import Foundation public import LanguageServerProtocol @_spi(SourceKitLSP) import SKLogging +import Synchronization @_spi(SourceKitLSP) import ToolsProtocolsSwiftExtensions /// A connection between two message handlers in the same process. @@ -39,7 +40,7 @@ public final class LocalConnection: Connection, Sendable { /// The queue guarding `_nextRequestID`. private let queue: DispatchQueue = DispatchQueue(label: "local-connection-queue") - private let _nextRequestID = AtomicUInt32(initialValue: 0) + private let _nextRequestID = Atomic(0) /// - Important: Must only be accessed from `queue` nonisolated(unsafe) private var state: State = .ready @@ -87,7 +88,7 @@ public final class LocalConnection: Connection, Sendable { } public func nextRequestID() -> RequestID { - return .string("sk-\(_nextRequestID.fetchAndIncrement())") + return .string("sk-\(_nextRequestID.wrappingAdd(1, ordering: .sequentiallyConsistent).oldValue)") } public func send(_ notification: Notification) { diff --git a/Sources/LanguageServerProtocolTransport/QueueBasedMessageHandler.swift b/Sources/LanguageServerProtocolTransport/QueueBasedMessageHandler.swift index a2af2d620..0d22934d5 100644 --- a/Sources/LanguageServerProtocolTransport/QueueBasedMessageHandler.swift +++ b/Sources/LanguageServerProtocolTransport/QueueBasedMessageHandler.swift @@ -13,6 +13,7 @@ import Foundation public import LanguageServerProtocol @_spi(SourceKitLSP) import SKLogging +import Synchronization @_spi(SourceKitLSP) public import ToolsProtocolsSwiftExtensions /// Side structure in which `QueueBasedMessageHandler` can keep track of active requests etc. @@ -42,7 +43,7 @@ public final class QueueBasedMessageHandlerHelper: Sendable { private let createLoggingScope: Bool /// Notifications don't have an ID. This represents the next ID we can use to identify a notification. - private let notificationIDForLogging = AtomicUInt32(initialValue: 1) + private let notificationIDForLogging = Atomic(1) private let state = ThreadSafeBox(initialValue: State()) @@ -107,7 +108,7 @@ public final class QueueBasedMessageHandlerHelper: Sendable { // Only use the last two digits of the notification ID for the logging scope to avoid creating too many scopes. // See comment in `withLoggingScope`. // The last 2 digits should be sufficient to differentiate between multiple concurrently running notifications. - let notificationID = notificationIDForLogging.fetchAndIncrement() + let notificationID = notificationIDForLogging.wrappingAdd(1, ordering: .sequentiallyConsistent).oldValue withLoggingScope("notification-\(notificationID % 100)") { body() } diff --git a/Sources/LanguageServerProtocolTransport/RequestAndReply.swift b/Sources/LanguageServerProtocolTransport/RequestAndReply.swift index bfdf1062d..1f1deedaa 100644 --- a/Sources/LanguageServerProtocolTransport/RequestAndReply.swift +++ b/Sources/LanguageServerProtocolTransport/RequestAndReply.swift @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// public import LanguageServerProtocol +import Synchronization @_spi(SourceKitLSP) import ToolsProtocolsSwiftExtensions /// A request and a callback that returns the request's reply @@ -22,7 +23,7 @@ public final class RequestAndReply: Sendable { private let reply: @Sendable (Result) -> Void /// Whether a reply has been made. Every request must reply exactly once. - private let replied: AtomicBool = AtomicBool(initialValue: false) + private let replied = Atomic(false) public init(_ request: Params, reply: @escaping @Sendable (Result) -> Void) { self.params = request @@ -30,12 +31,12 @@ public final class RequestAndReply: Sendable { } deinit { - precondition(replied.value, "request never received a reply") + precondition(replied.load(ordering: .sequentiallyConsistent), "request never received a reply") } /// Call the `replyBlock` with the result produced by the given closure. public func reply(_ body: () async throws -> Params.Response) async { - let didReply = replied.setAndGet(newValue: true) + let didReply = replied.exchange(true, ordering: .sequentiallyConsistent) precondition(!didReply, "replied to request more than once") do { reply(.success(try await body())) diff --git a/Sources/SKLogging/LoggingScope.swift b/Sources/SKLogging/LoggingScope.swift index 04df859a3..3e3e6a523 100644 --- a/Sources/SKLogging/LoggingScope.swift +++ b/Sources/SKLogging/LoggingScope.swift @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// import Foundation +import Synchronization @_spi(SourceKitLSP) import ToolsProtocolsSwiftExtensions public final class LoggingScope { @@ -20,7 +21,7 @@ public final class LoggingScope { /// Whether we have logged a fault that `subsystem` has been accessed without calling /// `configureDefaultLoggingSubsystem` first. - private static let hasLoggedNoSubsystemConfiguredFault = AtomicBool(initialValue: false) + private static let hasLoggedNoSubsystemConfiguredFault = Atomic(false) /// The name of the current logging subsystem or `nil` if no logging scope is set. @TaskLocal fileprivate static var _subsystem: String? @@ -35,7 +36,7 @@ public final class LoggingScope { } else if let defaultSubsystem = defaultSubsystem.value { return defaultSubsystem } else { - if !hasLoggedNoSubsystemConfiguredFault.setAndGet(newValue: true) { + if !hasLoggedNoSubsystemConfiguredFault.exchange(true, ordering: .sequentiallyConsistent) { Logger(subsystem: "default", category: "sklogging") .fault( """ diff --git a/Sources/SKLogging/NonDarwinLogging.swift b/Sources/SKLogging/NonDarwinLogging.swift index f56084ac3..9e31c1a7f 100644 --- a/Sources/SKLogging/NonDarwinLogging.swift +++ b/Sources/SKLogging/NonDarwinLogging.swift @@ -10,6 +10,7 @@ // //===----------------------------------------------------------------------===// +import Synchronization @_spi(SourceKitLSP) import ToolsProtocolsSwiftExtensions #if canImport(Darwin) @@ -434,7 +435,7 @@ public struct NonDarwinLogger: Sendable { fileprivate let id: NonDarwinSignpostID } -private let nextSignpostID = AtomicUInt32(initialValue: 0) +private let nextSignpostID = Atomic(0) /// A type that is API-compatible to `OSLogMessage` for all uses within sourcekit-lsp. /// @@ -447,7 +448,7 @@ private let nextSignpostID = AtomicUInt32(initialValue: 0) } @_spi(SourceKitLSP) public func makeSignpostID() -> NonDarwinSignpostID { - return NonDarwinSignpostID(id: nextSignpostID.fetchAndIncrement()) + return NonDarwinSignpostID(id: nextSignpostID.wrappingAdd(1, ordering: .sequentiallyConsistent).oldValue) } @_spi(SourceKitLSP) public func beginInterval( diff --git a/Sources/ToolsProtocolsCAtomics/CAtomics.c b/Sources/ToolsProtocolsCAtomics/CAtomics.c deleted file mode 100644 index f6d1c10c4..000000000 --- a/Sources/ToolsProtocolsCAtomics/CAtomics.c +++ /dev/null @@ -1,11 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2014 - 2025 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// diff --git a/Sources/ToolsProtocolsCAtomics/CMakeLists.txt b/Sources/ToolsProtocolsCAtomics/CMakeLists.txt deleted file mode 100644 index 43ac4e4a2..000000000 --- a/Sources/ToolsProtocolsCAtomics/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -add_library(ToolsProtocolsCAtomics INTERFACE) -target_include_directories(ToolsProtocolsCAtomics INTERFACE "include") - -set_property(GLOBAL APPEND PROPERTY SWIFTTOOLSPROTOCOLS_EXPORTS ToolsProtocolsCAtomics) diff --git a/Sources/ToolsProtocolsCAtomics/include/ToolsProtocolsCAtomics.h b/Sources/ToolsProtocolsCAtomics/include/ToolsProtocolsCAtomics.h deleted file mode 100644 index 2629f0379..000000000 --- a/Sources/ToolsProtocolsCAtomics/include/ToolsProtocolsCAtomics.h +++ /dev/null @@ -1,78 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2014 - 2024 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// - -#ifndef ToolsProtocolsCAtomics_H -#define ToolsProtocolsCAtomics_H - -#include -#include -#include -#include -#include - -typedef struct { - _Atomic(uint32_t) value; -} CAtomicUInt32; - -static inline CAtomicUInt32 *_Nonnull atomic_uint32_create(uint32_t initialValue) { - CAtomicUInt32 *atomic = malloc(sizeof(CAtomicUInt32)); - atomic->value = initialValue; - return atomic; -} - -static inline uint32_t atomic_uint32_get(CAtomicUInt32 *_Nonnull atomic) { - return atomic->value; -} - -static inline uint32_t atomic_uint32_get_and_set(CAtomicUInt32 *_Nonnull atomic, uint32_t newValue) { - return __c11_atomic_exchange(&atomic->value, newValue, __ATOMIC_SEQ_CST); -} - -static inline void atomic_uint32_set(CAtomicUInt32 *_Nonnull atomic, uint32_t newValue) { - atomic->value = newValue; -} - -static inline uint32_t atomic_uint32_fetch_and_increment(CAtomicUInt32 *_Nonnull atomic) { - return atomic->value++; -} - -static inline void atomic_uint32_destroy(CAtomicUInt32 *_Nonnull atomic) { - free(atomic); -} - -typedef struct { - _Atomic(int32_t) value; -} CAtomicInt32; - -static inline CAtomicInt32 *_Nonnull atomic_int32_create(int32_t initialValue) { - CAtomicInt32 *atomic = malloc(sizeof(CAtomicInt32)); - atomic->value = initialValue; - return atomic; -} - -static inline int32_t atomic_int32_get(CAtomicInt32 *_Nonnull atomic) { - return atomic->value; -} - -static inline void atomic_int32_set(CAtomicInt32 *_Nonnull atomic, int32_t newValue) { - atomic->value = newValue; -} - -static inline int32_t atomic_int32_fetch_and_increment(CAtomicInt32 *_Nonnull atomic) { - return atomic->value++; -} - -static inline void atomic_int32_destroy(CAtomicInt32 *_Nonnull atomic) { - free(atomic); -} - -#endif // ToolsProtocolsCAtomics_H diff --git a/Sources/ToolsProtocolsCAtomics/include/module.modulemap b/Sources/ToolsProtocolsCAtomics/include/module.modulemap deleted file mode 100644 index a64c49e73..000000000 --- a/Sources/ToolsProtocolsCAtomics/include/module.modulemap +++ /dev/null @@ -1,4 +0,0 @@ -module ToolsProtocolsCAtomics { - header "ToolsProtocolsCAtomics.h" - export * -} diff --git a/Sources/ToolsProtocolsSwiftExtensions/AsyncUtils.swift b/Sources/ToolsProtocolsSwiftExtensions/AsyncUtils.swift index aecfbafe7..b7f30e078 100644 --- a/Sources/ToolsProtocolsSwiftExtensions/AsyncUtils.swift +++ b/Sources/ToolsProtocolsSwiftExtensions/AsyncUtils.swift @@ -280,7 +280,7 @@ package func withTimeout( body: @escaping @Sendable () async throws -> T, resultReceivedAfterTimeout: @escaping @Sendable (_ result: T) async -> Void ) async throws -> T? { - let didHitTimeout = AtomicBool(initialValue: false) + let didHitTimeout = ThreadSafeBox(initialValue: false) let stream = AsyncThrowingStream { continuation in Task { diff --git a/Sources/ToolsProtocolsSwiftExtensions/Atomics.swift b/Sources/ToolsProtocolsSwiftExtensions/Atomics.swift deleted file mode 100644 index 302e6e7a5..000000000 --- a/Sources/ToolsProtocolsSwiftExtensions/Atomics.swift +++ /dev/null @@ -1,111 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2014 - 2024 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// - -import ToolsProtocolsCAtomics - -// TODO: Use atomic types from the standard library (https://github.com/swiftlang/sourcekit-lsp/issues/1949) -@_spi(SourceKitLSP) public final class AtomicBool: Sendable { - private nonisolated(unsafe) let atomic: UnsafeMutablePointer - - @_spi(SourceKitLSP) public init(initialValue: Bool) { - self.atomic = atomic_uint32_create(initialValue ? 1 : 0) - } - - deinit { - atomic_uint32_destroy(atomic) - } - - @_spi(SourceKitLSP) public var value: Bool { - get { - atomic_uint32_get(atomic) != 0 - } - set { - atomic_uint32_set(atomic, newValue ? 1 : 0) - } - } - - /// Sets the boolean to the new value and returns the previous value. - @_spi(SourceKitLSP) public func setAndGet(newValue: Bool) -> Bool { - return atomic_uint32_get_and_set(atomic, newValue ? 1 : 0) != 0 - } -} - -@_spi(SourceKitLSP) public final class AtomicUInt8: Sendable { - private nonisolated(unsafe) let atomic: UnsafeMutablePointer - - @_spi(SourceKitLSP) public init(initialValue: UInt8) { - self.atomic = atomic_uint32_create(UInt32(initialValue)) - } - - deinit { - atomic_uint32_destroy(atomic) - } - - @_spi(SourceKitLSP) public var value: UInt8 { - get { - UInt8(atomic_uint32_get(atomic)) - } - set { - atomic_uint32_set(atomic, UInt32(newValue)) - } - } -} - -@_spi(SourceKitLSP) public final class AtomicUInt32: Sendable { - private nonisolated(unsafe) let atomic: UnsafeMutablePointer - - @_spi(SourceKitLSP) public init(initialValue: UInt32) { - self.atomic = atomic_uint32_create(initialValue) - } - - @_spi(SourceKitLSP) public var value: UInt32 { - get { - atomic_uint32_get(atomic) - } - set { - atomic_uint32_set(atomic, newValue) - } - } - - deinit { - atomic_uint32_destroy(atomic) - } - - @_spi(SourceKitLSP) public func fetchAndIncrement() -> UInt32 { - return atomic_uint32_fetch_and_increment(atomic) - } -} - -@_spi(SourceKitLSP) public final class AtomicInt32: Sendable { - private nonisolated(unsafe) let atomic: UnsafeMutablePointer - - @_spi(SourceKitLSP) public init(initialValue: Int32) { - self.atomic = atomic_int32_create(initialValue) - } - - @_spi(SourceKitLSP) public var value: Int32 { - get { - atomic_int32_get(atomic) - } - set { - atomic_int32_set(atomic, newValue) - } - } - - deinit { - atomic_int32_destroy(atomic) - } - - @_spi(SourceKitLSP) public func fetchAndIncrement() -> Int32 { - return atomic_int32_fetch_and_increment(atomic) - } -} diff --git a/Sources/ToolsProtocolsSwiftExtensions/CMakeLists.txt b/Sources/ToolsProtocolsSwiftExtensions/CMakeLists.txt index e3963999d..a89ce6546 100644 --- a/Sources/ToolsProtocolsSwiftExtensions/CMakeLists.txt +++ b/Sources/ToolsProtocolsSwiftExtensions/CMakeLists.txt @@ -1,7 +1,6 @@ set(sources AsyncQueue.swift AsyncUtils.swift - Atomics.swift Collection+Only.swift Duration+Seconds.swift FileManagerExtensions.swift @@ -15,16 +14,12 @@ set(sources add_library(ToolsProtocolsSwiftExtensions ${sources}) set_target_properties(ToolsProtocolsSwiftExtensions PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_Swift_MODULE_DIRECTORY}) -target_link_libraries(ToolsProtocolsSwiftExtensions PUBLIC - ToolsProtocolsCAtomics) target_link_libraries(ToolsProtocolsSwiftExtensions PRIVATE $<$>:Foundation>) add_library(_ToolsProtocolsSwiftExtensionsForPlugin ${sources}) set_target_properties(_ToolsProtocolsSwiftExtensionsForPlugin PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_Swift_MODULE_DIRECTORY}) -target_link_libraries(_ToolsProtocolsSwiftExtensionsForPlugin PUBLIC - ToolsProtocolsCAtomics) target_link_libraries(_ToolsProtocolsSwiftExtensionsForPlugin PRIVATE $<$>:Foundation>) From 1ea99da04e0215790e3af182656543676b42ed31 Mon Sep 17 00:00:00 2001 From: Rintaro Ishizaki Date: Thu, 21 May 2026 11:16:02 -0700 Subject: [PATCH 2/2] Choose appropriate atomic memory orderings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous .sequentiallyConsistent ordering on every atomic forced unnecessary barriers (notably dmb ish on ARM). Replace with the minimum ordering each operation actually needs: - ID counters (request/notification/signpost) → .relaxed. Operations only need uniqueness; ordering relative to other memory carries no information. - LoggingScope's "fault logged" once-flag → .relaxed. No associated state rides on the flag. - RequestAndReply.replied → .acquiring on load, .acquiringAndReleasing on exchange. ARC's refcount synchronization in deinit would make .relaxed functionally correct, but acquire/release expresses the operation's intent without leaning on that side-channel. --- .../LanguageServerProtocolTransport/JSONRPCConnection.swift | 2 +- Sources/LanguageServerProtocolTransport/LocalConnection.swift | 2 +- .../QueueBasedMessageHandler.swift | 2 +- Sources/LanguageServerProtocolTransport/RequestAndReply.swift | 4 ++-- Sources/SKLogging/LoggingScope.swift | 2 +- Sources/SKLogging/NonDarwinLogging.swift | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Sources/LanguageServerProtocolTransport/JSONRPCConnection.swift b/Sources/LanguageServerProtocolTransport/JSONRPCConnection.swift index 4c8cfae9c..fd4d38630 100644 --- a/Sources/LanguageServerProtocolTransport/JSONRPCConnection.swift +++ b/Sources/LanguageServerProtocolTransport/JSONRPCConnection.swift @@ -598,7 +598,7 @@ public final class JSONRPCConnection: Connection { /// Request id for the next outgoing request. public func nextRequestID() -> RequestID { - return .string("sk-\(nextRequestIDStorage.wrappingAdd(1, ordering: .sequentiallyConsistent).oldValue)") + return .string("sk-\(nextRequestIDStorage.wrappingAdd(1, ordering: .relaxed).oldValue)") } // MARK: Connection interface diff --git a/Sources/LanguageServerProtocolTransport/LocalConnection.swift b/Sources/LanguageServerProtocolTransport/LocalConnection.swift index a5773e1ad..20ea28afe 100644 --- a/Sources/LanguageServerProtocolTransport/LocalConnection.swift +++ b/Sources/LanguageServerProtocolTransport/LocalConnection.swift @@ -88,7 +88,7 @@ public final class LocalConnection: Connection, Sendable { } public func nextRequestID() -> RequestID { - return .string("sk-\(_nextRequestID.wrappingAdd(1, ordering: .sequentiallyConsistent).oldValue)") + return .string("sk-\(_nextRequestID.wrappingAdd(1, ordering: .relaxed).oldValue)") } public func send(_ notification: Notification) { diff --git a/Sources/LanguageServerProtocolTransport/QueueBasedMessageHandler.swift b/Sources/LanguageServerProtocolTransport/QueueBasedMessageHandler.swift index 0d22934d5..42f19f76c 100644 --- a/Sources/LanguageServerProtocolTransport/QueueBasedMessageHandler.swift +++ b/Sources/LanguageServerProtocolTransport/QueueBasedMessageHandler.swift @@ -108,7 +108,7 @@ public final class QueueBasedMessageHandlerHelper: Sendable { // Only use the last two digits of the notification ID for the logging scope to avoid creating too many scopes. // See comment in `withLoggingScope`. // The last 2 digits should be sufficient to differentiate between multiple concurrently running notifications. - let notificationID = notificationIDForLogging.wrappingAdd(1, ordering: .sequentiallyConsistent).oldValue + let notificationID = notificationIDForLogging.wrappingAdd(1, ordering: .relaxed).oldValue withLoggingScope("notification-\(notificationID % 100)") { body() } diff --git a/Sources/LanguageServerProtocolTransport/RequestAndReply.swift b/Sources/LanguageServerProtocolTransport/RequestAndReply.swift index 1f1deedaa..ab224da45 100644 --- a/Sources/LanguageServerProtocolTransport/RequestAndReply.swift +++ b/Sources/LanguageServerProtocolTransport/RequestAndReply.swift @@ -31,12 +31,12 @@ public final class RequestAndReply: Sendable { } deinit { - precondition(replied.load(ordering: .sequentiallyConsistent), "request never received a reply") + precondition(replied.load(ordering: .acquiring), "request never received a reply") } /// Call the `replyBlock` with the result produced by the given closure. public func reply(_ body: () async throws -> Params.Response) async { - let didReply = replied.exchange(true, ordering: .sequentiallyConsistent) + let didReply = replied.exchange(true, ordering: .acquiringAndReleasing) precondition(!didReply, "replied to request more than once") do { reply(.success(try await body())) diff --git a/Sources/SKLogging/LoggingScope.swift b/Sources/SKLogging/LoggingScope.swift index 3e3e6a523..923e19e93 100644 --- a/Sources/SKLogging/LoggingScope.swift +++ b/Sources/SKLogging/LoggingScope.swift @@ -36,7 +36,7 @@ public final class LoggingScope { } else if let defaultSubsystem = defaultSubsystem.value { return defaultSubsystem } else { - if !hasLoggedNoSubsystemConfiguredFault.exchange(true, ordering: .sequentiallyConsistent) { + if !hasLoggedNoSubsystemConfiguredFault.exchange(true, ordering: .relaxed) { Logger(subsystem: "default", category: "sklogging") .fault( """ diff --git a/Sources/SKLogging/NonDarwinLogging.swift b/Sources/SKLogging/NonDarwinLogging.swift index 9e31c1a7f..764bb8db4 100644 --- a/Sources/SKLogging/NonDarwinLogging.swift +++ b/Sources/SKLogging/NonDarwinLogging.swift @@ -448,7 +448,7 @@ private let nextSignpostID = Atomic(0) } @_spi(SourceKitLSP) public func makeSignpostID() -> NonDarwinSignpostID { - return NonDarwinSignpostID(id: nextSignpostID.wrappingAdd(1, ordering: .sequentiallyConsistent).oldValue) + return NonDarwinSignpostID(id: nextSignpostID.wrappingAdd(1, ordering: .relaxed).oldValue) } @_spi(SourceKitLSP) public func beginInterval(