720 - concurrent programming with gcd in swift 3 04 final · 2016-07-09 · session 720 concurrent...

182
© 2016 Apple Inc. All rights reserved. Redistribution or public display not permitted without written permission from Apple. System Frameworks #WWDC16 Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit Darwin Runtime Engineer

Upload: others

Post on 12-Jan-2020

14 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

© 2016 Apple Inc. All rights reserved. Redistribution or public display not permitted without written permission from Apple.

System Frameworks #WWDC16

Session 720

Concurrent Programmingwith GCD in Swift 3

Matt Wright Darwin Runtime EngineerPierre Habouzit Darwin Runtime Engineer

Page 2: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit
Page 3: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Main Thread

Page 4: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

User Interface

Main Thread

Page 5: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

User Interface

Main Thread

Data Transform

Page 6: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

User Interface

Main Thread

Data Transform

Page 7: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Concurrency

Page 8: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

--

Concurrency

Threads allow execution of code at the same time

Page 9: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

--

Concurrency

Threads allow execution of code at the same timeCPU cores can each execute a single thread at any given time

Page 10: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

--

Concurrency

Threads allow execution of code at the same timeCPU cores can each execute a single thread at any given timeMaintaining code invariants is more difficult with concurrency

Page 11: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit
Page 12: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit
Page 13: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit
Page 14: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit
Page 15: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit
Page 16: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Dispatch Queues and Run Loops

Page 17: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Dispatch Queue

Dispatch Queues and Run Loops

Page 18: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Dispatch Queue () -> ()

Dispatch Queues and Run Loops

Page 19: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Dispatch Queue () -> ()

Dispatch Queues and Run Loops

Worker

Page 20: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Dispatch Queue

Dispatch Queues and Run Loops

Worker

Page 21: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Dispatch Queue

Dispatch Queues and Run Loops

Worker

Page 22: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Dispatch Queue

Dispatch Queues and Run Loops

Thread

Worker

Page 23: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Run Loop

Dispatch Queue

Dispatch Queues and Run Loops

Thread

Worker

Page 24: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Run Loop

Dispatch Queue

Dispatch Queues and Run Loops

Main Thread

Thread

Worker

Page 25: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Run Loop

Dispatch Queue

Main Run Loop Main Queue

Dispatch Queues and Run Loops

Main Thread

Thread

Worker

Page 26: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Dispatch Queue

Asynchronous Execution

Page 27: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Dispatch Queue

Asynchronous Execution

() -> ()

Page 28: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Dispatch Queue

Asynchronous Execution

() -> ()() -> ()

Page 29: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Dispatch Queue () -> ()

Asynchronous Execution

() -> ()() -> ()

Page 30: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Dispatch Queue () -> ()

Asynchronous Execution

() -> ()() -> ()Worker

Page 31: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Dispatch Queue () -> ()

Asynchronous Execution

() -> ()Worker

Page 32: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Dispatch Queue () -> ()

Asynchronous Execution

Worker

Page 33: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Dispatch Queue

Asynchronous Execution

Worker

Page 34: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Dispatch Queue

Asynchronous Execution

Page 35: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Synchronous Execution

Thread

Dispatch QueueWorker

Page 36: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Synchronous Execution

Thread

Dispatch Queue () -> ()Worker

Page 37: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Synchronous Execution

Thread

Dispatch Queue () -> ()

() -> ()

Worker

Page 38: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Synchronous Execution

Thread

Dispatch Queue () -> ()

() -> ()

() -> ()Worker

Page 39: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Synchronous Execution

Thread

Dispatch Queue () -> ()() -> ()

() -> ()

() -> ()Worker

Page 40: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Synchronous Execution

Thread

Dispatch Queue () -> ()() -> ()

() -> ()

() -> ()Worker

Page 41: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Synchronous Execution

Thread

Dispatch Queue () -> ()

() -> ()

() -> ()Worker

Page 42: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Synchronous Execution

Thread Dispatch Queue

() -> ()

() -> ()

() -> ()Worker

Page 43: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Synchronous Execution

Thread Dispatch Queue

() -> ()Worker

Page 44: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Synchronous Execution

Thread

Dispatch Queue () -> ()Worker

