Skip to content

NIOLock and NIOLockedValueBox are too strict #2910

Open
@Lukasa

Description

@Lukasa

NIOLock is particularly scary, but NIOLockedValueBox has some limitations too that need to be tidied up.

The following functions are dangerous:

extension NIOLock {
/// Acquire the lock for the duration of the given block.
///
/// This convenience method should be preferred to `lock` and `unlock` in
/// most situations, as it ensures that the lock will be released regardless
/// of how `body` exits.
///
/// - Parameter body: The block to execute while holding the lock.
/// - Returns: The value returned by the block.
@inlinable
public func withLock<T>(_ body: () throws -> T) rethrows -> T {
self.lock()
defer {
self.unlock()
}
return try body()
}
@inlinable
public func withLockVoid(_ body: () throws -> Void) rethrows {
try self.withLock(body)
}
}

Here, withLock needs to take its closure sending and the return value needs to be sending too. In Swift 5, these both need to be Sendable, with an unchecked version available.

/// Access the `Value`, allowing mutation of it.
@inlinable
public func withLockedValue<T>(_ mutate: (inout Value) throws -> T) rethrows -> T {
try self._storage.withLockedValue(mutate)
}

Here, withLockedValue needs again to take its closure sending. Optionally, we could relax its Sendable requirement, and also return the value sending, but given our need to remain compatible with Swift 5 we should probably leave it stricter for now. In Swift 5, the closure probably needs to be @Sendable.

Metadata

Metadata

Assignees

No one assigned

    Labels

    kind/bugFeature doesn't work as expected.size/SSmall task. (A couple of hours of work.)

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions