Swift Grand Central Dispatch

As explained by Jan Kaltoun

  • Dipatch Queue

  • FIFO

  • order of start guaranteed

  • order of completion varies

  • two types of processing

    • serial

    • concurrent

dispatch modes

  • sync

  • async

    • dispatching sync from same thread -> deadlock

    • serial queue

    • one task a at time

    • in order of dispatch

system provided queues

main queue

  • serial

  • highest priority

global queues

  • concurrent

  • qos defined priority

custom queues

  • defined by developer

  • qos defined priority

quality of service

  • user interactive - updating UI

  • user initiated - continue updating UI

  • utility - user need to be aware of reusult

  • background - task in the background, user unaware

See 12_GCD-QoS.playground at gitlab

import Foundation
import Dispatch

let mainQueue = DispatchQueue.main
let userInteractiveQueue = DispatchQueue.global(qos: .userInteractive)
let userInitiatedQueue = DispatchQueue.global(qos: .userInitiated)
let utilityQueue = DispatchQueue.global(qos: .utility)
let backgroundQueue = DispatchQueue.global(qos: .background)

for i in 1...1000 {
  
  backgroundQueue.async {
    print("❤️ background \(i)")
  }
  
  utilityQueue.async {
    print("💜 utility \(i)")
  }
  
  userInitiatedQueue.async {
    print("💙 user initiated \(i)")
  }
  
  userInteractiveQueue.async {
    print("💚 user interactive \(i)")
  }
  
  mainQueue.async {
    print("💛 main \(i)")
  }
}

queues and threads

  • main queue has one main thread

  • gcd maintains thread pool

  • gcf decides what thread to run your task on

  • dispatch queues are thread safe

Serial Queue - Synchronous Dispatch

  • Main thread blocked

  • The work is the only running work on the custom queue at a given time.

Serial Queue - Asynchronous Dispatch

  • Work run in background

  • Main queue not blocked

  • The work is the only running work on the custom queue at a given time.

Concurrent Queue - Synchronous Dispatch

  • Main thread blcoked

  • The work might not be the only running on the custom queue at a given time.

Concurrent Queue - Asynchronous Dispatch

  • Work runs in the background

  • Main thread is not blocked

  • The work might not be the only running on the custom queue at a given time.

Serial queues and shared resources

  • Serial queue execute one task at a time

  • Using a serial queue to access a shared resource 👍

Concurrent queues and shared resources

  • Concurrent queues execute multiple tasks at a time

  • Using concurrenct queues to access a shared resource 🤞 might work

  • Be carful

    • Locks

    • Semaphores

    • Barriers

Locks

  • NSLock

  • A lock will make sure resource only access from one threads

  • Reads and writes will wait

  • Slows down reads

Semaphores

  • DispatchSemaphore

  • N numnber of threads can access a shared resource

  • Reads and writes will wait

  • Slows down reads

Barriers

  • Dispatch work async with a .barrier flag

  • A queque will only execute such work when all previous work has finished

  • Use async dispatch with .barrier flag for writes

  • Use a sync dipatch for reads

  • All reads will be fast, all writes will be safe

Canceling Dispatched Work

  • DispatchWorkItem wrapper for block

  • can be cancelled

  • See [16_GCD-DispatchWorkItem.playground at gitlab]https://gitlab.com/dalcacer/til/-/blob/master/iOS/Concurrency/16_GCD-DispatchWorkItem.playground/Contents.swift)

Waiting for work to finish

Operations

  • Use gcd underneath

  • Additional layer of abstraction

  • Three classes

    • OperationQueue (DispatchQueue)

    • Operation (DispatchWorkItem)

    • BlockOperation (DispatchWorkItem)

  • Can depend on one another

  • Operation must be wrapper in Operation subclass

  • Pause, resume, cancel

  • KVO compliant

Operations vs. GCD

  • GCD: performance

  • GCD: low complexity in work organisation

  • OPS: complexity of work hierachy

  • OPS: reusability