Page 45: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Synchronous Execution

Thread

Dispatch QueueWorker

Page 46: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Synchronous Execution

Thread

Dispatch Queue

Page 47: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Getting Work Off Your Main Thread

User Interface

Main Thread

Page 48: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Getting Work Off Your Main Thread

User Interface

Main Thread

Transform

Page 49: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Getting Work Off Your Main Thread

User Interface

Main Thread

Transform

Page 50: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Getting Work Off Your Main Thread

User Interface

Main Thread Dispatch Queue

Transform

Page 51: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Getting Work Off Your Main Thread

User Interface

Main Thread Dispatch Queue

Transform

Data

Page 52: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Getting Work Off Your Main Thread

User Interface

Main Thread Dispatch Queue

TransformData

Page 53: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Getting Work Off Your Main Thread

User Interface

Main Thread Dispatch Queue

TransformData

Page 54: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Getting Work Off Your Main Thread

User Interface

Main Thread Dispatch Queue

Transform

Data

Page 55: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Getting Work Off Your Main Thread

Create a Dispatch Queue to which you submit work

let queue = DispatchQueue(label: "com.example.imagetransform")

queue.async {

let smallImage = image.resize(to: rect)

}

Page 56: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Getting Work Off Your Main Thread

Create a Dispatch Queue to which you submit work

let queue = DispatchQueue(label: "com.example.imagetransform")

queue.async {

let smallImage = image.resize(to: rect)

}

Page 57: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Getting Work Off Your Main Thread

Create a Dispatch Queue to which you submit workDispatch Queues execute work items in FIFO order

let queue = DispatchQueue(label: "com.example.imagetransform")

queue.async {

let smallImage = image.resize(to: rect)

}

Page 58: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Getting Work Off Your Main Thread

Create a Dispatch Queue to which you submit workDispatch Queues execute work items in FIFO orderUse .async to execute your work on the queue

let queue = DispatchQueue(label: "com.example.imagetransform")

queue.async {

let smallImage = image.resize(to: rect)

}

Page 59: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Getting Back to Your Main Thread

Dispatch main queue executes all items on the main thread

let queue = DispatchQueue(label: "com.example.imagetransform")

queue.async {

let smallImage = image.resize(to: rect)

DispatchQueue.main.async {

imageView.image = smallImage

}

}

Page 60: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Getting Back to Your Main Thread

Dispatch main queue executes all items on the main thread

let queue = DispatchQueue(label: "com.example.imagetransform")

queue.async {

let smallImage = image.resize(to: rect)

DispatchQueue.main.async {

imageView.image = smallImage

}

}

Page 61: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Getting Back to Your Main Thread

Dispatch main queue executes all items on the main threadSimple to chain work between queues

let queue = DispatchQueue(label: "com.example.imagetransform")

queue.async {

let smallImage = image.resize(to: rect)

DispatchQueue.main.async {

imageView.image = smallImage

}

}

Page 62: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Controlling Concurrency

Page 63: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Controlling Concurrency

Thread pool will limit concurrency

Page 64: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Controlling Concurrency

Thread pool will limit concurrencyWorker threads that block can cause more to spawn

Page 65: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Controlling Concurrency

Thread pool will limit concurrencyWorker threads that block can cause more to spawnChoosing the right number of queues to use is important

Page 66: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Controlling Concurrency

Thread pool will limit concurrencyWorker threads that block can cause more to spawnChoosing the right number of queues to use is important

Building Responsive and Efficient Apps with GCD WWDC 2015

Page 67: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Structuring Your Application

Page 68: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Structuring Your Application

Identify areas of data flow in your application DatabaseData TransformNetworkingUser Interface

Main Queue

Page 69: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Structuring Your Application

Identify areas of data flow in your applicationSplit into distinct subsystems

Database

Data Transform

Networking

User Interface

Main Queue

Page 70: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Structuring Your Application

Identify areas of data flow in your applicationSplit into distinct subsystemsQueues at subsystem granularity

Database

Dispatch Queue

Data Transform

Dispatch Queue

Networking

Dispatch Queue

User Interface

Main Queue

Page 71: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Chaining vs. Grouping Work

Chaining Grouping

Page 72: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Chaining vs. Grouping Work

Chaining Grouping

Page 73: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Chaining vs. Grouping Work

Chaining Grouping

Page 74: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Chaining vs. Grouping Work

Chaining Grouping

Page 75: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Grouping Work Together

Database

Dispatch Queue

Data Transform

Dispatch Queue

Networking

Dispatch Queue

User Interface

Main Queue

Page 76: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Grouping Work Together

Database

Dispatch Queue

Data Transform

Dispatch Queue

Networking

Dispatch Queue

User Interface

Main Queue

Page 77: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Grouping Work Together

Database

Dispatch Queue

Data Transform

Dispatch Queue

Networking

Dispatch Queue

User Interface

Main Queue

Dispatch Group

Page 78: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Grouping Work Together

Database

Dispatch Queue

Data Transform

Dispatch Queue

Networking

Dispatch Queue

User Interface

Main Queue

Dispatch Group

let group = DispatchGroup()

Page 79: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Grouping Work Together

Database

Dispatch Queue

Data Transform

Dispatch Queue

Networking

Dispatch Queue

User Interface

Main Queue

Dispatch Group

let group = DispatchGroup()

queue.async(group: group) { … }

1

Page 80: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Grouping Work Together

Database

Dispatch Queue

Data Transform

Dispatch Queue

Networking

Dispatch Queue

User Interface

Main Queue

Dispatch Group1

queue.async(group: group) { … }

let group = DispatchGroup()

Page 81: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Grouping Work Together

Database

Dispatch Queue

Data Transform

Dispatch Queue

Networking

Dispatch Queue

User Interface

Main Queue

Dispatch Group1

queue2.async(group: group) { … }

queue.async(group: group) { … }

let group = DispatchGroup()2

Page 82: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Grouping Work Together

Database

Dispatch Queue

Data Transform

Dispatch Queue

Networking

Dispatch Queue

User Interface

Main Queue

Dispatch Group

queue2.async(group: group) { … }

2

queue.async(group: group) { … }

let group = DispatchGroup()

Page 83: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Grouping Work Together

Database

Dispatch Queue

Data Transform

Dispatch Queue

Networking

Dispatch Queue

User Interface

Main Queue

Dispatch Group

queue2.async(group: group) { … }

2

queue.async(group: group) { … }

let group = DispatchGroup()

queue3.async(group: group) { … }

3

Page 84: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Grouping Work Together

Database

Dispatch Queue

Data Transform

Dispatch Queue

Networking

Dispatch Queue

User Interface

Main Queue

Dispatch Group

queue2.async(group: group) { … }

queue.async(group: group) { … }

let group = DispatchGroup()12

queue3.async(group: group) { … }

3

Page 85: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Grouping Work Together

Database

Dispatch Queue

Data Transform

Dispatch Queue

Networking

Dispatch Queue

User Interface

Main Queue

Dispatch Group

group.notify(queue: DispatchQueue.main) { … }

queue2.async(group: group) { … }

queue.async(group: group) { … }

let group = DispatchGroup()12

queue3.async(group: group) { … }

3

Page 86: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Grouping Work Together

Database

Dispatch Queue

Data Transform

Dispatch Queue

Networking

Dispatch Queue

User Interface

Main Queue

Dispatch Group

group.notify(queue: DispatchQueue.main) { … }

queue2.async(group: group) { … }

queue.async(group: group) { … }

let group = DispatchGroup()12

Page 87: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Grouping Work Together

Database

Dispatch Queue

Data Transform

Dispatch Queue

Networking

Dispatch Queue

User Interface

Main Queue

Dispatch Group

group.notify(queue: DispatchQueue.main) { … }

queue2.async(group: group) { … }

let group = DispatchGroup()1

Page 88: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Grouping Work Together

Database

Dispatch Queue

Data Transform

Dispatch Queue

Networking

Dispatch Queue

User Interface

Main Queue

Dispatch Group

group.notify(queue: DispatchQueue.main) { … }

let group = DispatchGroup()

Page 89: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Grouping Work Together

Database

Dispatch Queue

Data Transform

Dispatch Queue

Networking

Dispatch Queue

User Interface

Main Queue

Dispatch Group

let group = DispatchGroup()

Page 90: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Synchronizing Between Subsystems

Can use subsystem serial queues for mutual exclusion

Page 91: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Synchronizing Between Subsystems

var count: Int { queue.sync { self.connections.count } }

Can use subsystem serial queues for mutual exclusionUse .sync to safely access properties from subsystems

Page 92: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Synchronizing Between Subsystems

var count: Int { queue.sync { self.connections.count } }

Can use subsystem serial queues for mutual exclusionUse .sync to safely access properties from subsystemsBe aware of “lock ordering” introduced between subsystems

Page 93: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Synchronizing Between Subsystems

var count: Int { queue.sync { self.connections.count } }

Can use subsystem serial queues for mutual exclusionUse .sync to safely access properties from subsystemsBe aware of “lock ordering” introduced between subsystems

Page 94: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Synchronizing Between Subsystems

var count: Int { queue.sync { self.connections.count } }

Can use subsystem serial queues for mutual exclusionUse .sync to safely access properties from subsystemsBe aware of “lock ordering” introduced between subsystems

Page 95: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Synchronizing Between Subsystems

var count: Int { queue.sync { self.connections.count } }

Can use subsystem serial queues for mutual exclusionUse .sync to safely access properties from subsystemsBe aware of “lock ordering” introduced between subsystems

Page 96: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Dispatch Inside Subsystems

Page 97: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Choosing a Quality of Service

QoS provides explicit classification of work User Interactive

User Initiated

Utility

Background

Page 98: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Choosing a Quality of Service

QoS provides explicit classification of workIndicates developer intent

User Interactive

User Initiated

Utility

Background

Page 99: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Choosing a Quality of Service

QoS provides explicit classification of workIndicates developer intentAffects execution properties of your work

User Interactive

User Initiated

Utility

Background

Page 100: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Choosing a Quality of Service

QoS provides explicit classification of workIndicates developer intentAffects execution properties of your work

User Interactive

User Initiated

Utility

Background

Building Responsive and Efficient Apps with GCD WWDC 2015

Page 101: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Using Quality of Service Classes

queue.async(qos: .background) {

print("Maintenance work")

}

queue.async(qos: .userInitiated) {

print(“Button tapped”)

}

Page 102: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Using Quality of Service Classes

Use .async to submit work with a specific QoS class

queue.async(qos: .background) {

print("Maintenance work")

}

queue.async(qos: .userInitiated) {

print(“Button tapped”)

}

Page 103: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Using Quality of Service Classes

Use .async to submit work with a specific QoS classDispatch helps resolve priority inversions

queue.async(qos: .background) {

print("Maintenance work")

}

queue.async(qos: .userInitiated) {

print(“Button tapped”)

}

Page 104: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Using Quality of Service Classes

Use .async to submit work with a specific QoS classDispatch helps resolve priority inversionsCreate single-purpose queues with a specific QoS class

queue.async(qos: .background) {

print("Maintenance work")

}

queue.async(qos: .userInitiated) {

print(“Button tapped”)

}

Page 105: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

DispatchWorkItem

By default .async captures execution context at time of submission

Page 106: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

DispatchWorkItem

By default .async captures execution context at time of submissionCreate DispatchWorkItem from closures to control execution properties

let item = DispatchWorkItem(flags: .assignCurrentContext) {

print("Hello WWDC 2016!")

}

queue.async(execute: item)

Page 107: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

DispatchWorkItem

By default .async captures execution context at time of submissionCreate DispatchWorkItem from closures to control execution propertiesUse .assignCurrentContext to capture current QoS at time of creation

let item = DispatchWorkItem(flags: .assignCurrentContext) {

print("Hello WWDC 2016!")

}

queue.async(execute: item)

Page 108: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Waiting for Work Items

QueueMain Thread

Page 109: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Waiting for Work Items

Use .wait on work items to signal that this item needs to execute

QueueMain Thread

.wait

Page 110: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Waiting for Work Items

Use .wait on work items to signal that this item needs to executeDispatch elevates priority of queued work ahead

QueueMain Thread

.wait

Page 111: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Waiting for Work Items

Use .wait on work items to signal that this item needs to executeDispatch elevates priority of queued work ahead

QueueMain Thread

