Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -156,8 +156,16 @@ purpose, it has not landed in Swift.

Some asynchronous code is [notoriously difficult][reliably-testing-swift-concurrency] to test in
Swift due to how suspension points are processed by the runtime. The library comes with a static
function, `withMainSerialExecutor`, that runs all tasks spawned in an operation serially and
deterministically. This function can be used to make asynchronous tests faster and less flakey.
function, `withMainSerialExecutor`, that attempts to run all tasks spawned in an operation serially
and deterministically. This function can be used to make asynchronous tests faster and less flakey.

> **Warning**: This API is only intended to be used from tests to make them more reliable. Please do
> not use it from application code.
>
> We say that it "_attempts_ to run all tasks spawned in an operation serially and
> deterministically" because under the hood it relies on a global, mutable variable in the Swift
> runtime to do its job, and there are no scoping _guarantees_ should this mutable variable change
> during the operation.

For example, consider the following seemingly simple model that makes a network request and manages
so `isLoading` state while the request is inflight:
Expand Down
14 changes: 11 additions & 3 deletions Sources/ConcurrencyExtras/MainSerialExecutor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,24 @@
///
/// Some asynchronous code is [notoriously
/// difficult](https://forums.swift.org/t/reliably-testing-code-that-adopts-swift-concurrency/57304)
/// to test in Swift due to how suspension points are processed by the runtime. This function runs
/// all tasks spawned in the given operation serially and deterministically. It makes asynchronous
/// tests faster and less flakey.
/// to test in Swift due to how suspension points are processed by the runtime. This function
/// attempts to run all tasks spawned in the given operation serially and deterministically. It
/// makes asynchronous tests faster and less flakey.
///
/// ```swift
/// await withMainSerialExecutor {
/// // Everything performed in this scope is performed serially...
/// }
/// ```
///
/// > Warning: This API is only intended to be used from tests to make them more reliable. Please do
/// > not use it from application code.
/// >
/// > We say that it "_attempts_ to run all tasks spawned in an operation serially and
/// > deterministically" because under the hood it relies on a global, mutable variable in the Swift
/// > runtime to do its job, and there are no scoping _guarantees_ should this mutable variable change
/// > during the operation.
///
/// - Parameter operation: An operation to be performed on the main serial executor.
@MainActor
public func withMainSerialExecutor(
Expand Down