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

Full compatibility with -strict-concurrency=complete #125

Open
wants to merge 6 commits into
base: main
Choose a base branch
from

Conversation

MahdiBM
Copy link

@MahdiBM MahdiBM commented Jul 28, 2023

These changes will make leaf-kit fully compatible with -strict-concurrency=complete.

Copy link
Member

@gwynne gwynne left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See comments, also I'm not really happy with the SendableBox, too many locks... but I don't know that I have any better suggestions. This package is easily the worst mess left in Vapor now that Fluent and some other things have been cleaned up some...

Sources/LeafKit/Exports.swift Outdated Show resolved Hide resolved
Comment on lines 7 to 31

var __isEnabled = true
/// Global setting for enabling or disabling the cache
public var isEnabled: Bool = true
public var _isEnabled: Bool {
get {
self.lock.withLock {
self.__isEnabled
}
}
set(newValue) {
self.lock.withLock {
self.__isEnabled = newValue
}
}
}
/// Global setting for enabling or disabling the cache
public var isEnabled: Bool {
get {
self._isEnabled
}
set(newValue) {
self._isEnabled = newValue
}
}
/// Current count of cached documents
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why two layers of indirection?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i assume compiler will take care of that anyway... two levels to not use self.lock.withLock 2 more times, which is also less code.

Copy link
Member

@0xTim 0xTim left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should add the flag as a step in CI too

import NIOConcurrencyHelpers

/// Uses a locking mechanism to ensure Sendability.
internal final class SendableBox<Value>: @unchecked Sendable {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are we not using the NIO helpers? This doesn't make un-Sendable objects Sendable unfortunately as I've learn't the hard way

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What types are you thinking of? I don't think we can use types like NIOLoopBound since it requires an eventloop

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At least not everywhere. Like in global vars.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NIOLockedValueBox or NIOLockedBox

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I forgot to add a Value: Sendable constraint. I assume that solves most of the problems?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use NIOLockedValueBox then rather than rolling our own. This will cause issues with userInfo as I'm sure you'll see

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah ... the usual problem of outdated comments.
yeah i didn't remember that type exists.

@@ -25,9 +25,12 @@ public final class LeafRenderer {
public let sources: LeafSources
/// The NIO `EventLoop` on which this instance of `LeafRenderer` will operate
public let eventLoop: EventLoop
let _userInfo: SendableBox<[AnyHashable: Any]>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't do what you think it does. The only way we can make Any Sendable is by tying this to an event loop

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense ... even with a Value: Sendable constraint it is still showing warnings.
Not sure what exactly to do though.
We need to change Any -> any Sendable as well as somehow conforming AnyHashable to Sendable.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Though not sure what an event loop does that the locking mechanism can't ... I'm tempted to ask in the OpenSource slack.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The documentation of NIOLoopBound does mention why...

@MahdiBM
Copy link
Author

MahdiBM commented Jul 28, 2023

@gwynne should the reusable CI have an option for strict concurrency checking? (automatically set to complete, or with the option for users to set the flag to values like targeted/complete)

public let userInfo: [AnyHashable: Any]

public var userInfo: [AnyHashable: Any] {
_userInfo.value
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will this crash on access by users on another eventLoop?

@MahdiBM
Copy link
Author

MahdiBM commented Jul 28, 2023

NIOLoopBound crashing in CI .... not sure what to do with the dictionary.

@MahdiBM
Copy link
Author

MahdiBM commented Aug 1, 2023

It appears for a dictionary like that, Foundation itself just uses @unchecked Sendable while using a lock and also the _modify accessor (not sure if _modify helps for Sendability at all): userInfo, @unchecked Sendable.

@0xTim
Copy link
Member

0xTim commented Aug 1, 2023

Err @fabianfett that's wrong right?

@MahdiBM the issue is if you store something that's not Sendable in the dictionary and store a reference to it then something outside of the context can mutate it at the same time and so 💥

@MahdiBM
Copy link
Author

MahdiBM commented Aug 1, 2023

Yeah it's suboptimal, but it's something 😅

@0xTim
Copy link
Member

0xTim commented Aug 1, 2023

Nah it's really bad as Fabian explained to me 😅 essentially you go from the compiler giving you a warning saying this might be a problem to the user to the compiler completely removing that warning so the end user never knows. I'd rather have a dictionary that takes a Sendable type and pass the warning on to the user

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants