Skip to content

Instantly share code, notes, and snippets.

@ole
Created March 12, 2025 12:21
Show Gist options
  • Save ole/8ffe3ecdef6d9a55f9c7846e0e16347e to your computer and use it in GitHub Desktop.
Save ole/8ffe3ecdef6d9a55f9c7846e0e16347e to your computer and use it in GitHub Desktop.
#isolation, @isolated(any), Sendable: what effect do they have on where an async function is executed?
import Foundation
func inheritCallerIsolation(
isolation: isolated (any Actor)? = #isolation,
// Closure executes on different threads, depending on attributes
operation: () async -> Void
// operation: @Sendable () async -> Void
// operation: @isolated(any) () async -> Void
// operation: @isolated(any) @Sendable () async -> Void
) async {
print("inheritCallerIsolation thread=\(currentThread()) isolation=\(isolation)")
await operation()
}
func nonIsolatedFunc() async {
print("nonIsolatedFunc thread=\(currentThread())")
}
Task.detached {
print("Task started thread=\(currentThread())")
await withTaskGroup(of: Void.self) { group in
print("Task group started thread=\(currentThread())")
group.addTask { @Sendable @MainActor in
print("Child task started thread=\(currentThread())")
await inheritCallerIsolation {
print("Closure started thread=\(currentThread())")
await nonIsolatedFunc()
print("Closure ending thread=\(currentThread())")
}
print("Child task ending thread=\(currentThread())")
}
}
print("Task group ended thread=\(currentThread())")
print("Task ending thread=\(currentThread())")
}
func currentThread() -> String {
let thread = Thread.current
if thread.isMainThread {
return "main"
} else if let name = thread.name, !name.isEmpty {
return name
} else if let numberMatch = String(describing: thread).firstMatch(of: /{number = (\d+),/) {
let number = numberMatch.output.1
return String(number)
} else {
return String(describing: thread)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment