Worker Pools in Swift

Our example demonstrates how to implement a worker pool using Grand Central Dispatch (GCD) and queues in Swift.

import Foundation

// This is our worker function. It will receive work on the `jobs` queue
// and send the corresponding results on the `results` queue.
// We'll sleep for a second per job to simulate an expensive task.
func worker(id: Int, jobs: DispatchQueue, results: DispatchQueue) {
    jobs.async {
        for j in 1...5 {
            print("worker \(id) started  job \(j)")
            Thread.sleep(forTimeInterval: 1)
            print("worker \(id) finished job \(j)")
            results.async {
                _ = j * 2
            }
        }
    }
}

// In the main function, we set up our queues and dispatch our workers
func main() {
    let jobs = DispatchQueue(label: "com.example.jobs", attributes: .concurrent)
    let results = DispatchQueue(label: "com.example.results", attributes: .concurrent)
    
    // This starts up 3 workers, initially blocked because there are no jobs yet
    for w in 1...3 {
        worker(id: w, jobs: jobs, results: results)
    }
    
    // We use a dispatch group to wait for all jobs to complete
    let group = DispatchGroup()
    
    // Here we send 5 jobs
    for j in 1...5 {
        group.enter()
        jobs.async {
            // Simulating job execution
            Thread.sleep(forTimeInterval: 0.1)
            group.leave()
        }
    }
    
    // Wait for all jobs to complete
    group.wait()
    
    // Allow some time for all results to be processed
    Thread.sleep(forTimeInterval: 1)
}

main()

Our program demonstrates 5 jobs being executed by various workers. The program takes about 2 seconds to complete despite doing about 5 seconds of total work because there are 3 workers operating concurrently.

To run the program, save it as worker_pools.swift and use the Swift compiler:

$ swift worker_pools.swift
worker 1 started  job 1
worker 2 started  job 1
worker 3 started  job 1
worker 1 finished job 1
worker 1 started  job 2
worker 2 finished job 1
worker 2 started  job 2
worker 3 finished job 1
worker 3 started  job 2
worker 1 finished job 2
worker 1 started  job 3
worker 2 finished job 2
worker 2 started  job 3
worker 3 finished job 2
worker 3 started  job 3
worker 1 finished job 3
worker 1 started  job 4
worker 2 finished job 3
worker 2 started  job 4
worker 3 finished job 3
worker 3 started  job 4
worker 1 finished job 4
worker 1 started  job 5
worker 2 finished job 4
worker 2 started  job 5
worker 3 finished job 4
worker 3 started  job 5
worker 1 finished job 5
worker 2 finished job 5
worker 3 finished job 5

This example showcases how to use Grand Central Dispatch (GCD) in Swift to create a worker pool. It uses concurrent queues to manage jobs and results, and a dispatch group to coordinate the completion of all jobs.