Waitgroups in Swift

Our first example demonstrates how to use a dispatch group to wait for multiple asynchronous tasks to complete. This is similar to the concept of wait groups in other languages.

import Foundation

// This is the function we'll run in every task.
func worker(id: Int) {
    print("Worker \(id) starting")
    
    // Sleep to simulate an expensive task.
    Thread.sleep(forTimeInterval: 1)
    print("Worker \(id) done")
}

// Create a dispatch group
let group = DispatchGroup()

// Launch several tasks and add them to the dispatch group
for i in 1...5 {
    group.enter()
    
    // Wrap the worker call in a closure that makes sure to notify
    // the dispatch group that this worker is done. This way the worker
    // itself does not have to be aware of the concurrency primitives
    // involved in its execution.
    DispatchQueue.global().async {
        defer { group.leave() }
        worker(id: i)
    }
}

// Block until all tasks in the dispatch group have completed
group.wait()

// Note that this approach has no straightforward way
// to propagate errors from workers. For more
// advanced use cases, consider using Swift's Result type
// or a custom error handling mechanism.

To run the program, save it as DispatchGroups.swift and use swift to compile and run:

$ swift DispatchGroups.swift
Worker 5 starting
Worker 3 starting
Worker 4 starting
Worker 1 starting
Worker 2 starting
Worker 4 done
Worker 1 done
Worker 2 done
Worker 5 done
Worker 3 done

The order of workers starting up and finishing is likely to be different for each invocation.

In this Swift version:

  1. We use DispatchGroup instead of WaitGroup.
  2. group.enter() is equivalent to wg.Add(1).
  3. group.leave() is equivalent to wg.Done().
  4. group.wait() is equivalent to wg.Wait().
  5. We use DispatchQueue.global().async to create and run tasks asynchronously, which is similar to using goroutines in Go.

Swift’s concurrency model is different from Go’s, but this example demonstrates how to achieve similar functionality using Grand Central Dispatch (GCD), which is Swift’s native concurrency framework.