Slide 1

Slide 1 text

Sato Shun Tapple, inc. Kotlin Nativeͷfrozenͱ ฒߦॲཧʹ͍ͭͯ

Slide 2

Slide 2 text

લఏ஌ࣝ • ଟগͷKotlinͷ஌ࣝ

Slide 3

Slide 3 text

໨࣍ • ͦ΋ͦ΋ͷฒߦॲཧͷ೉͍͠ॴ • Kotlin NativeͰ͸ͲͷΑ͏ʹͯ͠ɺ͜ͷ՝୊Λղܾ͔ͨ͠ • Kotlin Nativeͷฒߦॲཧ

Slide 4

Slide 4 text

ฒߦॲཧͷ೉͍͠ॴ • mutableͳΠϯελϯεΛෳ਺εϨου͔Βૢ࡞͢Δ࣌ • synchronized΍ɺmutexͳͲͷϩοΫΛ࢖͏ • AtomicܥͷAPIΛ࢖͏ • બ୒ࢶ΋ଟ͘ɺద੾ʹॻ͘͜ͱ͸೉͍͠ • ·ͨόά͕ى͖ͨ࣌ʹ࠶ݱੑ͕௿͘ɺݪҼͷಛఆ͕ࠔ೉

Slide 5

Slide 5 text

ฒߦॲཧͷ೉͍͠ॴ • ͦ͜ͰKotlin NativeʢiOSଆʣͰ͸ɺmutableͳঢ়ଶͷΠϯελϯεʹର͠ ͯɺͱ͋Δ੍໿Λઃ͚Δ͜ͱͰղܾΛ໨ࢦͨ͠

Slide 6

Slide 6 text

shared XOR mutable੍໿ • ฒߦॲཧͰ໰୊͕ग़Δɺshared ͔ͭ mutableͳঢ়ଶΛڐՄ͠ͳ͍ͱ͍͏੍ ໿ • RustͳͲͰ΋࢖ΘΕ͍ͯΔ੍໿ʢΒ͍͠ʣ • ͜ͷ੍໿Λຬͨͨ͢ΊʹɺKotlin NativeͰ͸ frozenঢ়ଶ Λಋೖͨ͠

Slide 7

Slide 7 text

frozenঢ়ଶ? • ͦͷΠϯελϯε͕immutableͰ͋Δ͜ͱΛอূ͢Δ

Slide 8

Slide 8 text

frozenঢ়ଶ? • ͦͷΠϯελϯε͕immutableͰ͋Δ͜ͱΛอূ͢Δ /** * Freezes object subgraph reachable from this object. Frozen objects can be freely * shared between threads/workers. * * @throws FreezingException if freezing is not possible * @return the object itself * @see ensureNeverFrozen */ public fun T.freeze(): T

Slide 9

Slide 9 text

frozenঢ়ଶ? • ͦͷΠϯελϯε͕immutableͰ͋Δ͜ͱΛอূ͢Δ • freezeͨ͠ΠϯελϯεΛมߋ͠Α͏ͱ͢ΔͱɺΫϥογϡ͢Δ • ଞͷεϨουͱ҆શʹڞ༗͢Δ͜ͱ͕ग़དྷΔ

Slide 10

Slide 10 text

frozenঢ়ଶ? • ͦͷΠϯελϯε͕immutableͰ͋Δ͜ͱΛอূ͢Δ • freezeͨ͠ΠϯελϯεΛมߋ͠Α͏ͱ͢ΔͱɺΫϥογϡ͢Δ • ଞͷεϨουͱ҆શʹڞ༗͢Δ͜ͱ͕ग़དྷΔ /** * Checks if given object is null or frozen or permanent (i.e. instantiated at compile-time). * * @return true if given object is null or frozen or permanent */ public val Any ?. isFrozen

Slide 11

Slide 11 text

frozenঢ়ଶ? • ͦͷΠϯελϯε͕immutableͰ͋Δ͜ͱΛอূ͢Δ • freezeͨ͠ΠϯελϯεΛมߋ͠Α͏ͱ͢ΔͱɺΫϥογϡ͢Δ • ଞͷεϨουͱ҆શʹڞ༗͢Δ͜ͱ͕ग़དྷΔ • unfreeze͸ଘࡏ͠ͳ͍

Slide 12

Slide 12 text

val sample = Sample(3) sample.i + + sample.freeze() sample.i + +

Slide 13

Slide 13 text

val sample = Sample(3) sample.i + + sample.freeze() sample.i + + Uncaught Kotlin exception: kotlin.native.concurrent.InvalidMutabilityException

Slide 14

Slide 14 text

KMMͷfrozenͷ໰୊఺ • JVM(Android)ͱNative(iOS)Ͱڍಈ͕ҟͳΔ • JVMʹ͸frozenঢ়ଶͱ͍͏֓೦͸ͳ͍ • AndroidͰ͸ಈ͘ɺ͔͠͠iOSͰ͸Ϋϥογϡ͢ΔɻΈ͍ͨͳ͜ͱ͕ى͜ ΔՄೳੑ͕͋Δ • ·ͨɺKotlin NativeͰ͸freezeΛ໌ࣔతʹݺ͹ͳͯ͘΋ɺ҉໧తʹfreeze͠ ͯ͠·͏ύλʔϯ͕͋Δ

Slide 15

Slide 15 text

҉໧తͳfreeze • objectɺcompanion objectͳͲ͸ɺࣗಈͰfreeze͢Δ࢓༷ʹͳ͍ͬͯΔ

Slide 16

Slide 16 text

object DefaultGlobalState { private var i = 5 fun countUp() { i ++ } }

Slide 17

Slide 17 text

object DefaultGlobalState { private var i = 5 fun countUp() { i ++ } } Uncaught Kotlin exception: kotlin.native.concurrent.InvalidMutabilityException

Slide 18

Slide 18 text

@ThreadLocal object DefaultGlobalState { private var i = 5 fun countUp() { i ++ } }

Slide 19

Slide 19 text

͜͜·Ͱͷ·ͱΊ • shared XOR mutableΛຬͨͨ͢Ίʹfrozen͕ಋೖ͞Εͨ • frozenঢ়ଶʹ͢Δ͜ͱͰɺimmutableͳঢ়ଶΛදݱͰ͖Δ • ͜Ε͸ฒྻॲཧΛ҆શʹѻ͏͜ͱ͕ग़དྷΔ • ͔͠͠ɺ҉໧తͳfrozenͳͲͰɺiOS͚ͩಈ͔ͳ͍Մೳੑ͕͋Δ

Slide 20

Slide 20 text

Kotlin Nativeͷฒߦॲཧ • ௿ϨϕϧAPIͱͯ͠ɺWorkerΫϥε͕༻ҙ͞Ε͍ͯΔ • JavaͰ͍͏ͱ͜ΖͷThreadΫϥε • Kotlin NativeͰ͸ɺجຊతʹεϨου͕มΘΔ৔߹ɺfrozenঢ়ଶʹͯ͠ immutableʹ͢Δඞཁ͕͋Δ

Slide 21

Slide 21 text

val worker = Worker.start() worker.execute(TransferMode.SAFE, { … }) { … }

Slide 22

Slide 22 text

val worker = Worker.start() worker.execute(TransferMode.SAFE, { … }) { … } public fun execute( mode: TransferMode, producer: () -> T1, @VolatileLambda job: (T1) - > T2 ): Future

Slide 23

Slide 23 text

data class Sample(var i: Int) val sample = Sample(1)

Slide 24

Slide 24 text

data class Sample(var i: Int) val sample = Sample(1) worker.execute(TransferMode.SAFE, { sample }) { println(it) }

Slide 25

Slide 25 text

data class Sample(var i: Int) val sample = Sample(1) worker.execute(TransferMode.SAFE, { sample }) { println(it) } Uncaught Kotlin exception: kotlin.IllegalStateException: Illegal transfer state

Slide 26

Slide 26 text

data class Sample(var i: Int) val sample = Sample(1) worker.execute(TransferMode.SAFE, { sample.freeze() }) { println(it) }

Slide 27

Slide 27 text

data class Sample(var i: Int) val sample = Sample(1) val sample2 = Sample(2)

Slide 28

Slide 28 text

data class Sample(var i: Int) val sample = Sample(1) val sample2 = Sample(2) worker.execute(TransferMode.SAFE, { sample.freeze() }) { println(it) }

Slide 29

Slide 29 text

data class Sample(var i: Int) val sample = Sample(1) val sample2 = Sample(2) fun background(block: () -> Unit) { worker.execute(TransferMode.SAFE, { block.freeze() }) { it() } }

Slide 30

Slide 30 text

data class Sample(var i: Int) val sample = Sample(1) val sample2 = Sample(2) background { println(sample) println(sample2) } fun background(block: () -> Unit) { worker.execute(TransferMode.SAFE, { block.freeze() }) { it() } }

Slide 31

Slide 31 text

data class Sample(var i: Int) val sample = Sample(1) val sample2 = Sample(2) background { println(sample) println(sample2) } fun background(block: () -> Unit) { worker.execute(TransferMode.SAFE, { block.freeze() }) { it() } } sampleɺsample2ຊମΛfreeze͍ͯ͠ͳ͍ εϨου͕มΘΔ৔߹͸ɺfreeze͠ͳ͍ͱ͍͚ͳ͍ͷͰ͸?

Slide 32

Slide 32 text

data class Sample(var i: Int) val sample = Sample(1) val sample2 = Sample(2) background { println(sample) println(sample2) } fun background(block: () -> Unit) { worker.execute(TransferMode.SAFE, { block.freeze() }) { it() } } sampleɺsample2ຊମΛfreeze͍ͯ͠ͳ͍ εϨου͕มΘΔ৔߹͸ɺfreeze͠ͳ͍ͱ͍͚ͳ͍ͷͰ͸? ϥϜμຊମΛfreeze͢Δͱɺ ͦͷϥϜμ͕ࢀর͍ͯ͠Δม਺΋࿈࠯తʹfreeze͞ΕΔ

Slide 33

Slide 33 text

Kotlin Nativeͷฒߦॲཧͷ·ͱΊ • Kotlin Nativeʹ͸Workerͱ͍͏௿ϨϕϧAPI͕༻ҙ͞Ε͍ͯΔ • εϨουؒΛލ͙ͱ͖͸ɺfreeze͢Δඞཁ͕͋Δ • ͋ΔΠϯελϯεΛfreeze͢Δͱɺࢀর͞Ε͍ͯΔΠϯελϯε΋࿈࠯త ʹfreeze͢Δ

Slide 34

Slide 34 text

͓·͚: Coroutineʹ͍ͭͯ • ࣮ࡍͷ։ൃͰ͸ɺCoroutineͳͲͷߴϨϕϧͳAPIΛ࢖͏͜ͱ͕ଟ͍ • ݱঢ়ɺKotlin Nativeʹ͓͚ΔCoroutine͸ʮ୯ҰεϨουʹͷΈରԠͨ͠௨ ৗόʔδϣϯʯͱʮෳ਺εϨουʹରԠͨ͠όʔδϣϯʯ͕͋Δ

Slide 35

Slide 35 text

val sample = Sample("1") println(sample.isFrozen) withContext(Dispatchers.Default) { println(sample.isFrozen) }

Slide 36

Slide 36 text

val sample = Sample("1") println(sample.isFrozen) withContext(Dispatchers.Default) { println(sample.isFrozen) } ୯ҰεϨουόʔδϣϯͷCoroutineͷ৔߹͸ɺisFrozen͸falseɺ ෳ਺εϨουόʔδϣϯͷCoroutineͷ৔߹͸ɺisFrozen͸true

Slide 37

Slide 37 text

͝ਗ਼ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