Slide 1

Slide 1 text

Swi$ ؛઒ࠀݾ @k_katsumi Yuta Koshizawa @koher

Slide 2

Slide 2 text

؛઒ࠀݾ @k_katsumi Apple ޷͖͕ߴͯ͡ iOS ΞϓϦέʔγϣ ϯͷ։ൃΛ 14 ೥ଓ͚͍ͯ·͢ɻझຯͰ ࡞͍ͬͯΔ OSS ϥΠϒϥϦ͸͚ͬ͜͏ਓ ؾ͕͋Γ·͢ɻ Yuta Koshizawa @koher "Heart of Swi-" Λॻ͖·ͨ͠ɻීஈ͸ओ ʹϦΞϧλΠϜը૾ॲཧΛ༻͍ͨ iOS Ξ ϓϦΛ։ൃ͍ͯ͠·͢ɻ

Slide 3

Slide 3 text

Swi$ ͷ࠷৽ಈ޲

Slide 4

Slide 4 text

Swi$ 5.5: 9 ݄ϦϦʔεʢʁʣ

Slide 5

Slide 5 text

Concurrency ʢฒߦॲཧʣ

Slide 6

Slide 6 text

Swi$ 5.5+ ͷ Concurrency ฒߦॲཧʹىҼ͢Δσʔλڝ߹΍σουϩοΫ͕ى͜Βͳ͍͜ͱ ΛίϯύΠϥ͕อূͯ͘͠ΕΔɻ

Slide 7

Slide 7 text

Ұݟ Ruby ΍ Python ͷΑ͏͚ͩͲɾɾɾ // 0 Ҏ্ 100 ະຬͷ੔਺ͷ߹ܭ var sum = 0 for i in 0 ..< 100 { sum += i } print(sum)

Slide 8

Slide 8 text

ίϯύΠϥ͕ΨνΨνʹ੩తݕࠪ͢Δݴޠ • Null Safety ʢ 2014 ೥ͷϦϦʔε౰ॳ͔Βʣ • throws/try ʢݕࠪྫ֎ͷΑ͏ͳ΋ͷʣ

Slide 9

Slide 9 text

ίϯύΠϥ͕ΨνΨνʹ੩తݕࠪ͢Δݴޠ • Null Safety ʢ 2014 ೥ͷϦϦʔε౰ॳ͔Βʣ • throws/try ʢݕࠪྫ֎ͷΑ͏ͳ΋ͷʣ • σʔλڝ߹ͱσουϩοΫͷ๷ࢭ

Slide 10

Slide 10 text

Swi$ ͷฒߦॲཧ ! async/await " Structured Concurrency # actor

Slide 11

Slide 11 text

! async/await

Slide 12

Slide 12 text

async/await ͷྫ // Swift func fetchUser(...) async -> User { let userData = await downloadData(...) ... return user } Ұݟ JavaScript ౳ͷ async/await ͱࣅ͍ͯΔɻ

Slide 13

Slide 13 text

JS/TS ͷ async/await ͱͷҧ͍ // TypeScript async function fetchUser(...): Promise { const userData = await downloadData(...); ... return user; } JS/TS Ͱ͸ async ؔ਺͸ Promise Λฦ͢ɻ

Slide 14

Slide 14 text

JS/TS ͷ async/await ͱͷҧ͍ // Swift func fetchUser(...) async -> User { let userData = await downloadData(...) ... return user } Swi$ ͷ async ؔ਺͸ Promise Λฦ͞ͳ͍ɻ

Slide 15

Slide 15 text

JS/TS ͷ async/await ͱͷҧ͍ // TypeScript async function fetchUser(...): Promise { const promise = downloadData(...); ... return user; } JS/TS Ͱ͸ await ͠ͳ͍ͱ Promise ΛಘΔɻ

Slide 16

Slide 16 text

JS/TS ͷ async/await ͱͷҧ͍ // Swift func fetchUser(...) async -> User { let userData = downloadData(...) // ίϯύΠϧΤϥʔ ... return user } Swi$ Ͱ͸ await ͠ͳ͍ͱίϯύΠϧΤϥʔɻඞͣ await ͞ΕΔ ͷͰ Promise ʹ૬౰͢Δ΋ͷ͸ͳ͍ɻ

Slide 17

Slide 17 text

