All concurrency-sensitive code must follow an “atomic + lifecycle-valid” contract.
Rules
nonisolated(unsafe) unless you can prove all accesses are synchronized.Illustrative patterns
Atomic delete check (closure holds lock during check+delete):
try await volumesService.delete(name: volume) // implementation should do:
try await containersService.withContainerList { containers in
guard !containers.contains(where: { $0.isUsingVolume(volume) && $0.isRunning() }) else {
throw VolumeError.volumeInUse(volume)
}
try await volumeStore.delete(volume)
}
Teardown-safe async completion (guard active state before acting):
.whenComplete { result in
switch result {
case .success(let channel):
guard context.channel.isActive else {
channel.close(promise: nil)
return
}
self.glue(channel, context: context)
case .failure(let error):
context.close(promise: nil)
context.fireErrorCaught(error)
}
}
Deadlock-free FIFO test (writer+reader concurrently):
let group = DispatchGroup()
group.enter()
DispatchQueue.global().async {
defer { group.leave() }
let handle = try! FileHandle(forWritingTo: pipePath)
try! handle.write(contentsOf: "SECRET_KEY=value123\n".data(using: .utf8)!)
try! handle.close()
}
let lines = try Parser.envFile(path: pipePath)
group.wait()