Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Concurrency in Swift

73b5e9bf5f8ba0669b30c80f710f9904?s=47 Teddy Ku
December 07, 2017

Concurrency in Swift

Lightning Talk going over the Swift Concurrency Manifesto, and possible applications

73b5e9bf5f8ba0669b30c80f710f9904?s=128

Teddy Ku

December 07, 2017
Tweet

Transcript

  1. Concurrency Manifesto: async/await, actors, iOS Teddy Ku
 github.com/tkuichooseyou

  2. How do we handle concurrency in iOS?

  3. It’s almost 2018! • iPhone X: 6 cores, 3 GB

    RAM • Multi-core, multi-thread apps • Scalable, Distributed applications https://farm8.staticflickr.com/7403/16384510489_1cda4743b5_o.jpg
  4. Concurrency in Swift 4 func processImageData1(completionBlock: (result: Image) -> Void)

    { loadWebResource("dataprofile.txt") { dataResource in loadWebResource("imagedata.dat") { imageResource in decodeImage(dataResource, imageResource) { imageTmp in dewarpAndCleanupImage(imageTmp) { imageResult in completionBlock(imageResult) } } } } }
  5. Concurrency in Swift 4 • Completion blocks • Queues, Threads

    • Mutex, Semaphore • GCD: dispatch_barrier
  6. Problems • Ambiguous queue • Hard to read • Deadlocks

    • Race conditions Bugs
  7. what to do? futures/ promises channels coroutines Venice

  8. None
  9. Build a flexible foundation. Let community build libraries

  10. Step 1: async/await

  11. async/await func loadWebResource(_ path: String) async -> Resource func decodeImage(_

    r1: Resource, _ r2: Resource) async -> Image func dewarpAndCleanupImage(_ i : Image) async -> Image func processImageData1() async -> Image { let dataResource = await loadWebResource("dataprofile.txt") let imageResource = await loadWebResource("imagedata.dat") let imageTmp = await decodeImage(dataResource, imageResource) let imageResult = await dewarpAndCleanupImage(imageTmp) return imageResult }
  12. async/await func loadWebResource(_ path: String) async -> Resource func processImageData1()

    async -> Image { let dataResource = await loadWebResource("dataprofile.txt") // ... } • async: the func can suspend before returning a value (is a coroutine) • await: noop, but shows coder that non-local control flow can happen
  13. Step 1: async/await ✅

  14. What about handling multiple async things network requests, caching, image

    processing, etc?
  15. Step 2: Actors
 Eliminating shared mutable state

  16. Actors: in Swift 1. DispatchQueue 2. Data that queue protects

    3. Messages that can be run on that queue
 
 `actor`: reference type, like `class`. Can conform to protocols
  17. Do not communicate by sharing memory; instead, share memory by

    communicating
 - Effective Go
  18. actors actor TableActor { let mainActor : TheMainActor var theList

    : [String] = [] { didSet { mainActor.updateTableView(theList) } } init(mainActor: TheMainActor) { self.mainActor = mainActor } // this checks to see if all the entries in the list are capitalized: // if so, it capitalize the string before returning it to encourage // capitalization consistency in the list. func prettify(_ x : String) -> String { // Details omitted: it inspects theList, adjusting the // string before returning it if necessary. } actor func add(entry: String) { theList.append(prettify(entry)) } }
  19. actors actor TableActor { let mainActor : TheMainActor var theList

    : [String] = [] { didSet { mainActor.updateTableView(theList) } }
 
 func prettify(_ x : String) -> String {} actor func add(entry: String) { theList.append(prettify(entry)) } } // 1. send message to Table actor tableActor.add(entry: “foo") // 2. Table actor modifies its own data // 3. Table actor sends message to Main actor with copied data
 // 4. Main actor refreshes table view
  20. actors • TableActor’s data: reference to mainActor, and theList •

    actor can send messages to any other actor • actor methods are the messages that actors accept • actor methods are implicitly async, so they can freely call async methods and await their results • An actor method cannot return a value, throw an error, or have an inout parameter. • Actor method parameters must produce independent values when copied • Local state and non-actor methods may only be accessed by methods defined lexically on the actor or in an extension to it (whether they are marked actor or otherwise) actor func add(entry: String) mainActor.updateTableView(theList)
  21. We already have libraries, why do we need async/ await

    + actors?
  22. • Compiler optimization • detect deadlocks • optimize ARC retain/release

    calls • Better debugging • Spread knowledge First-class concurrency model benefits
  23. Example: Image Caching

  24. Before: completion block on DispatchQueue.main @objc final class RemoteImageManager: NSObject

    { static func downloadImage(with url: URL, mainQueueCompletion completion: @escaping PINRemoteImageManagerImageCompletion) -> UUID? { return PINRemoteImageManager.shared().downloadImage(with: url, options: [], completion: { (result: PINRemoteImageManagerResult) in DispatchQueue.main.async { completion(result) } }) } }
  25. After: RemoteImageActor actor RemoteImageActor { // implicitly private let cache:

    ImageCache actor func downloadImage(with url: URL) -> RemoteImageManagerResult { // urlSession stuff // handle updating cache without mutex/locks because this actor has exclusive access } } class ViewController: UIViewContoller { private var remoteImageActor: RemoteImageActor!
 private var imageViewActor: ImageViewActor! private func updateBackground() { let dogeImage = await remoteImageActor.downloadImage(with: "doge.gif") let processedImage = await imageProcessorActor.scale(0.5, image: dogeImage) imageViewActor.updateImageView(with image: dogeImage) } }
  26. Actor benefits • clearly express which queue is running •

    avoid mutex/locks • avoid programmer error
  27. Still to come • Reliability through fault isolation • fire

    and forget actor messages • add error handling in Actor init, not scattered everywhere • handle failures by restarting actor, etc. • Improving system architecture • declarative, clean interprocess communication • `distributed` keyword
  28. Let’s learn from other languages/libraries

  29. Thank you!