.wait

Page 112: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Waiting for Work Items

Use .wait on work items to signal that this item needs to executeDispatch elevates priority of queued work aheadWaiting with a DispatchWorkItem gives ownership information

QueueMain Thread

.wait

Page 113: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Waiting for Work Items

Use .wait on work items to signal that this item needs to executeDispatch elevates priority of queued work aheadWaiting with a DispatchWorkItem gives ownership informationSemaphores and Groups do not admit a concept of ownership

QueueMain Thread

.wait

Page 114: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Shared State Synchronization

Pierre Habouzit Darwin Runtime Engineer

Page 115: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Synchronization is not part of the language in Swift 3Swift 3 and Synchronization

Global variables are initialized atomically

Page 116: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Synchronization is not part of the language in Swift 3Swift 3 and Synchronization

Global variables are initialized atomicallyClass properties are not atomic

Page 117: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Synchronization is not part of the language in Swift 3Swift 3 and Synchronization

Global variables are initialized atomicallyClass properties are not atomicLazy properties are not initialized atomically

Page 118: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

“There is no such thing as a benign race.”

Herb Sutter Chair of the ISO C++ standards committee

Page 119: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

“There is no such thing as a benign race.”

Herb Sutter Chair of the ISO C++ standards committee

Thread Sanitizer and Static Analysis Mission Thursday 10:00AM

Page 120: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Traditional C Locks in Swift

The Darwin module exposes traditional C lock types • correct use of C struct based locks such as pthread_mutex_t is incredibly hard

Page 121: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Correct Use of Traditional Locks

Foundation.Lock can be used safely because it is a class

Page 122: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Correct Use of Traditional Locks

Foundation.Lock can be used safely because it is a classDerive an Objective-C base class with struct based locks as ivars

@implementation LockableObject {

os_unfair_lock _lock;

}

- (instancetype)init ...

- (void)lock { os_unfair_lock_lock(&_lock); }

- (void)unlock { os_unfair_lock_unlock(&_lock); }

@end

Page 123: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Correct Use of Traditional Locks

Foundation.Lock can be used safely because it is a classDerive an Objective-C base class with struct based locks as ivars

@implementation LockableObject {

os_unfair_lock _lock;

}

- (instancetype)init ...

- (void)lock { os_unfair_lock_lock(&_lock); }

- (void)unlock { os_unfair_lock_unlock(&_lock); }

@end

Page 124: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Use GCD for Synchronization

Use DispatchQueue.sync(execute:) • harder to misuse than traditional locks, more robust• better instrumentation (Xcode, assertions, …)

Page 125: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

// Use Explicit Synchronization

class MyObject {

private let internalState: Int

private let internalQueue: DispatchQueue

}

Page 126: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

// Use Explicit Synchronization

class MyObject {

private let internalState: Int

private let internalQueue: DispatchQueue

var state: Int {

get {

return internalQueue.sync { internalState }

}

}

}

Page 127: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

// Use Explicit Synchronization

class MyObject {

private let internalState: Int

private let internalQueue: DispatchQueue

var state: Int {

get {

return internalQueue.sync { internalState }

}

set (newState) {

internalQueue.sync { internalState = newState }

}

}

}

Page 128: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Avoid data corruptionPreconditions

GCD lets you express several preconditions

NEW

Page 129: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Avoid data corruptionPreconditions

GCD lets you express several preconditions• Code is running on a given queue

NEW

dispatchPrecondition(.onQueue(expectedQueue)))

Page 130: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Avoid data corruptionPreconditions

GCD lets you express several preconditions• Code is running on a given queue• Code is not running on a given queue

NEW

dispatchPrecondition(.onQueue(expectedQueue)))

dispatchPrecondition(.notOnQueue(unexpectedQueue)))

Page 131: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Object Lifecycle in a Concurrent World

Page 132: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Object Lifecycle in a Concurrent World

Page 133: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Object Lifecycle in a Concurrent World

1. Single threaded setup

Setup

Page 134: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Object Lifecycle in a Concurrent World

1. Single threaded setup2. activate the concurrent state machine

Setup

Activated

Page 135: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Object Lifecycle in a Concurrent World

1. Single threaded setup2. activate the concurrent state machine3. invalidate the concurrent state machine

Setup

Activated

Invalidated

Page 136: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Object Lifecycle in a Concurrent World

1. Single threaded setup2. activate the concurrent state machine3. invalidate the concurrent state machine4. Single threaded deallocation

Setup

Activated

Invalidated

Deallocation

Page 137: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Object Lifecycle in a Concurrent World

1. Single threaded setup2. activate the concurrent state machine3. invalidate the concurrent state machine4. Single threaded deallocation

Setup

Activated

Invalidated

Deallocation

Page 138: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Observer Pattern

Database

Dispatch Queue Dispatch Queue

Networking

Main Queue

User Interface

Dispatch Queue

Data Transform

Page 139: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Observer Pattern

Main Queue

User Interface

Dispatch Queue

Data Transform

Page 140: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Observer Pattern

My App

Main Queue

User Interface

Dispatch Queue

Data Transform

Page 141: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Observer Pattern

My App

protocol SubsystemObserving {

func systemStarted(...)

func systemDone(...)

}

Main Queue

User Interface

Dispatch Queue

Data Transform

class BusyController: SubsystemObserving {

// ...

}

Page 142: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Observer Pattern

My App

protocol SubsystemObserving {

func systemStarted(...)

func systemDone(...)

}

Main Queue

User Interface

Dispatch Queue

Data Transform

class BusyController: SubsystemObserving {

// ...

}

Page 143: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Observer Pattern

My App

protocol SubsystemObserving {

func systemStarted(...)

func systemDone(...)

}

Main Queue

User Interface

Dispatch Queue

Data Transform

class BusyController: SubsystemObserving {

// ...

}

Page 144: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Setup SetupActivated

Invalidated

Deallocation

class BusyController: SubsystemObserving {

init(...) { ... }

}

Page 145: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

ActivationInvalidated

Deallocation

SetupActivated

class BusyController: SubsystemObserving {

init(...) { ... }

func activate() {

DataTransform.sharedInstance.register(observer: self, queue: DispatchQueue.main)

}

}

Page 146: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Active State Machine SetupActivated

Invalidated

Deallocation

class BusyController: SubsystemObserving {

func systemStarted(...) { /* ... */ }

func systemDone(...) { /* ... */ }

}

My App

Page 147: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

class BusyController: SubsystemObserving {

deinit {

DataTransform.sharedInstance.unregister(observer: self)

}

}

Deallocation Setup

Invalidated

Deallocation

Activated

Page 148: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Deallocation

Main Queue

User Interface

Dispatch Queue

Data Transform

BusyController1

Setup

Invalidated

Deallocation

Activated

Page 149: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Deallocation

Main Queue

User Interface

Dispatch Queue

Data Transform

BusyController1

Observers

2

Setup

Invalidated

Deallocation

Activated

Page 150: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Deallocation

Main Queue

User Interface

Dispatch Queue

Data Transform

BusyController1

Observers

Setup

Invalidated

Deallocation

Activated

Page 151: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Deallocation

Main Queue

User Interface

Dispatch Queue

Data Transform

BusyController1

Observers

Abandoned memory

Setup

Invalidated

Deallocation

Activated

Page 152: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Deallocation

Main Queue

User Interface

Setup

Invalidated

Deallocation

Activated

Main Queue

User Interface

Dispatch Queue

Data Transform

BusyController1

Observers

2

Abandoned memory

Data Transform

BusyController1

Dispatch Queue

Observers

Page 153: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Deallocation

Main Queue

User Interface

Setup

Invalidated

Deallocation

Activated

Main Queue

User Interface

Dispatch Queue

Data Transform

BusyController1

Observers

2

Abandoned memory

Data Transform

OctopusBusyController

12

Dispatch Queue

Observers

Page 154: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Deallocation

Main Queue

User Interface

Setup

Invalidated

Deallocation

Activated

Main Queue

User Interface

Dispatch Queue

Data Transform

BusyController1

Observers

2

Abandoned memory

Data Transform

OctopusBusyController

1

Dispatch Queue

Observers

Page 155: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Deallocation

Main Queue

User Interface

Setup

Invalidated

Deallocation

Activated

Main Queue

User Interface

