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

Kotlin Nativeにおけるfrozen状態と並行処理について

Kotlin Nativeにおけるfrozen状態と並行処理について

Flutter × Kotlin Multiplatform by CyberAgent #2の登壇資料です。

Sato Shun

March 02, 2021
Tweet

More Decks by Sato Shun

Other Decks in Programming

Transcript

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

    View full-size slide

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

    View full-size slide

  3. ໨࣍
    • ͦ΋ͦ΋ͷฒߦॲཧͷ೉͍͠ॴ

    • Kotlin NativeͰ͸ͲͷΑ͏ʹͯ͠ɺ͜ͷ՝୊Λղܾ͔ͨ͠

    • Kotlin Nativeͷฒߦॲཧ

    View full-size slide

  4. ฒߦॲཧͷ೉͍͠ॴ
    • mutableͳΠϯελϯεΛෳ਺εϨου͔Βૢ࡞͢Δ࣌

    • synchronized΍ɺmutexͳͲͷϩοΫΛ࢖͏

    • AtomicܥͷAPIΛ࢖͏

    • બ୒ࢶ΋ଟ͘ɺద੾ʹॻ͘͜ͱ͸೉͍͠

    • ·ͨόά͕ى͖ͨ࣌ʹ࠶ݱੑ͕௿͘ɺݪҼͷಛఆ͕ࠔ೉

    View full-size slide

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

    View full-size slide

  6. shared XOR mutable੍໿
    • ฒߦॲཧͰ໰୊͕ग़Δɺshared ͔ͭ mutableͳঢ়ଶΛڐՄ͠ͳ͍ͱ͍͏੍
    ໿

    • RustͳͲͰ΋࢖ΘΕ͍ͯΔ੍໿ʢΒ͍͠ʣ

    • ͜ͷ੍໿Λຬͨͨ͢ΊʹɺKotlin NativeͰ͸ frozenঢ়ଶ Λಋೖͨ͠

    View full-size slide

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

    View full-size slide

  8. 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

    View full-size slide

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

    • freezeͨ͠ΠϯελϯεΛมߋ͠Α͏ͱ͢ΔͱɺΫϥογϡ͢Δ

    • ଞͷεϨουͱ҆શʹڞ༗͢Δ͜ͱ͕ग़དྷΔ

    View full-size slide

  10. 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

    View full-size slide

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

    • freezeͨ͠ΠϯελϯεΛมߋ͠Α͏ͱ͢ΔͱɺΫϥογϡ͢Δ

    • ଞͷεϨουͱ҆શʹڞ༗͢Δ͜ͱ͕ग़དྷΔ

    • unfreeze͸ଘࡏ͠ͳ͍

    View full-size slide

  12. val sample = Sample(3)

    sample.i
    + +


    sample.freeze()

    sample.i
    + +

    View full-size slide

  13. val sample = Sample(3)

    sample.i
    + +


    sample.freeze()

    sample.i
    + +
    Uncaught Kotlin exception: kotlin.native.concurrent.InvalidMutabilityException

    View full-size slide

  14. KMMͷfrozenͷ໰୊఺
    • JVM(Android)ͱNative(iOS)Ͱڍಈ͕ҟͳΔ

    • JVMʹ͸frozenঢ়ଶͱ͍͏֓೦͸ͳ͍

    • AndroidͰ͸ಈ͘ɺ͔͠͠iOSͰ͸Ϋϥογϡ͢ΔɻΈ͍ͨͳ͜ͱ͕ى͜
    ΔՄೳੑ͕͋Δ

    • ·ͨɺKotlin NativeͰ͸freezeΛ໌ࣔతʹݺ͹ͳͯ͘΋ɺ҉໧తʹfreeze͠
    ͯ͠·͏ύλʔϯ͕͋Δ

    View full-size slide

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

    View full-size slide

  16. object DefaultGlobalState {

    private var i = 5

    fun countUp() {

    i
    ++


    }

    }

    View full-size slide

  17. object DefaultGlobalState {

    private var i = 5

    fun countUp() {

    i
    ++


    }

    }
    Uncaught Kotlin exception: kotlin.native.concurrent.InvalidMutabilityException

    View full-size slide

  18. @ThreadLocal

    object DefaultGlobalState {

    private var i = 5

    fun countUp() {

    i
    ++


    }

    }

    View full-size slide

  19. ͜͜·Ͱͷ·ͱΊ
    • shared XOR mutableΛຬͨͨ͢Ίʹfrozen͕ಋೖ͞Εͨ

    • frozenঢ়ଶʹ͢Δ͜ͱͰɺimmutableͳঢ়ଶΛදݱͰ͖Δ

    • ͜Ε͸ฒྻॲཧΛ҆શʹѻ͏͜ͱ͕ग़དྷΔ

    • ͔͠͠ɺ҉໧తͳfrozenͳͲͰɺiOS͚ͩಈ͔ͳ͍Մೳੑ͕͋Δ

    View full-size slide

  20. Kotlin Nativeͷฒߦॲཧ
    • ௿ϨϕϧAPIͱͯ͠ɺWorkerΫϥε͕༻ҙ͞Ε͍ͯΔ

    • JavaͰ͍͏ͱ͜ΖͷThreadΫϥε

    • Kotlin NativeͰ͸ɺجຊతʹεϨου͕มΘΔ৔߹ɺfrozenঢ়ଶʹͯ͠
    immutableʹ͢Δඞཁ͕͋Δ

    View full-size slide

  21. val worker = Worker.start()

    worker.execute(TransferMode.SAFE, { … }) {



    }

    View full-size slide

  22. val worker = Worker.start()

    worker.execute(TransferMode.SAFE, { … }) {



    }
    public fun execute(

    mode: TransferMode,

    producer: ()
    ->
    T1,

    @VolatileLambda job: (T1)
    -
    >
    T2

    ): Future

    View full-size slide

  23. data class Sample(var i: Int)

    val sample = Sample(1)

    View full-size slide

  24. data class Sample(var i: Int)

    val sample = Sample(1)

    worker.execute(TransferMode.SAFE, { sample }) {

    println(it)

    }

    View full-size slide

  25. 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

    View full-size slide

  26. data class Sample(var i: Int)

    val sample = Sample(1)

    worker.execute(TransferMode.SAFE, { sample.freeze() }) {

    println(it)

    }

    View full-size slide

  27. data class Sample(var i: Int)

    val sample = Sample(1)

    val sample2 = Sample(2)

    View full-size slide

  28. data class Sample(var i: Int)

    val sample = Sample(1)

    val sample2 = Sample(2)

    worker.execute(TransferMode.SAFE, { sample.freeze() }) {

    println(it)

    }

    View full-size slide

  29. 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()

    }

    }

    View full-size slide

  30. 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()

    }

    }

    View full-size slide

  31. 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͠ͳ͍ͱ͍͚ͳ͍ͷͰ͸?

    View full-size slide

  32. 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͞ΕΔ

    View full-size slide

  33. Kotlin Nativeͷฒߦॲཧͷ·ͱΊ
    • Kotlin Nativeʹ͸Workerͱ͍͏௿ϨϕϧAPI͕༻ҙ͞Ε͍ͯΔ

    • εϨουؒΛލ͙ͱ͖͸ɺfreeze͢Δඞཁ͕͋Δ

    • ͋ΔΠϯελϯεΛfreeze͢Δͱɺࢀর͞Ε͍ͯΔΠϯελϯε΋࿈࠯త
    ʹfreeze͢Δ

    View full-size slide

  34. ͓·͚: Coroutineʹ͍ͭͯ
    • ࣮ࡍͷ։ൃͰ͸ɺCoroutineͳͲͷߴϨϕϧͳAPIΛ࢖͏͜ͱ͕ଟ͍

    • ݱঢ়ɺKotlin Nativeʹ͓͚ΔCoroutine͸ʮ୯ҰεϨουʹͷΈରԠͨ͠௨
    ৗόʔδϣϯʯͱʮෳ਺εϨουʹରԠͨ͠όʔδϣϯʯ͕͋Δ

    View full-size slide

  35. val sample = Sample("1")

    println(sample.isFrozen)

    withContext(Dispatchers.Default) {

    println(sample.isFrozen)

    }

    View full-size slide

  36. val sample = Sample("1")

    println(sample.isFrozen)

    withContext(Dispatchers.Default) {

    println(sample.isFrozen)

    }
    ୯ҰεϨουόʔδϣϯͷCoroutineͷ৔߹͸ɺisFrozen͸falseɺ

    ෳ਺εϨουόʔδϣϯͷCoroutineͷ৔߹͸ɺisFrozen͸true

    View full-size slide

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

    View full-size slide