await ඞਢͳͷͰ await ๨Ε͕ى͜Βͳ͍ func updateUser(user: User) async { // ⛔ ίϯύΠϧΤϥʔ db.collection("users") .document(user.id) .setData(from: user) } ʢಛʹ໭Γ஋͕ͳ͍৔߹Ͱ΋ʣҙਤͤͣ await Λ෇͚๨ΕΔࣄނ ͕ى͜Βͳ͍ɻ

Slide 18

Slide 18 text

JS/TS Ͱ͸ Promise Λ׆༻ͯ͠ฒߦʹ࣮ߦ // TypeScript async function fetchUser(...): Promise { const userPromise = downloadData(...); const avatarPromise = downloadData(...); const [userData, avatarData] = await Promise.all([userPromise, avatarPromise]); ... return user; } await ͠ͳ͍͜ͱ͕Մೳͩͱෳ਺ͷඇಉظॲཧΛฒߦʹ࣮ߦͰ͖ Δɻ

Slide 19

Slide 19 text

await ඞਢͰ Promise ͕ͳ͍ͳΒෳ਺ͷ ඇಉظॲཧΛͲ͏΍ͬͯฒߦʹ࣮ߦ͢Δʁ

Slide 20

Slide 20 text

! Structured Concurrency

Slide 21

Slide 21 text

async let Ͱฒߦॲཧ // Swift func fetchUser(...) async -> User { async let userData = downloadData(...) async let avatarData = downloadData(...) let user = await User(data: userData, avatar: avatarData) return user }

Slide 22

Slide 22 text

JS/TS ͷ৔߹ // TypeScript async function fetchUser(...): Promise { const userPromise = downloadData(...); const avatarPromise = downloadData(...); const [userData, avatarData] = await Promise.all([userPromise, avatarPromise]); ... return user; }

Slide 23

Slide 23 text

async let Ͱฒߦॲཧ // Swift func fetchUser(...) async -> User { async let userData = downloadData(...) async let avatarData = downloadData(...) let user = await User(data: userData, avatar: avatarData) return user } async let ͸ Promise ͱҧͬͯείʔϓͷ֎ʹ࣋ͪग़ͤͳ͍ɻ

Slide 24

Slide 24 text

Structured Concurrency ߏ଄Խϓϩάϥϛϯάʢ Structured Programming ʣͰ͸ goto Ͱ είʔϓ͔Β୤ग़Ͱ͖ͳ͍Α͏ʹɺ async let ͸ඞͣείʔϓ ͷதͰղܾ͞ΕΔɻ

Slide 25

Slide 25 text

Structured Concurrency ͷԿ͕͏Ε͍͠ͷ͔?

Slide 26

Slide 26 text

ྫ: ඇಉظॲཧͷΩϟϯηϧ

Slide 27

Slide 27 text

async ؔ਺ͷݺͼग़͠ͷ੍໿ func foo() async -> Int { ... } func bar() async -> Int { await foo() * 2 // ✅ OKɹ } async ؔ਺͸ async ؔ਺ͷதͰ͔͠ݺ΂ͳ͍ɻ

Slide 28

Slide 28 text

async ؔ਺ͷݺͼग़͠ͷ੍໿ func foo() async -> Int { ... } func bar() -> Int { await foo() * 2 // ⛔ ίϯύΠϧΤϥʔ } async ؔ਺͸ async ؔ਺ͷதͰ͔͠ݺ΂ͳ͍ɻ

Slide 29

Slide 29 text

Task Task({ await foo() }) async ؔ਺ͷݺͼग़͠ͷେݩ͸ Task ͷίϯετϥΫλʢΠχ γϟϥΠβʣɻ͢΂ͯͷ async ؔ਺͸ Task ͷ্Ͱ࣮ߦ͞ΕΔɻ

Slide 30

Slide 30 text

Child Task Task({ async let a = foo() // Child Task: foo async let b = bar() // Child Task: bar print(await a + b) }) async let Ͱ͸ฒߦʹ࣮ߦ͞ΕΔ Child Task ͕࡞ΒΕΔɻߏ଄Խ ͞Ε͍ͯΔͷͰ Task ͸πϦʔΛ࡞Δɻ

Slide 31

Slide 31 text

No content

Slide 32

Slide 32 text

No content

Slide 33

Slide 33 text

ඇಉظॲཧͷΩϟϯηϧ let task = Task({ async let a = foo() async let b = bar() print(try await a + b) }) task.cancel() Task Λ cancel ͢Δͱ Task πϦʔશମ͕ҰׅΩϟϯηϧ͞Ε ΔɻඇಉظॲཧͷΩϟϯηϧΛѻ͍΍͍͢ɻ

Slide 34

Slide 34 text

! actor

Slide 35

Slide 35 text

σʔλڝ߹ͱσουϩοΫͷ๷ࢭ

Slide 36

Slide 36 text

σʔλڝ߹ͷྫ class Counter { var count: Int = 0 func increment() -> Int { count += 1 return count } }

Slide 37

Slide 37 text

Χ΢ϯλʹฒߦʹΞΫηε͢Δ৔߹ let counter = Counter() Task { print(counter.increment()) // ? } Task { print(counter.increment()) // ? }

Slide 38

Slide 38 text

Χ΢ϯλʹฒߦʹΞΫηε͢Δ৔߹ let counter = Counter() Task { print(counter.increment()) // 1 } Task { print(counter.increment()) // 2 }

Slide 39

Slide 39 text

Χ΢ϯλʹฒߦʹΞΫηε͢Δ৔߹ let counter = Counter() Task { print(counter.increment()) // 2 } Task { print(counter.increment()) // 1 }

Slide 40

Slide 40 text

Χ΢ϯλʹฒߦʹΞΫηε͢Δ৔߹ let counter = Counter() Task { print(counter.increment()) // 2 } Task { print(counter.increment()) // 2 } ྆ํͷΠϯΫϦϝϯτ͕ߦΘΕͨޙͰ return ͞ΕΔͱ྆ऀͱ΋ 2 Λදࣔ͢Δɻ → σʔλڝ߹

Slide 41

Slide 41 text

ैདྷͷղܾ๏: ϩοΫ class Counter { var count: Int = 0 func increment() -> Int { lock() defer { unlock() } count += 1 return count } } ϩοΫΛ࢖͏ͱεϨουΛϒϩοΫͯ͠͠·͏ύϑΥʔϚϯε্ ͷෆརӹʹՃ͑ͯɺσουϩοΫͷݪҼͱͳΔڪΕ͕͋Δɻ

Slide 42

Slide 42 text

ैདྷͷղܾ๏: γϦΞϧΩϡʔ ΦϖϨʔγϣϯΛγϦΞϧΩϡʔʹೖΕͯɺΩϡʔ͕Ұͭͣͭॱ ൪ʹऔΓग़ͯ͠ॲཧΛ͢Δɻσʔλڝ߹΋σουϩοΫ΋ى͜Β ͳ͍ɻ

Slide 43

Slide 43 text

No content

Slide 44

Slide 44 text

ैདྷͷղܾ๏: γϦΞϧΩϡʔ class Counter { let queue = ... var count: Int = 0 func increment(completion: (Int) -> Void) { queue.async { count += 1 completion(count) } } } ࣮૷͕ෳࡶͩͬͨΓɺΩϡʔΛ࢖͏ͷΛ๨ΕͨΓ͕ͪ͠ɻ

Slide 45

Slide 45 text

// γϦΞϧΩϡʔΛ࢖͏ݱ࣮ͷίʔυ͸ΑΓෳࡶ let queue = DispatchQueue(...) func load(_ url: URL) { queue.sync { // ϝϞϦΩϟογϡΛ୳͢ ... } queue.sync { // σΟεΫΩϟογϡΛ୳͢ ... } queue.async { // ը૾Λμ΢ϯϩʔυ fetch(url) { if { // ੒ޭ: Ωϟογϡʹอଘ // ίʔϧόοΫΛݺͿ ... } else if { // ηογϣϯ੾Ε: queue.async { // ϦϑϨογϡτʔΫϯͰϦτϥΠ } ... } else { // ࣦഊ: ΤϥʔϋϯυϥΛݺͿ ... } } } }

Slide 46

Slide 46 text

actor ʹΑΔղܾ actor Counter { var count: Int = 0 func increment() -> Int { count += 1 return count } } ΩϡʔʹೖΕΔͷͱಉ͡Α͏ͳ͜ͱΛίϯύΠϥ͕ߦͬͯ͘Ε ΔɻύϑΥʔϚϯε΋ΑΓྑ͍ɻ

Slide 47

Slide 47 text

actor ͷϝιουΛ֎͔ΒݟΔͱ actor Counter { ... func increment() async -> Int { ... } } actor ֎෦͔Β͸ async ϝιουʹݟ͑Δɻ

Slide 48

Slide 48 text

actor ͷϝιουΛ֎͔ΒݟΔͱ let counter = Counter() print(await counter.increment())

Slide 49

Slide 49 text

actor ͷϝιουΛத͔ΒݟΔͱ actor Counter { var count: Int = 0 func countUp(amount: Int) -> Int { count += amount return count } func increment() -> Int { countUp(amount: 1) // ಉظݺͼग़͠ } } ֎͔ΒݟͨΒ async ͚ͩͲɺத͔ΒݟͨΒಉظతɻ

Slide 50

Slide 50 text

actor • ΦϖϨʔγϣϯΛΩϡʔʹೖΕͯॱ൪ʹߦ͏ͷͰσʔλڝ߹͕ ى͜Βͳ͍ • actor ͕ࣗಈతʹΦϖϨʔγϣϯΛΩϡʔʹೖΕΔͷͰΩϡʔ ʹೖΕ๨Εͳ͍ • ֎෦͔Β͸ async ʹݟ͑ɺϒϩοΩϯά͕ଘࡏ͠ͳ͍ͷͰσο υϩοΫ͕ى͜Βͳ͍

Slide 51

Slide 51 text

͜Ε͚ͩͰ͸σʔλڝ߹Λ׬શʹ͸๷͛ͳ͍

Slide 52

Slide 52 text

actor ʹ౉ͨ͠ΠϯελϯεΛ֎෦͔Βมߋ actor Foo { func method(x: X) { ... } } let foo = Foo() let x = X() foo.method(x: x) x.value += 1 // कΒΕ͍ͯͳ͍

Slide 53

Slide 53 text

actor ʹ౉ͨ͠ΠϯελϯεΛ֎෦͔Βมߋ actor Foo { func method(x: X) { ... } } let foo = Foo() let x = X() foo.method(x: x) // ⛔ ίϯύΠϧΤϥʔ x.value += 1 ϛϡʔλϒϧΫϥεͷΠϯελϯεΛ౉͢ͱίϯύΠϧΤϥʔɻ ஋ܕ΍ΠϛϡʔλϒϧΫϥεͷΠϯελϯε͸౉ͤΔɻ

Slide 54

Slide 54 text

actor ͔Βड͚औͬͨΠϯελϯεΛ֎෦͔Βมߋ actor Foo { let x = X() func method() -> X { return x } } let foo = Foo() let x = await foo.baz() // ⛔ ίϯύΠϧΤϥʔ x.count += 1 ϛϡʔλϒϧΫϥεͷΠϯελϯεΛฦ͢ͱίϯύΠϧΤϥʔɻ ஋ܕ΍ΠϛϡʔλϒϧΫϥεͷΠϯελϯε͸औΓग़ͤΔɻ

Slide 55

Slide 55 text

ͦͷଞʹɺσουϩοΫΛ׬શʹ๷͙ͨΊʹ ͸ actor ͷ Reentrancy ͕ɾɾɾ ͕࣌ؒ଍Γͳ͍ͷͰৄࡉ͸ Proposal SE-0304 Λޚཡ͍ͩ͘͞ɻ SE-0304 Structured concurrency h)ps:/ /github.com/apple/swi;-evolu=on/blob/main/proposals/0304-structured- concurrency.md

Slide 56

Slide 56 text

·ͱΊ ! async/await " Structured Concurrency # actor ͜ΕΒͷ࢓૊ΈΛ༻͍ͯɺฒߦॲཧͰσʔλڝ߹ͱσουϩοΫ ͕ى͜Βͳ͍͜ͱΛίϯύΠϥ͕อূɻ

Slide 57

Slide 57 text

ࢀߟจݙ 10254 Swi$ concurrency: Behind the scenes h(ps:/ /developer.apple.com/videos/play/wwdc2021/10254/ 10134 Explore structured concurrency in Swi3 h'ps:/ /developer.apple.com/videos/play/wwdc2021/10134/ 10133 Protect mutable state with Swi2 actors h&ps:/ /developer.apple.com/videos/play/wwdc2021/10133/ 10132 Meet async/await in Swi. h'ps:/ /developer.apple.com/videos/play/wwdc2021/10132/ WWDC 2021 Sessions SE-0317 async let bindings h*ps:/ /github.com/apple/swi<-evolu>on/blob/main/proposals/0317-async-let.md SE-0316 Global actors h*ps:/ /github.com/apple/swi<-evolu>on/blob/main/proposals/0316-global-actors.md SE-0306 Actors h)ps:/ /github.com/apple/swi;-evolu=on/blob/main/proposals/0306-actors.md SE-0304 Structured concurrency h)ps:/ /github.com/apple/swi;-evolu=on/blob/main/proposals/0304-structured- concurrency.md SE-0302 Sendable and @Sendable closures h)ps:/ /github.com/apple/swi;-evolu=on/blob/main/proposals/0302- concurrent-value-and-concurrent-closures.md SE-0296 Async/await h*ps:/ /github.com/apple/swi<-evolu>on/blob/main/proposals/0296-async-await.md Swi$ Evolu+on Proposals