Use `swift-atomics` instead of `NIOAtomics` (#153)

This commit is contained in:
David Nadoba 2022-07-07 18:50:28 +02:00 committed by GitHub
parent 605f7a4c55
commit 94645c8fcd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 30 additions and 23 deletions

View File

@ -22,6 +22,7 @@ let package = Package(
],
dependencies: [
.package(url: "https://github.com/apple/swift-nio.git", from: "2.32.0"),
.package(url: "https://github.com/apple/swift-atomics.git", from: "1.0.2"),
],
targets: [
.target(
@ -30,8 +31,8 @@ let package = Package(
.product(name: "NIO", package: "swift-nio"),
.product(name: "NIOCore", package: "swift-nio"),
.product(name: "NIOFoundationCompat", package: "swift-nio"),
.product(name: "NIOConcurrencyHelpers", package: "swift-nio"),
.product(name: "NIOTLS", package: "swift-nio"),
.product(name: "Atomics", package: "swift-atomics"),
]),
.executableTarget(
name: "NIOTSHTTPClient",
@ -53,7 +54,7 @@ let package = Package(
"NIOTransportServices",
.product(name: "NIOCore", package: "swift-nio"),
.product(name: "NIOEmbedded", package: "swift-nio"),
.product(name: "NIOConcurrencyHelpers", package: "swift-nio"),
.product(name: "Atomics", package: "swift-atomics"),
]),
]
)

View File

@ -21,6 +21,7 @@ import NIOTLS
import Dispatch
import Network
import Security
import Atomics
/// Channel options for the connection channel.
@available(OSX 10.14, iOS 12.0, tvOS 12.0, watchOS 6.0, *)
@ -66,7 +67,7 @@ private struct BackpressureManager {
/// because in most cases these loads/stores will be free, as the user will never actually check the
/// channel writability from another thread, meaning this cache line is uncontended. CAS is never free:
/// it always has some substantial runtime cost over loads/stores.
let writable = NIOAtomic<Bool>.makeAtomic(value: true)
let writable = ManagedAtomic(true)
/// The number of bytes outstanding on the network.
private var outstandingBytes: Int = 0
@ -82,8 +83,8 @@ private struct BackpressureManager {
/// - returns: Whether the state changed.
mutating func writabilityChanges(whenQueueingBytes newBytes: Int) -> Bool {
self.outstandingBytes += newBytes
if self.outstandingBytes > self.waterMarks.high && self.writable.load() {
self.writable.store(false)
if self.outstandingBytes > self.waterMarks.high && self.writable.load(ordering: .relaxed) {
self.writable.store(false, ordering: .relaxed)
return true
}
@ -98,8 +99,8 @@ private struct BackpressureManager {
/// - returns: Whether the state changed.
mutating func writabilityChanges(whenBytesSent sentBytes: Int) -> Bool {
self.outstandingBytes -= sentBytes
if self.outstandingBytes < self.waterMarks.low && !self.writable.load() {
self.writable.store(true)
if self.outstandingBytes < self.waterMarks.low && !self.writable.load(ordering: .relaxed) {
self.writable.store(true, ordering: .relaxed)
return true
}
@ -113,14 +114,14 @@ private struct BackpressureManager {
/// - waterMarks: The new waterMarks to use.
/// - returns: Whether the state changed.
mutating func writabilityChanges(whenUpdatingWaterMarks waterMarks: ChannelOptions.Types.WriteBufferWaterMark) -> Bool {
let writable = self.writable.load()
let writable = self.writable.load(ordering: .relaxed)
self.waterMarks = waterMarks
if writable && self.outstandingBytes > self.waterMarks.high {
self.writable.store(false)
self.writable.store(false, ordering: .relaxed)
return true
} else if !writable && self.outstandingBytes < self.waterMarks.low {
self.writable.store(true)
self.writable.store(true, ordering: .relaxed)
return true
}
@ -169,7 +170,7 @@ internal final class NIOTSConnectionChannel {
internal var state: ChannelState<ActiveSubstate> = .idle
/// The active state, used for safely reporting the channel state across threads.
internal var isActive0: NIOAtomic<Bool> = .makeAtomic(value: false)
internal var isActive0 = ManagedAtomic(false)
/// The kinds of channel activation this channel supports
internal let supportedActivationType: ActivationType = .connect
@ -265,7 +266,7 @@ extension NIOTSConnectionChannel: Channel {
/// Whether this channel is currently writable.
public var isWritable: Bool {
return self.backpressureManager.writable.load()
return self.backpressureManager.writable.load(ordering: .relaxed)
}
public var _channelCore: ChannelCore {

View File

@ -18,6 +18,7 @@ import NIOCore
import NIOConcurrencyHelpers
import Dispatch
import Network
import Atomics
/// An `EventLoopGroup` containing `EventLoop`s specifically designed for use with
@ -47,7 +48,7 @@ import Network
/// preferred networking backend.
@available(OSX 10.14, iOS 12.0, tvOS 12.0, watchOS 6.0, *)
public final class NIOTSEventLoopGroup: EventLoopGroup {
private let index = NIOAtomic<Int>.makeAtomic(value: 0)
private let index = ManagedAtomic(0)
private let eventLoops: [NIOTSEventLoop]
public init(loopCount: Int = 1, defaultQoS: DispatchQoS = .default) {
@ -56,7 +57,7 @@ public final class NIOTSEventLoopGroup: EventLoopGroup {
}
public func next() -> EventLoop {
return self.eventLoops[abs(index.add(1) % self.eventLoops.count)]
return self.eventLoops[abs(index.loadThenWrappingIncrement(ordering: .relaxed) % self.eventLoops.count)]
}
/// Shuts down all of the event loops, rendering them unable to perform further work.

View File

@ -19,6 +19,7 @@ import NIOFoundationCompat
import NIOConcurrencyHelpers
import Dispatch
import Network
import Atomics
@available(OSX 10.14, iOS 12.0, tvOS 12.0, watchOS 6.0, *)
internal final class NIOTSListenerChannel {
@ -63,7 +64,7 @@ internal final class NIOTSListenerChannel {
internal let supportedActivationType: ActivationType = .bind
/// The active state, used for safely reporting the channel state across threads.
internal var isActive0: NIOAtomic<Bool> = .makeAtomic(value: false)
internal var isActive0 = ManagedAtomic(false)
/// Whether a call to NWListener.receive has been made, but the completion
/// handler has not yet been invoked.

View File

@ -19,6 +19,7 @@ import NIOFoundationCompat
import NIOConcurrencyHelpers
import Dispatch
import Network
import Atomics
/// An object that conforms to this protocol represents the substate of a channel in the
@ -102,7 +103,7 @@ internal protocol StateManagedChannel: Channel, ChannelCore {
var state: ChannelState<ActiveSubstate> { get set }
var isActive0: NIOAtomic<Bool> { get set }
var isActive0: ManagedAtomic<Bool> { get set }
var tsEventLoop: NIOTSEventLoop { get }
@ -131,7 +132,7 @@ extension StateManagedChannel {
/// Whether this channel is currently active.
public var isActive: Bool {
return self.isActive0.load()
return self.isActive0.load(ordering: .relaxed)
}
/// Whether this channel is currently closed. This is not necessary for the public
@ -201,7 +202,7 @@ extension StateManagedChannel {
return
}
self.isActive0.store(false)
self.isActive0.store(false, ordering: .relaxed)
self.doClose0(error: error)
@ -247,7 +248,7 @@ extension StateManagedChannel {
return
}
self.isActive0.store(true)
self.isActive0.store(true, ordering: .relaxed)
promise?.succeed(())
self.pipeline.fireChannelActive()
self.readIfNeeded0()

View File

@ -13,6 +13,7 @@
//===----------------------------------------------------------------------===//
#if canImport(Network)
import Atomics
import XCTest
import Network
import NIOCore
@ -128,10 +129,10 @@ final class NIOTSBootstrapTests: XCTestCase {
}
let group = NIOTSEventLoopGroup()
func makeServer(isTLS: EventLoopPromise<Bool>) throws -> Channel {
let numberOfConnections = NIOAtomic<Int>.makeAtomic(value: 0)
let numberOfConnections = ManagedAtomic(0)
return try NIOTSListenerBootstrap(group: group)
.childChannelInitializer { channel in
XCTAssertEqual(0, numberOfConnections.add(1))
XCTAssertEqual(0, numberOfConnections.loadThenWrappingIncrement(ordering: .relaxed))
return channel.pipeline.addHandler(TellMeIfConnectionIsTLSHandler(isTLS: isTLS))
}
.bind(host: "127.0.0.1", port: 0)

View File

@ -13,6 +13,7 @@
//===----------------------------------------------------------------------===//
#if canImport(Network)
import Atomics
import XCTest
import NIOCore
import NIOConcurrencyHelpers
@ -101,11 +102,11 @@ class NIOTSEventLoopTest: XCTestCase {
weakELG = group
weakEL = group.next()
let counter = NIOAtomic<Int>.makeAtomic(value: 0)
let counter = ManagedAtomic(0)
let acceptedChan = group.next().makePromise(of: Channel.self)
let server = try NIOTSListenerBootstrap(group: group)
.childChannelInitializer { channel in
XCTAssertEqual(0, counter.add(1))
XCTAssertEqual(0, counter.loadThenWrappingIncrement(ordering: .relaxed))
acceptedChan.succeed(channel)
return channel.eventLoop.makeSucceededFuture(())
}