Concurrency

RSS for tag

Concurrency is the notion of multiple things happening at the same time.

Posts under Concurrency tag

89 Posts
Sort by:

Post

Replies

Boosts

Views

Activity

Concurrency Resources
Swift Concurrency Resources: DevForums tags: Concurrency The Swift Programming Language Concurrency > Concurrency documentation WWDC 2022 Session 110351 Eliminate data races using Swift Concurrency — This ‘sailing on the sea of concurrency’ talk is a great introduction to the fundamentals. WWDC 2021 Session 10134 Explore structured concurrency in Swift — The table that starts rolling out at around 25:45 is really helpful. Dispatch Resources: DevForums tags: Dispatch Dispatch documentation — Note that the Swift API and C API, while generally aligned, are different in many details. Make sure you select the right language at the top of the page. Dispatch man pages — While the standard Dispatch documentation is good, you can still find some great tidbits in the man pages. See Reading UNIX Manual Pages. Start by reading dispatch in section 3. WWDC 2015 Session 718 Building Responsive and Efficient Apps with GCD [1] WWDC 2017 Session 706 Modernizing Grand Central Dispatch Usage [1] Avoid Dispatch Global Concurrent Queues DevForums post Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com" [1] These videos may or may not be available from Apple. If not, the URL should help you locate other sources of this info.
0
0
552
Nov ’23
Function called isolated on MainActor via an isolated parameter are not considered run on the MainActor
If I try to compile the following, I get a compilation error: import Foundation func isolatedPrint<A : Actor>(on actor: isolated A) { print("hello") } Task{ @MainActor in isolatedPrint(on: MainActor.shared) } The error: toto.swift:9:2: error: expression is 'async' but is not marked with 'await' isolatedPrint(on: MainActor.shared) ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ await toto.swift:9:2: note: calls to global function 'isolatedPrint(on:)' from outside of its actor context are implicitly asynchronous isolatedPrint(on: MainActor.shared) ^ I don’t understand why the compiler does not detect the function is called on the MainActor via the actor parameter.
0
0
46
14h
Ensuring exclusive access to a function in structured concurrency
So our back end manages tokens in a strange way. Whenever we try to request a new access token using our refresh token, it invalidates our old refresh token and returns us with a new access + refresh token. The problem with this is that multiple concurrent network requests can see that a user's access token has expired and try to get a new access token, potentially causing us to get a 401 unauthorized error. Is there any way with structured/unstructured concurrency to ensure that our method for grabbing the access token can only at max be run once at a time? Im assuming the only realistic way would be to do something like this: @MyGlobalActor private var tokenTask: Task<String, any Error>? @MyGlobalActor func getAccessToken() async await -> String { if let tokenTask { return try await tokenTask.value } self.tokenTask = Task<String, any Error> { // refresh access token } let token = try await self.tokenTask!.value self.tokenTask = nil return token }
0
0
43
21h
Migrating @MainActor ViewModel to @Observable causing error
I get this error while migrating from ObservableObject to @Observable. Call to main actor-isolated initializer 'init()' in a synchronous nonisolated context My original code: struct SomeView: View { @StateObject private var viewModel = ViewModel() } After migration: @MainActor @Observable class BaseViewModel { } @MainActor class ViewModel: BaseViewModel { } struct SomeView: View { @State private var viewModel = ViewModel() } As discussed here. It seems like @StateObject is adding @MainActor compliance to my View under the hood because it's wrappedValue and projectedValue properties are marked as @MainActor, while on @State they are not. @available(iOS 14.0, macOS 11.0, tvOS 14.0, watchOS 7.0, *) @frozen @propertyWrapper public struct StateObject&lt;ObjectType&gt; : DynamicProperty where ObjectType : ObservableObject { ... @MainActor public var wrappedValue: ObjectType { get } .... @MainActor public var projectedValue: ObservedObject&lt;ObjectType&gt;.Wrapper { get } } One solution for this is to mark my View explicitly as @MainActor struct ViewModel: View but it have it side effects, for example code like: Button(action: resendButtonAction) { Text(resendButtonAttributedTitle()) } Will result a warning Converting function value of type '@MainActor () -&gt; ()' to '() -&gt; Void' loses global actor 'MainActor' While could be easily solved by using instead Button(action: { resendButtonAction() } ) { Text(resendButtonAttributedTitle()) } I still feel like marking the whole View explicitly as @MainActor is not a good practice. Adding fake @StateObject property to my view also do the trick, but it's a hack (the same for @FetchRequest). Can anyone think of a more robust solution for this?
1
1
981
2w
How to make sysctl and gettimeofday thread-safe in Swift?
I am trying to sync the ntp time from the server using Kronos library. However, I believe the code is not fully protected from multithreading access since it is using low level system code. So, does anyone know how can I ensure sysctl and gettimeofday are thread-safe when calling them? Or, is there any thread-safe alternative to get the same result? func currentTime() -&gt; TimeInterval { var current = timeval() let systemTimeError = gettimeofday(&amp;current, nil) != 0 assert(!systemTimeError, "system clock error: system time unavailable") return Double(current.tv_sec) + Double(current.tv_usec) / 1_000_000 } static func systemUptime() -&gt; TimeInterval { var mib = [CTL_KERN, KERN_BOOTTIME] var size = MemoryLayout&lt;timeval&gt;.stride var bootTime = timeval() let bootTimeError = sysctl(&amp;mib, u_int(mib.count), &amp;bootTime, &amp;size, nil, 0) != 0 assert(!bootTimeError, "system clock error: kernel boot time unavailable") let now = currentTime() let uptime = Double(bootTime.tv_sec) + Double(bootTime.tv_usec) / 1_000_000 assert(now &gt;= uptime, "inconsistent clock state: system time precedes boot time") return now - uptime } I have thought of using NSLock but I can only protect from the getter (caller) not the setter (system)
14
0
468
2w
WKScriptMessageHandlerWithReply and strict concurrency checking
Hi, I'm trying to implement a type conforming to WKScriptMessageHandlerWithReply while having Swift's strict concurrency checking enabled. It's not been fun. The protocol contains the following method (there's also one with a callback, but we're in 2024): func userContentController( controller: WKUserContentController, didReceive message: WKScriptMessage ) async -> (Any?, String?) WKScriptMessage's properties like body must be accessed on the main thread. But since WKScriptMessageHandlerWithReply is not @MainActor, neither can this method be so marked (same for the conforming type). At the same time WKScriptMessage is not Sendable, so I can't handle it in Task { @MainActor in this method, because that leads to Capture of 'message' with non-sendable type 'WKScriptMessage' in a `@Sendable` closure That leaves me with @preconcurrency import - is that the way to go? Should I file a feedback for this or is it somehow working as intended?
3
0
206
3w
[SwiftUI][Crash] Weird crash with FocusBrigde.hasHostingController.getter
This is a bug I have been trying to identify and fix for more than 3 weeks. This bug mostly happens in production. The stack trace doesn't help that much, because it looks like the app is crashing due to some SwiftUI internal methods. I tried everything in my power to debug and find this bug, still nothing. Due to the lack of 100% reproducibility, it made me think that this bug is either memory-pressure related or Swift concurrency related. When does it happen: This bug happens when presenting a SwiftUI modal (UIViewControllerRepresentable)[A] which in terms presents a UIHostingController modal[B] which then presents a modally a SwiftUI sheet [C] The bug happens somewhere around staying in [C] or after dismissing it. Context: The app lifecycle is SwiftUI. The main SwiftUI screen in the app body is a UIViewControllerRepresentable containing a UISplitViewController. Here is a screenshot from the crash log in Xcode. Anyone facing a similar issue?
2
0
186
4w
Using SwiftData: Model not saved when inserting from background actor
Hi everyone, I'm trying to make use of a background actor in my SwiftUI project. Inserting data works with the ModelContainer's mainContext. Another context in a ModelActor, however, fails to write into the same database. I verify the results by opening the SQLite file on the file system. While the mainContext.insert call does indeed insert a row into the table, the ModelActor's context fails to do so. There is no error or message received in the ModelActor. The property autosaveEnabled is set to true. I wrote a sample project to reproduce the issue in isolation. It consists of a single source file that introduces the Model ToDo, the ToDoView, initializes the ModelContainer and ModelActor. Please find the source code below. Is there any mistake in my approach? import SwiftUI import SwiftData @Model final class ToDo { let title: String init(title: String) { self.title = title } } @main struct testSwiftDataApp: App { @State var modelContainer: ModelContainer @State var backgroundData: BackgroundDataActor init() { let modelContainer: ModelContainer = try! ModelContainer(for: ToDo.self) self.modelContainer = modelContainer self.backgroundData = BackgroundDataActor( modelContainer: modelContainer ) } var body: some Scene { WindowGroup { ToDoView(backgroundData: self.backgroundData) .modelContainer(modelContainer) } } } struct ToDoView: View { @Environment(\.modelContext) var modelContext @Query var todos: [ToDo] let backgroundData: BackgroundDataActor var modelContainer: ModelContainer { self.modelContext.container } var body: some View { VStack { Text("Add ToDo") TextField( "", text: .constant( "URL to database: " + "\(self.modelContainer.configurations.first!.url)" ) ) // This action will be invoked on the ModelActor's context Button { Task { let todo = ToDo(title: "Step 1") await self.backgroundData.store( id: todo.persistentModelID ) } } label: { Text("Create ToDo in background") } // This action will be invoked on the mainContext Button { Task { let todo = ToDo(title: "Step 2") self.modelContainer.mainContext.insert(todo) } } label: { Text("Create ToDo in foreground") } // Show the query results VStack { Text("Available ToDos") ForEach(self.todos) { Text($0.title) } } } } } @ModelActor actor BackgroundDataActor: ModelActor { func store(id: PersistentIdentifier) { print("Trying to save") print("Is auto save enabled: \(self.modelContext.autosaveEnabled)") if let dbo = self[id, as: ToDo.self] { self.modelContext.insert(dbo) try! self.modelContext.save() print("Saved into database") } } }
1
0
198
Apr ’24
Apple MusicKit
Hello. I have the following question. I call the nextBatch() method on MusicItemCollection to get the next collection of artist albums. Here is my method: func allAlbums2(artist: Artist) async throws -> [Album] { var allAlbums: [Album] = [] artist.albums?.forEach { allAlbums.append($0) } guard let albums = artist.albums else { return [] } var albumsCollection = albums while albumsCollection.hasNextBatch { let response = try await albumsCollection.nextBatch() if let response { albumsCollection = response var albums = [Album]() albumsCollection.forEach({ albums.append($0)}) allAlbums.append(contentsOf: albums) } } return allAlbums } The problem is as follows. Sometimes it happens that some albums not in nextBatch are not returned (I noticed one, I didn't check the others). This happens once every 50-100 requests. The number of batches is returned the same when the album is skipped. The same albums are returned in the batch where the album was missed. I have a question, do I have a problem with multi-threading or something else or is it a problem in the API. The file contains prints of the returned batches. One with a missing album, the other without a missing one. There are about 3000 lines in the file. I will be grateful for a hint or an answer. Thank you! Here link to file: https://files.fm/u/nj4r5wgyg3
0
0
205
Apr ’24
What is the difference between OSAllocatedUnfairLock's withLock and withLockUnchecked functions?
OSAllocatedUnfairLock has two different methods for executing a block of code with the lock held: withLock() and withLockUnchecked(). The only difference between the two is that the former has the closure and return type marked as Sendable. withLockUnchecked() has a comment (that is for reasons I do not understand not visible in the documentation) saying: /// This method does not enforce sendability requirement /// on closure body and its return type. /// The caller of this method is responsible for ensuring references /// to non-sendables from closure uphold the Sendability contract. What I do not understand here is why Sendable conformance would be needed. These function should call this block synchronously in the same context, and return the return value through a normal function return. None of this should require the types to be Sendable. This seems to be supported by this paragraph of the documentation for OSAllocatedUnfairLock: /// This lock must be unlocked from the same thread that locked it. As such, it /// is unsafe to use `lock()` / `unlock()` across an `await` suspension point. /// Instead, use `withLock` to enforce that the lock is only held within /// a synchronous scope. So, why does this Sendable requirement exist, and in practice, if I did want to use withLockUnchecked, how would I "uphold the Sendability contract"? To summarise the question in a more concise way: Is there an example where using withLockUnchecked() would actually cause a problem, and using withLock() instead would catch that problem?
7
0
360
Apr ’24
Ambiguous "#locationUpdater received unhandled message" error from CLLocationUpdate.liveUpdates()
I’m working on updating one of my apps to the asynchronous location updates API, but have been running into an unhelpful error. Here's my code: @Observable class CurrentLocation: NSObject, CLLocationManagerDelegate { private(set) var location: CLLocation? private let locationManager = CLLocationManager() override init() { super.init() self.locationManager.delegate = self self.locationManager.desiredAccuracy = kCLLocationAccuracyReduced } func requestLocation() async throws { print("requesting location") requestAccess() for try await update in CLLocationUpdate.liveUpdates() { self.location = update.location if update.isStationary { break } } } } But after calling requestLocation(), I receive the following error in the console without any location updates: {"msg":"#locationUpdater received unhandled message", "Message":kCLConnectionMessageCompensatedLocation, "self":"0x600002eaa600"} Googling this error yields absolutely no matches. I’ve ensured that I have the necessary Info.plist entries (as the old, synchronous location update code I have is also working without issues). I’d be grateful for any assistance!
0
0
239
Apr ’24
Non-sendable type ModelContext on MainActor
Hi, just trying to learn how to work with mainActor. I am in a need of analyzing users data with API service one a background. Whenever user saves a post into SwiftData, I need to analyze that posts asynchronously. Here is my current code, which by the way works, but I am getting warning here; actor DatabaseInteractor { let networkInteractor: any NetworkInteractor = NetworkInteractorImpl() func loadUserProfile() async -&gt; String { do { let objects = try await modelContainer.mainContext.fetch(FetchDescriptor&lt;ProfileSwiftData&gt;()) if let profileTest = objects.first?.profile { return profileTest } } catch { } return "" } I get a warning on let objects line. Warning: Non-sendable type 'ModelContext' in implicitly asynchronous access to main actor-isolated property 'mainContext' cannot cross actor boundary
1
0
324
Apr ’24
Observation and MainActor
Previously, it was recommended to use the @MainActor annotation for ObservableObject implementation. @MainActor final class MyModel: ObservableObject { let session: URLSession @Published var someText = "" init(session: URLSession) { self.session = session } } We could use this as either a @StateObject or @ObservedObject: struct MyView: View { @StateObject let model = MyModel(session: .shared) } By moving to Observation, I need to the @Observable macro, remove the @Published property wrappers and Switch @StateObject to @State: @MainActor @Observable final class MyModel { let session: URLSession var someText = "" init(session: URLSession) { self.session = session } } But switching from @StateObject to @State triggers me an error due to a call to main-actor isolated initialiser in a synchronous nonisolated context. This was not the case with @StateObject of @ObservedObject. To suppress the warning I could : mark the initializer as nonisolated but it is not actually what I want Mark the View with @MainActor but this sounds odd Both solutions does not sound nice to my eye. Did I miss something here?
9
3
3.9k
Apr ’24
Swift 5.10: Cannot access property '*' with a non-sendable type '*' from non-isolated deinit; this is an error in Swift 6
The following Swift UIKit code produces the warning "Cannot access property 'authController' with a non-sendable type 'AuthController' from non-isolated deinit; this is an error in Swift 6": import UIKit class AuthFormNavC: UINavigationController { let authController: AuthController init(authController: AuthController) { self.authController = authController super.init(rootViewController: ConsentVC()) } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } deinit { authController.signInAnonymouslyIfNecessary() } } Swift 5.10, Xcode 15.3 with complete strict concurrency checking. What is the workaround? Please don't ask me why I'm doing what I'm doing or anything unrelated to the question. If you're wondering why I want to call authController.signInAnonymouslyIfNecessary() when the navigation controller is denitialized, my goal is to call it when the navigation controller is dismissed (or popped), and I think that the deinitializer of a view controller is the only method that is called if and only if the view controller is being dismissed (or popped) in my case. I tried observing variables like isViewLoaded in the past using KVO but I couldn't get it to work passing any combination of options in observe(_:options:changeHandler:).
1
0
339
Apr ’24
How to resolve SwiftUI.DynamicProperty on MainActor compiler warning on 6.0?
Hi! I'm running into a warning from a SwiftUI.DynamicProperty on a 6.0 development build (swift-6.0-DEVELOPMENT-SNAPSHOT-2024-03-26-a). I am attempting to build a type (conforming to DynamicProperty) that should also be MainActor. This type with also need a custom update function. Here is a simple custom wrapper (handwaving over the orthogonal missing pieces) that shows the warning: import SwiftUI @MainActor struct MainProperty: DynamicProperty { // Main actor-isolated instance method 'update()' cannot be used to satisfy nonisolated protocol requirement; this is an error in the Swift 6 language mode @MainActor func update() { } } Is there anything I can do about that warning? Does the warning correctly imply that this will be a legit compiler error when 6.0 ships? I can find (at least) two examples of types adopting DynamicProperty from Apple that are also MainActor: FetchRequest and SectionedFetchRequest. What is confusing is that both FetchRequest^1 and SectionedFetchRequest^2 explicitly declare their update method to be MainActor. Is there anything missing from my Wrapper declaration that can get me what I'm looking for? Any more advice about that? Thanks!
2
0
308
Apr ’24