Dispatch Queue

Data Transform

BusyController1

Observers

2

Abandoned memory

Data Transform

OctopusBusyController

1

Dispatch Queue

Observers

Page 156: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Deallocation

Main Queue

User Interface

Setup

Invalidated

Deallocation

Activated

Main Queue

User Interface

Dispatch Queue

Data Transform

BusyController1

Observers

2

Abandoned memory

Data Transform

OctopusBusyController

1

Dispatch Queue

Observers

Page 157: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Deallocation

Main Queue

User Interface

Setup

Invalidated

Deallocation

Activated

Main Queue

User Interface

Dispatch Queue

Data Transform

BusyController1

Observers

2

Abandoned memory

Data Transform

OctopusBusyController

1

Dispatch Queue

Observers

Page 158: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Deallocation

Main Queue

User Interface

Setup

Invalidated

Deallocation

Activated

Main Queue

User Interface

Dispatch Queue

Data Transform

BusyController1

Observers

2

Abandoned memory

Data Transform

OctopusBusyController

1

Dispatch Queue

Observers

Page 159: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Deallocation

Main Queue

User Interface

Deadlocks

Setup

Invalidated

Deallocation

Activated

Main Queue

User Interface

Dispatch Queue

Data Transform

BusyController1

Observers

2

Abandoned memory

Data Transform

OctopusBusyController

1

Dispatch Queue

Observers

Page 160: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

// Deadlocks on Serial Queues Assert

Application Specific Information:

BUG IN CLIENT OF LIBDISPATCH: dispatch_barrier_sync called on queue already owned by current

thread

Thread 1 Crashed:: Dispatch queue: com.example.queue

0 libdispatch.dylib 0x00007fff920b44ee _dispatch_barrier_sync_f_slow + 675

1 <YOUR APP> 0x000000010a3d7f26 __main_block_invoke_2 + 38

2 libdispatch.dylib 0x00007fff920a8ed6 _dispatch_client_callout + 8

3 libdispatch.dylib 0x00007fff920a9b0e _dispatch_barrier_sync_f_invoke + 83

4 <YOUR APP> 0x000000010a3d7ef6 __main_block_invoke + 38

5 libdispatch.dylib 0x00007fff920b1d54 _dispatch_call_block_and_release + 12

6 libdispatch.dylib 0x00007fff920a8ed6 _dispatch_client_callout + 8

7 libdispatch.dylib 0x00007fff920c2d34 _dispatch_queue_serial_drain + 896

...

Page 161: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

// Deadlocks on Serial Queues Assert

Application Specific Information:

BUG IN CLIENT OF LIBDISPATCH: dispatch_barrier_sync called on queue already owned by current

thread

Thread 1 Crashed:: Dispatch queue: com.example.queue

0 libdispatch.dylib 0x00007fff920b44ee _dispatch_barrier_sync_f_slow + 675

1 <YOUR APP> 0x000000010a3d7f26 __main_block_invoke_2 + 38

2 libdispatch.dylib 0x00007fff920a8ed6 _dispatch_client_callout + 8

3 libdispatch.dylib 0x00007fff920a9b0e _dispatch_barrier_sync_f_invoke + 83

4 <YOUR APP> 0x000000010a3d7ef6 __main_block_invoke + 38

5 libdispatch.dylib 0x00007fff920b1d54 _dispatch_call_block_and_release + 12

6 libdispatch.dylib 0x00007fff920a8ed6 _dispatch_client_callout + 8

7 libdispatch.dylib 0x00007fff920c2d34 _dispatch_queue_serial_drain + 896

...

Page 162: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Explicit Invalidation SetupActivated

Deallocation

Invalidated

class BusyController: SubsystemObserving {

func invalidate() {

}

deinit {

}

}

Page 163: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Explicit Invalidation SetupActivated

Deallocation

Invalidated

class BusyController: SubsystemObserving {

func invalidate() {

DataTransform.sharedInstance.unregister(observer: self)

}

deinit {

}

}

Page 164: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Explicit Invalidation SetupActivated

Deallocation

Invalidated

class BusyController: SubsystemObserving {

func invalidate() {

dispatchPrecondition(.onQueue(DispatchQueue.main))

DataTransform.sharedInstance.unregister(observer: self)

}

deinit {

}

}

