Skip to content

Rename AsyncQueue -> FIFOQueue. Create ActorQueue #3

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

Merged
merged 43 commits into from
Jan 8, 2023
Merged

Conversation

dfed
Copy link
Owner

@dfed dfed commented Nov 24, 2022

I realized that our AsyncQueue is really a FIFOQueue, and that consumers may desire a queue which maintains task execution order when interacting with an actor but allows for reentrancy and re-ordering of tasks due to suspension.

This realization led to the creation of an ActorQueue. This queue is purpose-built to send ordered, asynchronous work to actor instances from a non-isolated context/

Reviewers should feel free to question the type and method names within this PR. I could use another brain here.


// MARK: - Semaphore

private actor Semaphore {
Copy link
Owner Author

@dfed dfed Nov 24, 2022

Choose a reason for hiding this comment

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

This Semaphore implementation was moved to its own file without changes beyond its accessibility level.


// MARK: - Counter

private actor Counter {
Copy link
Owner Author

@dfed dfed Nov 24, 2022

Choose a reason for hiding this comment

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

This Counter implementation was moved to its own file without changes beyond its accessibility level.

@dfed dfed force-pushed the dfed--fifo-vs-actor branch from dd1819e to 0315eca Compare November 24, 2022 05:51
@codecov
Copy link

codecov bot commented Nov 24, 2022

Codecov Report

Merging #3 (bf3a0c2) into main (b09b217) will not change coverage.
The diff coverage is 100.00%.

Impacted file tree graph

@@            Coverage Diff            @@
##              main        #3   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files            1         2    +1     
  Lines           39        95   +56     
=========================================
+ Hits            39        95   +56     
Impacted Files Coverage Δ
Sources/AsyncQueue/FIFOQueue.swift 100.00% <ø> (ø)
Sources/AsyncQueue/ActorQueue.swift 100.00% <100.00%> (ø)

@dfed dfed force-pushed the dfed--fifo-vs-actor branch 3 times, most recently from efc1dd3 to 2957e19 Compare November 24, 2022 07:28
@dfed dfed marked this pull request as ready for review November 24, 2022 07:32
@dfed dfed requested review from bachand and Gabardone November 24, 2022 07:32
@dfed dfed force-pushed the dfed--fifo-vs-actor branch 2 times, most recently from 54db140 to bd3a337 Compare November 24, 2022 15:06
@dfed dfed force-pushed the dfed--create-async-queue branch from a458835 to ec8838a Compare November 24, 2022 15:08
@dfed dfed force-pushed the dfed--fifo-vs-actor branch 2 times, most recently from 3be98e5 to dfd4e80 Compare November 24, 2022 15:11
@dfed dfed mentioned this pull request Nov 24, 2022
Base automatically changed from dfed--create-async-queue to main November 28, 2022 01:12
@dfed dfed force-pushed the dfed--fifo-vs-actor branch from dfd4e80 to 67910a7 Compare November 28, 2022 01:13
@dfed
Copy link
Owner Author

dfed commented Nov 28, 2022

Force push was rebasing develop


@testable import AsyncQueue

final class SemaphoreTests: XCTestCase {
Copy link
Owner Author

Choose a reason for hiding this comment

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

These tests are no longer required as part of this PR since Semaphore is no longer living in the Sources directory. I'll remove them shortly and put up a separate PR to add them. They're explicitly a nice-to-have now, though I think it's helpful to have examples of async tests like the below.

@dfed dfed mentioned this pull request Dec 10, 2022
@dfed
Copy link
Owner Author

dfed commented Dec 10, 2022

Apologies for the multiple rounds of revisions here. @bachand @Gabardone this PR is once again ready for another review!


@testable import AsyncQueue

final class ActorQueueTests: XCTestCase {
Copy link
Owner Author

Choose a reason for hiding this comment

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

When reviewing this file, it's worth comparing these tests to the ones in FIFOQueueTests

Copy link
Collaborator

@bachand bachand left a comment

Choose a reason for hiding this comment

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

Nice work @dfed !

README.md Outdated

```swift
let asyncQueue = AsyncQueue()
```
Copy link
Collaborator

Choose a reason for hiding this comment

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

Very useful. Thanks for including this.

Copy link
Owner Author

Choose a reason for hiding this comment

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

Thanks for the prompt to do so!

/*
`async` context that can return a value or throw an error.
Executes after all other enqueued work has begun executing.
Work enqueued after this task will wait for this task to complete or suspend.
Copy link
Collaborator

Choose a reason for hiding this comment

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

👍

///
/// An `ActorQueue` is used to ensure tasks sent from a nonisolated context to a single `actor`'s isolated context begin execution in order.
/// Here is an example of how an `ActorQueue` should be utilized within an `actor`:
/// ```
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
/// ```
/// ```swift

Copy link
Owner Author

@dfed dfed Jan 8, 2023

Choose a reason for hiding this comment

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

Good catch! bf3a0c2

/// The scheduled task will not execute until all prior tasks have completed or suspended.
/// - Parameter task: The task to enqueue.
/// - Returns: The value returned from the enqueued task.
public func await<T>(_ task: @escaping @Sendable () async throws -> T) async throws -> T {
Copy link
Collaborator

Choose a reason for hiding this comment

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

If this function is accepts a throwing task should the above one accept a throwing task too?

Copy link
Owner Author

Choose a reason for hiding this comment

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

Ideally we'd use rethrows here so we only need to declare one method, however I couldn't get rethrows to work here: there's no way today (that I know of) to signal to the compiler that we're only going to throw within withUnsafeThrowingContinuation if and only if the task throws. So I created one method that can throw and one that can't.

Comment on lines +56 to +57
// If the actor queue were FIFO, this test would hang since this code would never execute:
// we'd still be waiting for the prior `wait()` tasks to finish.
Copy link
Collaborator

Choose a reason for hiding this comment

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

👍

@dfed dfed enabled auto-merge (squash) January 8, 2023 23:19
@dfed dfed merged commit d08ed02 into main Jan 8, 2023
@dfed dfed deleted the dfed--fifo-vs-actor branch January 8, 2023 23:20
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.

3 participants