Repository: apple/swift-nio
File: Sources/NIOEmbedded/AsyncTestingChannel.swift (Swift)

Code before:
        set {
            self.stateLock.withLockedValue {
                $0.localAddress = newValue
            }
        }
    }

    /// - see: `Channel.remoteAddress`
    public var remoteAddress: SocketAddress? {
        get {
            self.stateLock.withLockedValue { $0.remoteAddress }
        }
        set {
            self.stateLock.withLockedValue {
                $0.remoteAddress = newValue
            }
        }
    }

    public var options: [(option: any ChannelOption, value: any Sendable)] {
        get {
            self.stateLock.withLockedValue { $0.options }
        }
        set {
            self.stateLock.withLockedValue { $0.options = newValue }
        }
    }

    /// Create a new instance.
    ///
    /// During creation it will automatically also register itself on the ``NIOAsyncTestingEventLoop``.
    ///
    /// - Parameters:
    ///   - loop: The ``NIOAsyncTestingEventLoop`` to use.
    public init(loop: NIOAsyncTestingEventLoop = NIOAsyncTestingEventLoop()) {
        self.testingEventLoop = loop
        self._pipeline = ChannelPipeline(channel: self)
        self.channelcore = EmbeddedChannelCore(pipeline: self._pipeline, eventLoop: self.eventLoop)
    }

    /// Create a new instance.
    ///
    /// During creation it will automatically also register itself on the ``NIOAsyncTestingEventLoop``.
    ///
    /// - Parameters:
    ///   - handler: The `ChannelHandler` to add to the `ChannelPipeline` before register.
    ///   - loop: The ``NIOAsyncTestingEventLoop`` to use.
    @preconcurrency
    public convenience init(
        handler: ChannelHandler & Sendable,
        loop: NIOAsyncTestingEventLoop = NIOAsyncTestingEventLoop()

Review comment (suggestion):
This probably doesn't need a public setter, which is good, because this pattern is prone to weird ABA problems.

Code after:
    public var localAddress: SocketAddress? {
        get {
            self._stateLock.withLockedValue { $0.localAddress }
        }
        set {
            self._stateLock.withLockedValue {
                $0.localAddress = newValue
            }
        }
    }

    /// - see: `Channel.remoteAddress`
    public var remoteAddress: SocketAddress? {
        get {
            self._stateLock.withLockedValue { $0.remoteAddress }
        }
        set {
            self._stateLock.withLockedValue {
                $0.remoteAddress = newValue
            }
        }
    }

    /// The `ChannelOption`s set on this channel.
    /// - see: `NIOAsyncTestingChannel.setOption`
    public var options: [(option: any ChannelOption, value: any Sendable)] {
        self._stateLock.withLockedValue { $0.options }
    }
    /// Create a new instance.
    ///
    /// During creation it will automatically also register itself on the ``NIOAsyncTestingEventLoop``.
    ///
    /// - Parameters:
    ///   - loop: The ``NIOAsyncTestingEventLoop`` to use.
    public init(loop: NIOAsyncTestingEventLoop = NIOAsyncTestingEventLoop()) {
        self.testingEventLoop = loop
        self._pipeline = ChannelPipeline(channel: self)
        self.channelcore = EmbeddedChannelCore(pipeline: self._pipeline, eventLoop: self.eventLoop)
    }

    /// Create a new instance.
    ///
    /// During creation it will automatically also register itself on the ``NIOAsyncTestingEventLoop``.
    ///
    /// - Parameters:
    ///   - handler: The `ChannelHandler` to add to the `ChannelPipeline` before register.
    ///   - loop: The ``NIOAsyncTestingEventLoop`` to use.
    @preconcurrency
    public convenience init(
        handler: ChannelHandler & Sendable,
        loop: NIOAsyncTestingEventLoop = NIOAsyncTestingEventLoop()