Use `swift-atomics` instead of `NIOAtomics` (#153)
This commit is contained in:
parent
605f7a4c55
commit
94645c8fcd
|
|
@ -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"),
|
||||
]),
|
||||
]
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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(())
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue