Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NIOLock and NIOLockedValueBox are too strict #2910

Open
Lukasa opened this issue Oct 9, 2024 · 4 comments
Open

NIOLock and NIOLockedValueBox are too strict #2910

Lukasa opened this issue Oct 9, 2024 · 4 comments
Labels
kind/bug Feature doesn't work as expected. size/S Small task. (A couple of hours of work.)

Comments

@Lukasa
Copy link
Contributor

Lukasa commented Oct 9, 2024

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.

@Lukasa Lukasa added the kind/bug Feature doesn't work as expected. label Oct 9, 2024
@FranzBusch
Copy link
Member

Yep good catch. We need to basically copy the API from Mutex on the LockedValueBox here

@FranzBusch FranzBusch added the size/S Small task. (A couple of hours of work.) label Oct 10, 2024
@weissi
Copy link
Member

weissi commented Oct 10, 2024

@Lukasa Why does NIOLock.withLock need sending? It doesn't contain a value (so there's nothing to escape) and it never changes isolation or anything (no async etc).

And NIOLockedValueBox is currently only Sendable iff Value: Sendable, so that seems fine too as it can be escaped safely.


Said all that, it might be useful for developers if they were sending (just in case they want to pass an isolated closure). But I don't see a not-strict-enough issue here.

@weissi
Copy link
Member

weissi commented Oct 11, 2024

I think we should reverb this ticket as it's currently written confusingly. My summary would be:

  • Most importantly: NIOLockedValueBox as well as NIOLock are correct regarding sendability etc
  • NIOLock should stay is as and should not get a sending in withLock (as that would make it less useful)
  • NIOLockedValueBox is more strict than it needs to be as of Swift 6.0. It could be even more helpful if it took sending closures as that would allow us to make it unconditionally Sendable.

@weissi
Copy link
Member

weissi commented Oct 15, 2024

@Lukasa can we close this bug or retitle to "NIOLockedValueBox too strict"?

@Lukasa Lukasa changed the title NIOLock and NIOLockedValueBox aren't strict enough NIOLock and NIOLockedValueBox are too strict Oct 16, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind/bug Feature doesn't work as expected. size/S Small task. (A couple of hours of work.)
Projects
None yet
Development

No branches or pull requests

3 participants