Skip to content

Commit

Permalink
Add Wasm/Windows support/CI (#1)
Browse files Browse the repository at this point in the history
* Add Wasm/Windows CI

* wip

* wip

* test

* wip
  • Loading branch information
stephencelis authored Jul 17, 2023
1 parent e8af1c3 commit 479750b
Show file tree
Hide file tree
Showing 4 changed files with 214 additions and 175 deletions.
39 changes: 35 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,29 +15,60 @@ concurrency:

jobs:
library:
runs-on: macos-13
name: macOS
strategy:
matrix:
xcode: ['14.3.1']
config: ['debug', 'release']
runs-on: macos-13
steps:
- uses: actions/checkout@v3
- name: Select Xcode ${{ matrix.xcode }}
run: sudo xcode-select -s /Applications/Xcode_${{ matrix.xcode }}.app
- name: Run ${{ matrix.config }} tests
run: CONFIG=${{ matrix.config }} make test

ubuntu-tests:
linux:
name: Linux
strategy:
matrix:
os: [ubuntu-20.04]
config: ['debug', 'release']

runs-on: ${{ matrix.os }}

steps:
- uses: actions/checkout@v3
- name: Build
run: swift build
- name: Run tests
run: swift test -c ${{ matrix.config }}

wasm:
name: Wasm
runs-on: ubuntu-latest
strategy:
matrix:
include:
- { toolchain: wasm-5.7.1-RELEASE }
steps:
- uses: actions/checkout@v3
- run: echo "${{ matrix.toolchain }}" > .swift-version
- uses: swiftwasm/[email protected]
with:
shell-action: carton test --environment node

windows:
name: Windows
strategy:
matrix:
os: [windows-latest]
config: ['debug', 'release']
runs-on: ${{ matrix.os }}
steps:
- uses: compnerd/gha-setup-swift@main
with:
branch: swift-5.8-release
tag: 5.8-RELEASE

- uses: actions/checkout@v3
- name: Run tests
run: swift build -c ${{ matrix.config }}
10 changes: 7 additions & 3 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,6 @@ let package = Package(
targets: ["ConcurrencyExtras"]
)
],
dependencies: [
.package(url: "https://github.com/apple/swift-docc-plugin", from: "1.0.0")
],
targets: [
.target(
name: "ConcurrencyExtras"
Expand All @@ -32,6 +29,13 @@ let package = Package(
]
)

#if !os(Windows)
// Add the documentation compiler plugin if possible
package.dependencies.append(
.package(url: "https://github.com/apple/swift-docc-plugin", from: "1.0.0")
)
#endif

//for target in package.targets {
// target.swiftSettings = target.swiftSettings ?? []
// target.swiftSettings?.append(
Expand Down
142 changes: 72 additions & 70 deletions Sources/ConcurrencyExtras/MainSerialExecutor.swift
Original file line number Diff line number Diff line change
@@ -1,76 +1,78 @@
import Foundation
#if !os(WASI) && !os(Windows)
import Foundation

/// Perform an operation on the main serial executor.
///
/// 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.
///
/// ```swift
/// await withMainSerialExecutor {
/// // Everything performed in this scope is performed serially...
/// }
/// ```
///
/// - Parameter operation: An operation to be performed on the main serial executor.
@MainActor
public func withMainSerialExecutor(
@_implicitSelfCapture operation: @MainActor @Sendable () async throws -> Void
) async rethrows {
let didUseMainSerialExecutor = uncheckedUseMainSerialExecutor
defer { uncheckedUseMainSerialExecutor = didUseMainSerialExecutor }
uncheckedUseMainSerialExecutor = true
try await operation()
}
/// Perform an operation on the main serial executor.
///
/// 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.
///
/// ```swift
/// await withMainSerialExecutor {
/// // Everything performed in this scope is performed serially...
/// }
/// ```
///
/// - Parameter operation: An operation to be performed on the main serial executor.
@MainActor
public func withMainSerialExecutor(
@_implicitSelfCapture operation: @MainActor @Sendable () async throws -> Void
) async rethrows {
let didUseMainSerialExecutor = uncheckedUseMainSerialExecutor
defer { uncheckedUseMainSerialExecutor = didUseMainSerialExecutor }
uncheckedUseMainSerialExecutor = true
try await operation()
}

/// Perform an operation on the main serial executor.
///
/// A synchronous version of ``withMainSerialExecutor(operation:)-79jpc`` that can be used in
/// `XCTestCase.invokeTest` to ensure all async tests are performed serially:
///
/// ```swift
/// class BaseTestCase: XCTestCase {
/// override func invokeTest() {
/// withMainSerialExecutor {
/// super.invokeTest()
/// }
/// }
/// }
/// ```
///
/// - Parameter operation: An operation to be performed on the main serial executor.
public func withMainSerialExecutor(
@_implicitSelfCapture operation: () throws -> Void
) rethrows {
let didUseMainSerialExecutor = uncheckedUseMainSerialExecutor
defer { uncheckedUseMainSerialExecutor = didUseMainSerialExecutor }
uncheckedUseMainSerialExecutor = true
try operation()
}
/// Perform an operation on the main serial executor.
///
/// A synchronous version of ``withMainSerialExecutor(operation:)-79jpc`` that can be used in
/// `XCTestCase.invokeTest` to ensure all async tests are performed serially:
///
/// ```swift
/// class BaseTestCase: XCTestCase {
/// override func invokeTest() {
/// withMainSerialExecutor {
/// super.invokeTest()
/// }
/// }
/// }
/// ```
///
/// - Parameter operation: An operation to be performed on the main serial executor.
public func withMainSerialExecutor(
@_implicitSelfCapture operation: () throws -> Void
) rethrows {
let didUseMainSerialExecutor = uncheckedUseMainSerialExecutor
defer { uncheckedUseMainSerialExecutor = didUseMainSerialExecutor }
uncheckedUseMainSerialExecutor = true
try operation()
}

/// Overrides Swift's global executor with the main serial executor in an unchecked fashion.
///
/// > Warning: When set to `true`, all tasks will be enqueued on the main serial executor till set
/// > back to `false`. Consider using ``withMainSerialExecutor(operation:)-79jpc``, instead, which
/// > scopes this work to the duration of a given operation.
public var uncheckedUseMainSerialExecutor: Bool {
get { swift_task_enqueueGlobal_hook != nil }
set {
swift_task_enqueueGlobal_hook =
newValue
? { job, _ in MainActor.shared.enqueue(job) }
: nil
/// Overrides Swift's global executor with the main serial executor in an unchecked fashion.
///
/// > Warning: When set to `true`, all tasks will be enqueued on the main serial executor till set
/// > back to `false`. Consider using ``withMainSerialExecutor(operation:)-79jpc``, instead, which
/// > scopes this work to the duration of a given operation.
public var uncheckedUseMainSerialExecutor: Bool {
get { swift_task_enqueueGlobal_hook != nil }
set {
swift_task_enqueueGlobal_hook =
newValue
? { job, _ in MainActor.shared.enqueue(job) }
: nil
}
}
}

private typealias Original = @convention(thin) (UnownedJob) -> Void
private typealias Hook = @convention(thin) (UnownedJob, Original) -> Void
private typealias Original = @convention(thin) (UnownedJob) -> Void
private typealias Hook = @convention(thin) (UnownedJob, Original) -> Void

private var swift_task_enqueueGlobal_hook: Hook? {
get { _swift_task_enqueueGlobal_hook.pointee }
set { _swift_task_enqueueGlobal_hook.pointee = newValue }
}
private let _swift_task_enqueueGlobal_hook: UnsafeMutablePointer<Hook?> =
dlsym(dlopen(nil, 0), "swift_task_enqueueGlobal_hook").assumingMemoryBound(to: Hook?.self)
private var swift_task_enqueueGlobal_hook: Hook? {
get { _swift_task_enqueueGlobal_hook.pointee }
set { _swift_task_enqueueGlobal_hook.pointee = newValue }
}
private let _swift_task_enqueueGlobal_hook: UnsafeMutablePointer<Hook?> =
dlsym(dlopen(nil, 0), "swift_task_enqueueGlobal_hook").assumingMemoryBound(to: Hook?.self)
#endif
Loading

0 comments on commit 479750b

Please sign in to comment.