Skip to content

Swift 6: complete concurrency checking (LLC and UIKit) #3661

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

Draft
wants to merge 20 commits into
base: develop
Choose a base branch
from

Conversation

laevandus
Copy link
Contributor

@laevandus laevandus commented May 5, 2025

Important

StreamChatUI changes are in #3660 and will be merged to here. This PR can be reviewed already.

🔗 Issue Links

Resolves IOS-735

🎯 Goal

  • Set Swift version to 6 and implement complete concurrency checking

📝 Summary

  • Sendable conformance to types
  • @Sendable to completion handlers
  • Many thread-safety related changes to @unchecked Sendable types (internal classes have manual handling and found many which did not guard that state properly)
  • Fixes warnings in the demo app (adding @Sendable to completion handlers creates warnings at callsites)
  • Backported AllocatedUnfairLock which is needed for static concurrency safe properties (our Atomic property wrapper can't be used)

🛠 Implementation

🧪 Manual Testing Notes

Manual regression testing round when UIKit changes are merged into this branch.

☑️ Contributor Checklist

  • I have signed the Stream CLA (required)
  • This change should be manually QAed
  • Changelog is updated with client-facing changes
  • Changelog is updated with new localization keys
  • New code is covered by unit tests
  • Documentation has been updated in the docs-content repo

@laevandus laevandus requested a review from a team as a code owner May 5, 2025 12:26
@laevandus laevandus added the 🌐 SDK: StreamChat (LLC) Tasks related to the StreamChat LLC SDK label May 5, 2025
@laevandus laevandus marked this pull request as draft May 5, 2025 12:27
Copy link

github-actions bot commented May 5, 2025

1 Message
📖 Skipping Danger since the Pull Request is classed as Draft/Work In Progress

Generated by 🚫 Danger

Comment on lines -71 to +72
if: ${{ github.event.inputs.record_snapshots != 'true' }}
# if: ${{ github.event.inputs.record_snapshots != 'true' }}
if: false # disable Xcode 15 builds
Copy link
Contributor Author

@laevandus laevandus May 5, 2025

Choose a reason for hiding this comment

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

Disabled Xcode 15 builds (it is hard to support it when complete concurrency checking is enabled). Hard means avoiding compiler crashes.

@Stream-SDK-Bot
Copy link
Collaborator

SDK Size

title develop branch diff status
StreamChat 7.2 MB 7.28 MB +81 KB 🟢
StreamChatUI 4.72 MB 4.73 MB +17 KB 🟢

@@ -26,7 +26,7 @@ final class StreamAudioWaveformAnalyser: AudioAnalysing {
private let audioSamplesExtractor: AudioSamplesExtractor
private let audioSamplesProcessor: AudioSamplesProcessor
private let audioSamplesPercentageNormaliser: AudioValuePercentageNormaliser
private let outputSettings: [String: Any]
nonisolated(unsafe) private let outputSettings: [String: Any]
Copy link
Contributor Author

Choose a reason for hiding this comment

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

nonisolated(unsafe) because value is Any

@Stream-SDK-Bot
Copy link
Collaborator

SDK Performance

target metric benchmark branch performance status
MessageList Hitches total duration 10 ms 1.67 ms 83.3% 🔼 🟢
Duration 2.6 s 2.53 s 2.69% 🔼 🟢
Hitch time ratio 4 ms per s 0.66 ms per s 83.5% 🔼 🟢
Frame rate 75 fps 78.53 fps 4.71% 🔼 🟢
Number of hitches 1 0.2 80.0% 🔼 🟢


import Foundation

/// Erase type for structs which recursively contain themselves.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

It is easier to use a type instead of a closure when dealing with Sendable.

@@ -131,15 +131,19 @@ open class StreamAudioPlayer: AudioPlaying, AppStateObserverDelegate {
open func play() {
do {
try audioSessionConfigurator.activatePlaybackSession()
player.play()
MainActor.ensureIsolated {
player.play()
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Note that AVPlayer and some asset related methods require main actor


// MARK: -

private static let queue = DispatchQueue(label: "io.getstream.stream-runtime-check", target: .global())
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Alternative is to skip using queue here and making everything nonisolated(unsafe), especially because these are internal runtime checkes.

@laevandus laevandus changed the title Swift 6: complete concurrency checking Swift 6: complete concurrency checking (LLC and UIKit) May 5, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🌐 SDK: StreamChat (LLC) Tasks related to the StreamChat LLC SDK
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants