-
Notifications
You must be signed in to change notification settings - Fork 43
Update WorkQueue.queue to be a reference type instead of an array. #194
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -77,12 +77,33 @@ private struct BackgroundWorkItem { | |
// We can't use Mutex directly here because we need the underlying `pthread_mutex_t` to be | ||
// exposed so we can use it with `pthread_cond_wait`. | ||
private final class WorkQueue: Sendable { | ||
private nonisolated(unsafe) var queue: [BackgroundWorkItem] | ||
// Queue needs to be a reference type because we pass it inout | ||
final class Queue: Sendable { | ||
internal nonisolated(unsafe) var queue: [BackgroundWorkItem] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is incorrect because this type isn't Sendable. It allows mutation without synchronousiarion. furthermore, the reference gets passed inout. We should also add a test that shows where precisely you need reference semantics and why There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
This type is exclusively used under a pthread_mutex_t. It is for that reason
I don't quite understand what do you mean. Could you suggest a test? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I get that this is intent but we should prove this to the compiler and not use
I assume that the reason for this pull request is that something didn't work as expected. The test should test that before it doesn't work as expected but now (with this change) it does. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
We can't use
This change resolves issue #182. Currently, the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Okay, but if you build a general purpose work queue, then I'd suggest
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looking at this code, it looks like Is my understanding correct? If so, then I tend to agree that marking this type private nonisolated(unsafe) var queue: Queue There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My position is: Anything A narrow exception is if you're creating new, reusable components (such as a generic queue) with an extensive test suite that cannot be used unsafely through their API, then that's fine. For example, AsyncProcess doesn't contain |
||
|
||
var isEmpty: Bool { self.queue.isEmpty } | ||
|
||
func append(_ item: BackgroundWorkItem) { | ||
self.queue.append(item) | ||
} | ||
|
||
func removeFirst() -> BackgroundWorkItem { | ||
return self.queue.removeFirst() | ||
} | ||
|
||
func removeAll() { self.queue.removeAll() } | ||
|
||
init() { | ||
self.queue = [] | ||
} | ||
} | ||
|
||
private nonisolated(unsafe) var queue: Queue | ||
internal nonisolated(unsafe) let mutex: UnsafeMutablePointer<MutexType> | ||
internal nonisolated(unsafe) let waitCondition: UnsafeMutablePointer<ConditionType> | ||
|
||
init() { | ||
self.queue = [] | ||
self.queue = Queue() | ||
self.mutex = UnsafeMutablePointer<MutexType>.allocate(capacity: 1) | ||
self.waitCondition = UnsafeMutablePointer<ConditionType>.allocate(capacity: 1) | ||
#if canImport(WinSDK) | ||
|
@@ -94,14 +115,14 @@ private final class WorkQueue: Sendable { | |
#endif | ||
} | ||
|
||
func withLock<R>(_ body: (inout [BackgroundWorkItem]) throws -> R) rethrows -> R { | ||
func withLock<R>(_ body: (inout Queue) throws -> R) rethrows -> R { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What's the point of using inout anymore if it's a reference type? |
||
try withUnsafeUnderlyingLock { _, queue in | ||
try body(&queue) | ||
} | ||
} | ||
|
||
private func withUnsafeUnderlyingLock<R>( | ||
_ body: (UnsafeMutablePointer<MutexType>, inout [BackgroundWorkItem]) throws -> R | ||
_ body: (UnsafeMutablePointer<MutexType>, inout Queue) throws -> R | ||
) rethrows -> R { | ||
#if canImport(WinSDK) | ||
EnterCriticalSection(self.mutex) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add
Invoke-Program swift test -c release
below this line so we have release coverage for Windows as well?