Page 165: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

class BusyController: SubsystemObserving {

private var invalidated: Bool = false

func invalidate() {

dispatchPrecondition(.onQueue(DispatchQueue.main))

invalidated = true

DataTransform.sharedInstance.unregister(observer: self)

}

deinit {

precondition(invalidated)

}

}

Invalidation as a State SetupActivated

Invalidated

Deallocation

Page 166: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

class BusyController: SubsystemObserving {

private var invalidated: Bool = false

func invalidate() {

dispatchPrecondition(.onQueue(DispatchQueue.main))

invalidated = true

DataTransform.sharedInstance.unregister(observer: self)

}

deinit {

precondition(invalidated)

}

}

Invalidation as a State SetupActivated

Invalidated

Deallocation

Page 167: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

class BusyController: SubsystemObserving {

private var invalidated: Bool = false

func systemStarted(...) {

if invalidated { return }

/* ... */

}

deinit {

precondition(invalidated)

}

}

Invalidation as a State SetupActivated

Invalidated

Deallocation

Page 168: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

GCD Object Lifecycle

Page 169: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Setup

Attributes and target queue

SetupActivated

Deallocation

Invalidated

let q = DispatchQueue(label: "com.example.queue", attributes: [.autoreleaseWorkItem])

let source = DispatchSource.read(fileDescriptor: fd, queue: q)

Page 170: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Setup

Attributes and target queueSource handlers

SetupActivated

Deallocation

Invalidated

source.setEventHandler { /* handle your event here */ }

source.setCancelHandler { close(fd) }

let q = DispatchQueue(label: "com.example.queue", attributes: [.autoreleaseWorkItem])

let source = DispatchSource.read(fileDescriptor: fd, queue: q)

Page 171: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Properties of dispatch objects must not be mutated after activation

Activation Setup

Deallocation

Activated

Invalidated

extension DispatchObject {

func activate()

}

Page 172: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Properties of dispatch objects must not be mutated after activation

Activation NEWSetup

Deallocation

Activated

Invalidated

extension DispatchObject {

func activate()

}

Page 173: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Properties of dispatch objects must not be mutated after activation• Queues can also be created inactive

Activation NEWSetup

Deallocation

Activated

Invalidated

extension DispatchObject {

func activate()

}

let queue = DispatchQueue(label: “com.example.queue”, attributes: [.initiallyInactive])

Page 174: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Cancellation

Sources require explicit cancellation• Event monitoring is stopped

SetupActivated

Deallocation

Invalidated

extension DispatchSource {

func cancel()

}

Page 175: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Cancellation

Sources require explicit cancellation• Event monitoring is stopped• Cancellation handler runs

SetupActivated

Deallocation

Invalidated

let source = DispatchSource.read(fileDescriptor: fd, queue: q)

source.setCancelHandler { close(fd) }

Page 176: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Cancellation

Sources require explicit cancellation• Event monitoring is stopped• Cancellation handler runs• All handlers are deallocated

SetupActivated

Deallocation

Invalidated

let source = DispatchSource.read(fileDescriptor: fd, queue: q)

source.setCancelHandler { close(fd) }

Page 177: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Deallocation Hygiene

GCD Objects expect to be in a defined state at deallocation• Activated• Not suspended

Setup

Deallocation

Activated

Invalidated

Page 178: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Summary

Organize your application around data flows into independent subsystemsSynchronize state with Dispatch QueuesUse the activate/invalidate pattern

Page 179: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

More Information

https://developer.apple.com/wwdc16/720

Page 180: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Related Sessions

Thread Sanitizer and Static Analysis Mission Thursday 10:00AM

Going Server-side with Swift Open Source Mission Friday 9:00AM

Optimizing I/O for Performance and Battery Life Nob Hill Friday 11:00AM

Page 181: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit

Labs

GCD Lab Frameworks Lab D Tuesday 5:00PM

Page 182: 720 - Concurrent Programming with GCD in Swift 3 04 FINAL · 2016-07-09 · Session 720 Concurrent Programming with GCD in Swift 3 Matt Wright Darwin Runtime Engineer Pierre Habouzit