Trying to implement basic concurrent code with actors

These examples aren't in an actor context. Even if they were that doesn't necessarily mean they don't run concurrently, or even in parallel. If you're not touching actor state it seems to execute just like the non-actor case. If you are, you pay the synchronization overhead, but the rest of the execution can happen concurrently.

Overall, I've found that the best way to find an execution strategy for your work is to test various implementations until you find the fastest one, including simply throwing synchronous work onto a single Task.

2 Likes

This method works fine as long as the processed data does not get too large and/or the call chain that follows too complicated, in which case I get a nasty EXC_BAD_ACCESS error, see the code below: just wrapping the call into group.addTask produces the error. Any guess? (Thanks.) (In the full code I then do the for await _ in group, same problem then.)

        print("------- 1: OK")
        
        let run1 = Items(files)

        if #available(macOS 10.15, *) {
            await withTaskGroup(of: Void.self) { group in
                if let file = run1.next {
                    print("processing \(file.path)...")
                    do {
                        try await processFile(file: file)
                    }
                    catch {
                        print("ERROR: \(error.localizedDescription)")
                    }
                }
            }
        } else {
            print("wrong OS version")
        }
        
        print("press return...")
        _ = readLine()
        print("continuing...")
        
        print("------- 2: Thread 2: EXC_BAD_ACCESS (code=2, address=...)")
        
        let run2 = Items(files)

        if #available(macOS 10.15, *) {
            await withTaskGroup(of: Void.self) { group in
                if let file = run2.next {
                    print("processing \(file.path)...")
                    group.addTask {
                        do {
                            try await processFile(file: file)
                        }
                        catch {
                            print("ERROR: \(error.localizedDescription)")
                        }
                    }
                }
            }
        } else {
            print("wrong OS version")
        }

UPDATE: I added a demo project to show this error as GitHub - stefanspringer1/BadAccessDemo. Maybe someone has an idea... Thanks.

UPDATE 2: In my "real" project I managed to avoid the EXC_BAD_ACCESS error by keeping track of the data outside of the await withTaskGroup. Else, the data I am working on disappears and I get the error. But 1) I then do not know where I should remove the data from the tracking again (got back the EXC_BAD_ACCESS error each time I tried), and 2) in my BadAccessDemo mentioned, this trick somehow did not work. Could this be an error in the Swift runtime?