From 69b8bf63b45f4aaad94ccc99c334d2aa08916e02 Mon Sep 17 00:00:00 2001 From: Scott Marchant Date: Mon, 15 Dec 2025 14:12:20 -0700 Subject: [PATCH 1/2] docs: Update README in preparation for semantic 1.0.0 release. --- README.md | 87 +++++++++++------------ Sources/DispatchAsync/DispatchAsync.swift | 2 - 2 files changed, 42 insertions(+), 47 deletions(-) diff --git a/README.md b/README.md index 811af9f..367a303 100644 --- a/README.md +++ b/README.md @@ -1,57 +1,20 @@ # swift-dispatch-async -## ⚠️ WARNING - This is an 🧪experimental🧪 repository and should not be adopted at large. +DispatchAsync provides a pure-swift implementation of `Dispatch`, powered by Swift Concurrency. It is currently intended for use only +in WASM targets, but could be used in other scenarios should the need arise. -DispatchAsync is a temporary experimental repository aimed at implementing missing Dispatch support in the SwiftWasm toolchain. -Currently, [SwiftWasm doesn't include Dispatch](https://book.swiftwasm.org/getting-started/porting.html#swift-foundation-and-dispatch). -But, SwiftWasm does support Swift Concurrency. DispatchAsync implements a number of common Dispatch API's using Swift Concurrency -under the hood. +The Swift for WebAssembly SDK [doesn't currenty include Dispatch](https://book.swiftwasm.org/getting-started/porting.html#swift-foundation-and-dispatch). +But, it does support Swift Concurrency. DispatchAsync implements a number of common Dispatch API's using Swift Concurrency +under the hood. This allows `import DispatchAsync` to be used in wasm targets as a drop-in replacement anywhere `import Dispatch` is +currently in use. Dispatch Async does not provide blocking API's such as `DispatchQueue.sync`, primarily due to the intentional lack of blocking API's in Swift Concurrency. -# Toolchain Adoption Plans - -DispatchAsync is not meant for consumption abroad directly as a new Swift Module. Rather, the intention is to provide eventual integration -as a drop-in replacement for Dispatch when compiling to Wasm. - -There are a few paths to adoption into the Swift toolchain - -- DispatchAsync can be emplaced inside the [libDispatch repository](https://github.com/swiftlang/swift-corelibs-libdispatch), and compiled -into the toolchain only for wasm targets. -- DispatchAsync can be consumed in place of libDispatch when building the Swift toolchain. - -Ideally, with either approach, this repository would transfer ownership to the swiftlang organization. - -In the interim, to move wasm support forward, portions of DispatchAsync may be inlined (copy-pasted) -into various libraries to enable wasm support. DispatchAsync is designed for this purpose, and has -special `#if` handling to ensure that existing temporary usages will be elided without breakage -the moment SwiftWasm adds support for `Dispatch` into the toolchain. - -# DispatchSemaphore Limitations - -The current implementation of `DispatchSemaphore` has some limitations. Blocking threads goes against the design goals of Swift Concurrency. -The `wait` function on `DispatchSemaphore` goes against this goal. Furthermore, most wasm targets run on a single thread from the web -browser, so any time the `wait` function ends up blocking the calling thread, it would almost certainly freeze the single-threaded wasm -executable. - -To navigate these issues, there are some limitations: - -- For wasm compilation targets, `DispatchSemaphore` assumes single-threaded execution, and lacks various safeguards that would otherwise -be needed for multi-threaded execution. This makes the implementation much easier. -- For wasm targets, calls to `signal` and `wait` must be balanced. An assertion triggers if `wait` is called more times than `signal`. -- DispatchSemaphore is deprecated for wasm targets, and AsyncSemaphore is encouraged as the replacement. -- For non-wasm targets, DispatchSemaphore is simply a typealias for `AsyncSemaphore`, and provides only a non-blocking async `wait` -function. This reduces potential issues that can arise from wait being a thread-blocking function. - # Usage -If you've scrolled this far, you probably saw the warning. But just to make sure… - -> ⚠️ WARNING - This is an 🧪experimental🧪 repository and should not be adopted at large at the present time. - -PassiveLogic is [actively working](https://github.com/PassiveLogic/swift-web-examples/issues/1) to mainstream this into the SwiftWasm -toolchain. But if you can't wait, here are some tips. +PassiveLogic plans to mainstream this into the SwiftWasm toolchain. If possible, it's better to wait until this is part of the +official Swift for WebAssembly SDK. But if you need this now, below are some usage tips. ## 1. Only use this for WASI platforms, and only if Dispatch cannot be imported. @@ -133,6 +96,40 @@ DispatchQueue.main.async { } ``` +# Toolchain Adoption Plans + +DispatchAsync is not meant for consumption abroad directly as a new Swift Module. Rather, the intention is to provide eventual integration +as a drop-in replacement for Dispatch when compiling to Wasm. + +There are a few paths to adoption into the Swift toolchain + +- DispatchAsync can be emplaced inside the [libDispatch repository](https://github.com/swiftlang/swift-corelibs-libdispatch), and compiled +into the toolchain only for wasm targets. +- DispatchAsync can be consumed in place of libDispatch when building the Swift toolchain. + +Ideally, with either approach, this repository would transfer ownership to the swiftlang organization. + +In the interim, to move wasm support forward, portions of DispatchAsync may be inlined (copy-pasted) +into various libraries to enable wasm support. DispatchAsync is designed for this purpose, and has +special `#if` handling to ensure that existing temporary usages will be elided without breakage +the moment SwiftWasm adds support for `Dispatch` into the toolchain. + +# DispatchSemaphore Limitations + +The current implementation of `DispatchSemaphore` has some limitations. Blocking threads goes against the design goals of Swift Concurrency. +The `wait` function on `DispatchSemaphore` goes against this goal. Furthermore, most wasm targets run on a single thread from the web +browser, so any time the `wait` function ends up blocking the calling thread, it would almost certainly freeze the single-threaded wasm +executable. + +To navigate these issues, there are some limitations: + +- For wasm compilation targets, `DispatchSemaphore` assumes single-threaded execution, and lacks various safeguards that would otherwise +be needed for multi-threaded execution. This makes the implementation much easier. +- For wasm targets, calls to `signal` and `wait` must be balanced. An assertion triggers if `wait` is called more times than `signal`. +- DispatchSemaphore is deprecated for wasm targets, and AsyncSemaphore is encouraged as the replacement. +- For non-wasm targets, DispatchSemaphore is simply a typealias for `AsyncSemaphore`, and provides only a non-blocking async `wait` +function. This reduces potential issues that can arise from wait being a thread-blocking function. + # LICENSE This project is distributed by PassiveLogic under the Apache-2.0 license. See diff --git a/Sources/DispatchAsync/DispatchAsync.swift b/Sources/DispatchAsync/DispatchAsync.swift index 271b33c..530e445 100644 --- a/Sources/DispatchAsync/DispatchAsync.swift +++ b/Sources/DispatchAsync/DispatchAsync.swift @@ -18,8 +18,6 @@ /// /// Platforms other than WASI shouldn't consume this library for now /// except for testing and development purposes. -/// -/// TODO: SM: Add github permalink to this, after it is merged. #if !os(WASI) @_spi(DispatchAsync) #endif From 5bdf9c8000373c4288a3d56d36a6580eba6f70b5 Mon Sep 17 00:00:00 2001 From: Scott Marchant Date: Mon, 15 Dec 2025 14:38:20 -0700 Subject: [PATCH 2/2] ci: Pin swift workflows to version 0.0.2 for now, to avoid CI breaking due to unstable changes. --- .github/workflows/pull_request.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 835f9e0..913d48a 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -7,7 +7,7 @@ on: jobs: soundness: name: Soundness - uses: swiftlang/github-workflows/.github/workflows/soundness.yml@main + uses: swiftlang/github-workflows/.github/workflows/soundness.yml@0.0.2 with: format_check_container_image: swift:6.1.0-noble license_header_check_enabled: false @@ -15,7 +15,7 @@ jobs: tests: name: tests - uses: swiftlang/github-workflows/.github/workflows/swift_package_test.yml@main + uses: swiftlang/github-workflows/.github/workflows/swift_package_test.yml@0.0.2 with: # Runners aren't set up for this currently in GitHub/PassiveLogic enable_macos_checks: false