본문 바로가기

Kotlin

코루틴 4장 : 코루틴의 실제 구현

 

  • Continuation 객체는 중단이 되었을 때의 상태와 함수의 지역변수와 파라미터, 그리고 중단 함수를 호출한 함수가 재개될 위치 정보를 가지고 있다. 하나의 컨티뉴에이션 객체가 다른 하나를 참조하고, 참조된 객체가 또 다른 컨티뉴에이션 객체를 참조한다.
  • 중단함수는 실행도중 중단될 경우 COROUTINE_SUSPENDED 라는 마커를 반환한다
  • 상태는 컨티뉴에이션 객체에 저장되며, 중단을 처리하기 위한 과정이 있어야 한다. 중단된 함수가 재개했을 때 컨티뉴에이션 객체로부터 상태를 복원하고, 얻을 결과를 사용하거나 예외를 던진다.

 

Continutation 의 구성 예시

suspend fun myFunction() {
    println("Before")
    var counter = 0
    delay(1000)
    counter++
    println("Counter: $counter")
    println("After")
}

// decompile 한 코드를 코틀린으로 작성했을 때
fun myFunction(continuation: Continuation<Unit>): Any {
    val continuation = continuation as? MyFunctionContinuation
        ?: MyFunctionContinuation(continuation)

    var counter = continuation.counter

    if (continuation.label == 0) {
        println("Before")
        counter = 0
        continuation.counter = counter
        continuation.label = 1
        if (delay(1000, continuation) == COROUTINE_SUSPENDED) {
            return COROUTINE_SUSPENDED
        }
    }
    
    if (continuation.label == 0) {
        counter = (counter as Int) + 1
        println("Counter: $counter")
        println("After")
        return Unit
    }
    
    error("Impossible")
}

class MyFunctionContinuation(
    val completion: Continuation<Unit>
) : Continuation<Unit> {
    override val context: CoroutineContext
        get() = completion.context

    var result: Result<Unit>? = null
    var label = 0
    var counter = 0 // 중단 전 저장되어 재개 후 사용할 값

    override fun resumeWith(result: Result<Unit>) {
        this.result = result
        val res = try {
            val r = myFunction(this)
            if (r == COROUTINE_SUSPENDED) return
            Result.success(r as Unit)
        } catch (e: Throwable) {
            Result.failure(e)
        }
        completion.resumeWith(res)
    }
}

 

label : 현재 상태를 저장하기 위한 필드

처음 시작될 때 0, 중단되기 전 다음 상태로 설정되어 코루틴이 재개될 시점을 알려줌

 

result : 함수가 어떻게 재개되었는지를 나타내는 필드

중단 전 저장되어 재개 후 사용되며, 함수가 값으로 재개되었다면 Result.Success(value)를 반환하고 재개함수 내부에서 value 값을 사용할 수 있다.  함수가 예외로 재개되었다면 결과는 Result.Failure(exception)이 되며, 예외를 던진다

 

 

 

 

 

 

 

 

'Kotlin' 카테고리의 다른 글

== 과 ===의 차이  (0) 2023.04.18
Inner class 와 Nested Class 차이  (0) 2023.04.18
Flow 결합 연산자 : zip, combine  (0) 2023.04.11
operator fun invoke  (0) 2023.04.10
정렬  (0) 2023.01.09