Slide 1

Slide 1 text

ઌऔΓʂSwi$ 6 ͷ async/await Yuta Koshizawa @koher

Slide 2

Slide 2 text

SE-0296: Async/await4 4 h$ps:/ /github.com/apple/swi6-evolu9on/blob/main/proposals/0296-async-await.md

Slide 3

Slide 3 text

Swi$ ͷඇಉظॲཧʢ͜Ε·Ͱʣ func download(from url: URL, completion: @escaping (Data) -> Void) download(from: url) { data in // ͜͜Ͱඇಉظʹड͚औͬͨ data Λ࢖͏ }

Slide 4

Slide 4 text

Swi$ ͷඇಉظॲཧʢ͜Ε͔Βʣ func download(from url: URL) async -> Data let data = await download(from: url) // ͜͜Ͱඇಉظʹड͚औͬͨ data Λ࢖͏

Slide 5

Slide 5 text

throws/try func foo() throws {} func bar() { try foo() // ⛔ }

Slide 6

Slide 6 text

throws/try func foo() throws {} func bar() throws { try foo() // ✅ }

Slide 7

Slide 7 text

async/await func foo() async {} func bar() { await foo() // ⛔ }

Slide 8

Slide 8 text

async/await func foo() async {} func bar() async { await foo() // ✅ }

Slide 9

Slide 9 text

Poten&al Suspension Point func download(from url: URL) async -> Data func downloadImage(from url: URL) async -> UIImage { // Potential Suspension Point let data = await download(from: url) // (A) let image = UIImage(data: data)! // (B) return image }

Slide 10

Slide 10 text

RPG ͷྫͱϒϩοΩϯά

Slide 11

Slide 11 text

RPG ͷྫͱϒϩοΩϯά func performTurn(of character: Character) { ... switch action { ... case .spell: // (1) ຐ๏Λબ୒ let spell = selectSpell(of: character) // (2) ຐ๏Λ͔͚Δ૬खΛબ୒ let target = selectTarget(of: spell) // (3) ຐ๏Λ࣮ߦ perform(spell, on: target) } }

Slide 12

Slide 12 text

RPG ͷྫͱϒϩοΩϯά func performTurn(of character: Character) async { ... switch action { ... case .spell: // (1) ຐ๏Λબ୒ let spell = await selectSpell(of: character) // (2) ຐ๏Λ͔͚Δ૬खΛબ୒ let target = await selectTarget(of: spell) // (3) ຐ๏Λ࣮ߦ await perform(spell, on: target) } }

Slide 13

Slide 13 text

ίʔϧόοΫ஍ࠈ foo { a in bar(a) { b in baz(b) { c in qux(c) { d in self.x = d } } } }

Slide 14

Slide 14 text

async/await ͳΒ let a = await foo() let b = await bar(a) let c = await baz(b) let d = await qux(c) self.x = d

Slide 15

Slide 15 text

Future ͩͱ foo().flatMap { a in bar(a) }.flatMap { b in baz(b) }.flatMap { c in qux(c) }.sink { d in self.x = d }.store(in: &cancellables)

Slide 16

Slide 16 text

੍ޚߏ଄ͱͷ૊Έ߹Θͤ let x = await foo() var sum = 0 while x > 0 { sum += x x = await bar(x) if x.isMultiple(of: 2) { return nil } } return sum

Slide 17

Slide 17 text

࿅श໰୊

Slide 18

Slide 18 text

໰୊ 01A h"ps:/ /swi)fiddle.com/m7nn4xoim62xdk7p5htbxmmau ໰୊ 01B h"ps:/ /swi)fiddle.com/zvnt3mp5tvgbbkd5mq5n3fvynm

Slide 19

Slide 19 text

Τϥʔ͕ى͜ΓಘΔ৔߹ʢίʔϧόοΫʣ func download(from url: URL, completion: @escaping (Result) -> Void) download(from: url) { result in do { let data: Data = try result.get() // ͜͜Ͱ data Λ࢖͏ } catch { // ͜͜ͰΤϥʔॲཧΛߦ͏ } }

Slide 20

Slide 20 text

Τϥʔ͕ى͜ΓಘΔ৔߹ʢ async/await ʣ func download(from url: URL) async throws -> Data do { let data = try await download(from: url) // ͜͜Ͱ data Λ࢖͏ } catch { // ͜͜ͰΤϥʔॲཧΛߦ͏ }

Slide 21

Slide 21 text

໰୊ 02A h"ps:/ /swi)fiddle.com/g7gvhfdug5hurbre2nzhifshaa ໰୊ 02B h"ps:/ /swi)fiddle.com/2si365hypvbd7pw27mp7hhibkm

Slide 22

Slide 22 text

໰୊ 03A h"ps:/ /swi)fiddle.com/5wnkjwkrzvhptlvhy7iukkfue4 ໰୊ 03B h"ps:/ /swi)fiddle.com/nbdwkt4yjzb23b33236wr5oj?

Slide 23

Slide 23 text

ฒߦॲཧʁ let a = await foo() let b = await bar() print(a + b)

Slide 24

Slide 24 text

ฒߦॲཧ async let a = foo() async let b = bar() print(await a + b)

Slide 25

Slide 25 text

ฒߦॲཧʢ JS ʣʁ const a = await foo(); // number const b = await bar(); // number console.log(a + b);

Slide 26

Slide 26 text

ฒߦॲཧʢ JS ʣ const a = foo(); // Promise const b = bar(); // Promise console.log(await a + await b);

Slide 27

Slide 27 text

ฒߦॲཧʢ Swi% ʣ async let a = foo() // Int async let b = bar() // Int print(await a + b)

Slide 28

Slide 28 text

inout func foo(_ x: inout Int) -> () -> Int { let bar: () -> Int = { return x + 1 } // return bar } var a = 42 let bar = foo(&a) a += 1 print(bar())

Slide 29

Slide 29 text

Structured concurrency5 The concept was formulated in 2016 by Mar7n Sústrik ..., and then further refined in 2018 by Nathaniel J. Smith, ... Meanwhile, Roman Elizarov independently came upon the same ideas while developing an experimental corou7ne library for the Kotlin language. In 2019, the loom project from OpenJDK is adop8ng structured concurrency ... In 2020, Swi? is men8oning adop8on of structured concurrency in their concurrency roadmap. 5 h$ps:/ /en.wikipedia.org/wiki/Structured_concurrency

Slide 30

Slide 30 text

SE-NNNN: Structured concurrency6 6 h$ps:/ /github.com/DougGregor/swi7-evolu;on/blob/structured-concurrency/proposals/nnnn-structured- concurrency.md

Slide 31

Slide 31 text

໰୊ 04 h"ps:/ /swi)fiddle.com/dgvmmmc4fax8yu6474p37ke

Slide 32

Slide 32 text

async ͷࠜͬ͜ func foo() async {} func bar() { await foo() // ⛔ }

Slide 33

Slide 33 text

async ͷࠜͬ͜ • τοϓϨϕϧ • @main • @asyncHandler • Task.runDetached • ( runAsyncAndBlock )

Slide 34

Slide 34 text

τοϓϨϕϧ await foo() await bar() await baz()

Slide 35

Slide 35 text

runAsyncAndBlock runAsyncAndBlock { await foo() await bar() await baz() }

Slide 36

Slide 36 text

@asyncHandler func foo() async {} @asyncHandler func bar() { await foo() }

Slide 37

Slide 37 text

@asyncHandler @asyncHandler func bar() { print(2) await foo1() print(4) await foo2() print(5) } print(1) bar() print(3)

Slide 38

Slide 38 text

async // @asyncHandler func bar() async { print(2) await foo1() print(3) await foo2() print(4) } print(1) await bar() print(5)

Slide 39

Slide 39 text

໰୊ 05 h"ps:/ /swi)fiddle.com/rhtpvch3rreovbcgw757c3keem

Slide 40

Slide 40 text

@asyncHandler func foo() async {} @asyncHandler func bar() { await foo() }

Slide 41

Slide 41 text

Task.runDetached func foo() async {} func bar() { Task.runDetached { await foo() } }

Slide 42

Slide 42 text

Task.runDetached func foo() async {} func bar() { let handle = Task.runDetached { await foo() } handle.cancel() }

Slide 43

Slide 43 text

Task func foo() async { // Thread A await bar() // Thread B await baz() // Threac C }

Slide 44

Slide 44 text

Task func foo() async { // Task A await bar() // Task A await baz() // Task A }

Slide 45

Slide 45 text

Child Task func foo() async -> Int { // Task A async let a = bar() // Task A async let b = baz() // Task A return await a + b }

Slide 46

Slide 46 text

Child Task func bar() async -> Int { // Task A' ... } func bar() async -> Int { // Task A'' ... }

Slide 47

Slide 47 text

Child Task func foo() async -> Int { // Task A async let a = bar() // Task A async let b = baz() // Task A return await a + b }

Slide 48

Slide 48 text

Task Tree શମͷΩϟϯηϧ func foo() async { // ෳࡶͳ Task Tree Λ࣋ͭඇಉظॲཧ } func bar() { let handle = Task.runDetached { await foo() } handle.cancel() }

Slide 49

Slide 49 text

໰୊ 06 h"ps:/ /swi)fiddle.com/mwjiy2f768ztaagrfrqs6lxhy

Slide 50

Slide 50 text

ίʔϧόοΫ → async func foo(completion: @escaping (Int) -> Void) { ... } func foo() async -> Int { // ίʔϧόοΫ൛ͷ foo Λ࢖ͬͯͲ͏΍࣮ͬͯ૷͢Δʁ }

Slide 51

Slide 51 text

ίʔϧόοΫ → async ʢ JS ʣ function fooCallback(completion) { ... } function fooAsync() { return new Promise((resolve) => { fooCallback(value => { resolve(value); }); }); }

Slide 52

Slide 52 text

ίʔϧόοΫ → async ʢ Swi& ʣ func foo(completion: @escaping (Int) -> Void) { ... } func foo() async -> Int { await withUnsafeContinuation { continuation in foo { value in continuation.resume(returning: value) } } }

Slide 53

Slide 53 text

SE-0300: Con+nua+ons for interfacing async tasks with synchronous code7 7 h$ps:/ /github.com/apple/swi6-evolu9on/blob/main/proposals/0300-con9nua9on.md

Slide 54

Slide 54 text

Con$nua$on • UnsafeContinuation • UnsafeThrowingContinuation • CheckedContinuation • CheckedThrowingContinuation

Slide 55

Slide 55 text

UnsafeContinuation withUnsafeContinuation Ͱड͚औΔɻ struct UnsafeContinuation { func resume(returning: T) }

Slide 56

Slide 56 text

UnsafeThrowingContinuation withUnsafeThrowingContinuation Ͱड͚औΔɻ struct UnsafeThrowingContinuation { func resume(returning: T) func resume(throwing: Error) func resume(with result: Result) }

Slide 57

Slide 57 text

໰୊ 07 h"ps:/ /swi)fiddle.com/tuu5w2k37jdu5:k6gv5>hcni

Slide 58

Slide 58 text

·ͱΊ • async/await (Accepted) • async let • @asyncHandler • Task.Handle • Con&nua&on (Ac)ve review)