Post

What does Cooperative Concurrency Model Mean?

Understand Swift's cooperative concurrency model and how it differs from pre-emptive concurrency.

What does Cooperative Concurrency Model Mean?

Concurrency models dictate how tasks multitask and handle cancellation. Swift’s concurrency follows the cooperative concurrency model, contrasting with the pre-emptive model. This article clarifies both models, highlights why Swift chose cooperative concurrency, and demonstrates practical implications through clear examples.

1. Pre‑emptive vs. Cooperative: The Big Picture

AspectPre‑emptiveCooperative
Pausing TasksScheduler interrupts tasks at regular intervals.Tasks voluntarily yield at defined suspension points.
Context SwitchesCan occur at unpredictable points, even mid-operation.Occur only at explicit points (await, Task.yield()).
CancellationImmediate, can happen mid-execution.Checked only at suspension points.
OverheadHigh due to frequent interruptions.Lower, due to targeted yielding.
Fairness & ResponsivenessGood fairness, potential overhead.Efficient, but tasks must yield proactively to remain responsive.

2. Why Swift Uses Cooperative Concurrency

Swift’s cooperative concurrency approach offers key advantages:

  • Efficiency: Low overhead as the scheduler only switches tasks at explicit suspension points.
  • Predictability: Developers explicitly define suspension points, simplifying code reasoning.
  • Safety: Complements Swift’s data-race protections (actor isolation, Sendable enforcement), maintaining clear boundaries and invariants.

3. Suspension Points as Yield Points

Every await is a clear suspension point in Swift, performing these operations:

  • Saves current task’s context (stack, registers).
  • Scheduler runs another ready task.
  • Resumes original task upon awaited task completion.

Cancellation checks occur exclusively at these points, meaning tasks won’t interrupt spontaneously.

4. Practical Examples

A. Uncancellable Busy-Loop

1
2
3
4
5
6
7
8
func crunchNumbers(_ max: Int) async {
  var total = 0
  for i in 1...max {
    total += i * i
    // No suspension points; can't cancel mid-execution.
  }
  print("Done: \(total)")
}

Result: Task ignores cancellation requests until completion.

B. Cancellable Loop with Task.yield()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
func crunchNumbers(_ max: Int) async {
  var total = 0
  for i in 1...max {
    total += i * i

    if i % 1_000 == 0 {
      await Task.yield() // Explicit suspension & cancellation check

      if Task.isCancelled {
        print("Crunch cancelled at i = \(i)")
        return
      }
    }
  }
  print("Done: \(total)")
}

Result: Task becomes cancellable every 1000 iterations, allowing responsive cancellations.

C. Network Calls & Natural Suspension

1
2
3
4
5
6
7
8
9
10
11
12
func downloadImages(urls: [URL]) async throws {
  for url in urls {
    let (data, _) = try await URLSession.shared.data(from: url) // Natural suspension

    if Task.isCancelled {
      print("Download cancelled before processing \(url)")
      return
    }

    process(data)
  }
}

Result: Cancellation checks happen naturally at each network call.

5. Cooperative Cancellation with Task.checkCancellation()

Swift provides Task.checkCancellation(), combining suspension and immediate cancellation checks:

1
2
3
4
5
6
func runSteps() async throws {
  for step in 1...10 {
    try Task.checkCancellation() // Suspends and checks cancellation
    // Perform heavy step work...
  }
}

Equivalent to:

1
2
await Task.yield()
if Task.isCancelled { throw CancellationError() }

6. Summary

  • Pre-emptive: Tasks interrupted unpredictably; higher overhead.
  • Cooperative: Explicit, predictable suspension points; efficient.
  • Why Cooperative in Swift? Small tasks, predictability, data-safety integrations.
  • Developer Responsibility: Use await Task.yield() and Task.checkCancellation() to maintain task responsiveness.

☕ Support My Work

If you found this post helpful and want to support more content like this, you can buy me a coffee!

Your support helps me continue creating useful articles and tips for fellow developers. Thank you! 🙏

This post is licensed under CC BY 4.0 by the author.