Concurrency Concepts
Sendable Values
Immutable data is a good fit for values passed across concurrency boundaries.
Pass immutable data
sendable_values.swift
Replay: real traced execution (multi-file project)
struct Job: Sendable {
let name: String
let count: Int
}
func summarize(_ job: Job) async -> String {
return "\(job.name):\(job.count)"
}
let count = 2
let job = Job(name: "trace", count: count)
let message = await summarize(job)
print(message)
struct Job: Sendable {
let name: String
let count: Int
}
func summarize(_ job: Job) async -> String {
return "\(job.name):\(job.count)"
}
let count = 4
let job = Job(name: "trace", count: count)
let message = await summarize(job)
print(message)
struct Job: Sendable {
let name: String
let count: Int
}
func summarize(_ job: Job) async -> String {
return "\(job.name):\(job.count)"
}
let count = 6
let job = Job(name: "trace", count: count)
let message = await summarize(job)
print(message)
count ← 2, job ← Job(name: "trace", count: 2)
10let count→ 2 = 2 //@count=4, 611let job→ Job(name: "trace", count: 2) = Job(name: "trace", count: count2)12let message = await summarize(jobJob(name: "trace", count: 2))func summarize(_ job: Job) async -> String
6func summarize(_ jobJob(name: "trace", count: 2): Job) async -> String {7 return "\(job.nametrace):\(job.count2)"8}message ← trace:2
11let job = Job(name: "trace", count: count)12let message→ trace:2 = await summarize(jobJob(name: "trace", count: 2))1314print(messagetrace:2)outputtrace:2
count ← 4, job ← Job(name: "trace", count: 4)
10let count→ 4 = 411let job→ Job(name: "trace", count: 4) = Job(name: "trace", count: count4)12let message = await summarize(jobJob(name: "trace", count: 4))func summarize(_ job: Job) async -> String
6func summarize(_ jobJob(name: "trace", count: 4): Job) async -> String {7 return "\(job.nametrace):\(job.count4)"8}message ← trace:4
11let job = Job(name: "trace", count: count)12let message→ trace:4 = await summarize(jobJob(name: "trace", count: 4))1314print(messagetrace:4)outputtrace:4
count ← 6, job ← Job(name: "trace", count: 6)
10let count→ 6 = 611let job→ Job(name: "trace", count: 6) = Job(name: "trace", count: count6)12let message = await summarize(jobJob(name: "trace", count: 6))func summarize(_ job: Job) async -> String
6func summarize(_ jobJob(name: "trace", count: 6): Job) async -> String {7 return "\(job.nametrace):\(job.count6)"8}message ← trace:6
11let job = Job(name: "trace", count: count)12let message→ trace:6 = await summarize(jobJob(name: "trace", count: 6))1314print(messagetrace:6)outputtrace:6
sendable value
A simple `Sendable` struct communicates that its stored values are safe to pass between concurrent tasks.